Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2649d102b8 | ||
|
|
1517c63a78 | ||
|
|
5fbe88ab40 |
@@ -59,7 +59,7 @@ export type CompilerDiagnosticDetail =
|
||||
*/
|
||||
{
|
||||
kind: 'error';
|
||||
loc: SourceLocation | null;
|
||||
loc: SourceLocation;
|
||||
message: string;
|
||||
};
|
||||
|
||||
@@ -100,12 +100,6 @@ export class CompilerDiagnostic {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
static create(
|
||||
options: Omit<CompilerDiagnosticOptions, 'details'>,
|
||||
): CompilerDiagnostic {
|
||||
return new CompilerDiagnostic({...options, details: []});
|
||||
}
|
||||
|
||||
get category(): CompilerDiagnosticOptions['category'] {
|
||||
return this.options.category;
|
||||
}
|
||||
@@ -119,11 +113,6 @@ export class CompilerDiagnostic {
|
||||
return this.options.suggestions;
|
||||
}
|
||||
|
||||
withDetail(detail: CompilerDiagnosticDetail): CompilerDiagnostic {
|
||||
this.options.details.push(detail);
|
||||
return this;
|
||||
}
|
||||
|
||||
primaryLocation(): SourceLocation | null {
|
||||
return this.options.details.filter(d => d.kind === 'error')[0]?.loc ?? null;
|
||||
}
|
||||
@@ -138,7 +127,7 @@ export class CompilerDiagnostic {
|
||||
switch (detail.kind) {
|
||||
case 'error': {
|
||||
const loc = detail.loc;
|
||||
if (loc == null || typeof loc === 'symbol') {
|
||||
if (typeof loc === 'symbol') {
|
||||
continue;
|
||||
}
|
||||
let codeFrame: string;
|
||||
|
||||
@@ -9,7 +9,6 @@ import {NodePath, Scope} from '@babel/traverse';
|
||||
import * as t from '@babel/types';
|
||||
import invariant from 'invariant';
|
||||
import {
|
||||
CompilerDiagnostic,
|
||||
CompilerError,
|
||||
CompilerSuggestionOperation,
|
||||
ErrorSeverity,
|
||||
@@ -105,18 +104,12 @@ export function lower(
|
||||
if (param.isIdentifier()) {
|
||||
const binding = builder.resolveIdentifier(param);
|
||||
if (binding.kind !== 'Identifier') {
|
||||
builder.errors.pushDiagnostic(
|
||||
CompilerDiagnostic.create({
|
||||
category: 'Could not find binding',
|
||||
description: `[BuildHIR] Could not find binding for param \`${param.node.name}\``,
|
||||
severity: ErrorSeverity.Invariant,
|
||||
suggestions: null,
|
||||
}).withDetail({
|
||||
kind: 'error',
|
||||
loc: param.node.loc ?? null,
|
||||
message: 'Could not find binding',
|
||||
}),
|
||||
);
|
||||
builder.errors.push({
|
||||
reason: `(BuildHIR::lower) Could not find binding for param \`${param.node.name}\``,
|
||||
severity: ErrorSeverity.Invariant,
|
||||
loc: param.node.loc ?? null,
|
||||
suggestions: null,
|
||||
});
|
||||
return;
|
||||
}
|
||||
const place: Place = {
|
||||
@@ -170,18 +163,12 @@ export function lower(
|
||||
'Assignment',
|
||||
);
|
||||
} else {
|
||||
builder.errors.pushDiagnostic(
|
||||
CompilerDiagnostic.create({
|
||||
category: `Handle ${param.node.type} parameters`,
|
||||
description: `[BuildHIR] Add support for ${param.node.type} parameters`,
|
||||
severity: ErrorSeverity.Todo,
|
||||
suggestions: null,
|
||||
}).withDetail({
|
||||
kind: 'error',
|
||||
loc: param.node.loc ?? null,
|
||||
message: 'Unsupported parameter type',
|
||||
}),
|
||||
);
|
||||
builder.errors.push({
|
||||
reason: `(BuildHIR::lower) Handle ${param.node.type} params`,
|
||||
severity: ErrorSeverity.Todo,
|
||||
loc: param.node.loc ?? null,
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -201,18 +188,13 @@ export function lower(
|
||||
lowerStatement(builder, body);
|
||||
directives = body.get('directives').map(d => d.node.value.value);
|
||||
} else {
|
||||
builder.errors.pushDiagnostic(
|
||||
CompilerDiagnostic.create({
|
||||
severity: ErrorSeverity.InvalidJS,
|
||||
category: `Unexpected function body kind`,
|
||||
description: `Expected function body to be an expression or a block statement, got \`${body.type}\``,
|
||||
suggestions: null,
|
||||
}).withDetail({
|
||||
kind: 'error',
|
||||
loc: body.node.loc ?? null,
|
||||
message: 'Expected a block statement or expression',
|
||||
}),
|
||||
);
|
||||
builder.errors.push({
|
||||
severity: ErrorSeverity.InvalidJS,
|
||||
reason: `Unexpected function body kind`,
|
||||
description: `Expected function body to be an expression or a block statement, got \`${body.type}\``,
|
||||
loc: body.node.loc ?? null,
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
|
||||
if (builder.errors.hasErrors()) {
|
||||
|
||||
@@ -345,51 +345,6 @@ export function* eachPatternOperand(pattern: Pattern): Iterable<Place> {
|
||||
}
|
||||
}
|
||||
|
||||
export function* eachPatternItem(
|
||||
pattern: Pattern,
|
||||
): Iterable<Place | SpreadPattern> {
|
||||
switch (pattern.kind) {
|
||||
case 'ArrayPattern': {
|
||||
for (const item of pattern.items) {
|
||||
if (item.kind === 'Identifier') {
|
||||
yield item;
|
||||
} else if (item.kind === 'Spread') {
|
||||
yield item;
|
||||
} else if (item.kind === 'Hole') {
|
||||
continue;
|
||||
} else {
|
||||
assertExhaustive(
|
||||
item,
|
||||
`Unexpected item kind \`${(item as any).kind}\``,
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'ObjectPattern': {
|
||||
for (const property of pattern.properties) {
|
||||
if (property.kind === 'ObjectProperty') {
|
||||
yield property.place;
|
||||
} else if (property.kind === 'Spread') {
|
||||
yield property;
|
||||
} else {
|
||||
assertExhaustive(
|
||||
property,
|
||||
`Unexpected item kind \`${(property as any).kind}\``,
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(
|
||||
pattern,
|
||||
`Unexpected pattern kind \`${(pattern as any).kind}\``,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function mapInstructionLValues(
|
||||
instr: Instruction,
|
||||
fn: (place: Place) => Place,
|
||||
|
||||
@@ -36,8 +36,8 @@ import {
|
||||
ValueReason,
|
||||
} from '../HIR';
|
||||
import {
|
||||
eachInstructionValueLValue,
|
||||
eachInstructionValueOperand,
|
||||
eachPatternItem,
|
||||
eachTerminalOperand,
|
||||
eachTerminalSuccessor,
|
||||
} from '../HIR/visitors';
|
||||
@@ -1864,34 +1864,19 @@ function computeSignatureForInstruction(
|
||||
break;
|
||||
}
|
||||
case 'Destructure': {
|
||||
for (const patternItem of eachPatternItem(value.lvalue.pattern)) {
|
||||
const place =
|
||||
patternItem.kind === 'Identifier' ? patternItem : patternItem.place;
|
||||
if (isPrimitiveType(place.identifier)) {
|
||||
for (const patternLValue of eachInstructionValueLValue(value)) {
|
||||
if (isPrimitiveType(patternLValue.identifier)) {
|
||||
effects.push({
|
||||
kind: 'Create',
|
||||
into: place,
|
||||
into: patternLValue,
|
||||
value: ValueKind.Primitive,
|
||||
reason: ValueReason.Other,
|
||||
});
|
||||
} else if (patternItem.kind === 'Identifier') {
|
||||
} else {
|
||||
effects.push({
|
||||
kind: 'CreateFrom',
|
||||
from: value.value,
|
||||
into: place,
|
||||
});
|
||||
} else {
|
||||
// Spread creates a new object/array that captures from the RValue
|
||||
effects.push({
|
||||
kind: 'Create',
|
||||
into: place,
|
||||
reason: ValueReason.Other,
|
||||
value: ValueKind.Mutable,
|
||||
});
|
||||
effects.push({
|
||||
kind: 'Capture',
|
||||
from: value.value,
|
||||
into: place,
|
||||
into: patternLValue,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,12 +360,6 @@ function* generateInstructionTypes(
|
||||
value: makePropertyLiteral(propertyName),
|
||||
},
|
||||
});
|
||||
} else if (item.kind === 'Spread') {
|
||||
// Array pattern spread always creates an array
|
||||
yield equation(item.place.identifier.type, {
|
||||
kind: 'Object',
|
||||
shapeId: BuiltInArrayId,
|
||||
});
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {CompilerDiagnostic, CompilerError, Effect, ErrorSeverity} from '..';
|
||||
import {CompilerError, Effect} from '..';
|
||||
import {HIRFunction, IdentifierId, Place} from '../HIR';
|
||||
import {
|
||||
eachInstructionLValue,
|
||||
@@ -28,19 +28,16 @@ export function validateLocalsNotReassignedAfterRender(fn: HIRFunction): void {
|
||||
false,
|
||||
);
|
||||
if (reassignment !== null) {
|
||||
const errors = new CompilerError();
|
||||
errors.pushDiagnostic(
|
||||
CompilerDiagnostic.create({
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
category: 'Cannot reassign a variable after render completes',
|
||||
description: `Reassigning ${reassignment.identifier.name != null && reassignment.identifier.name.kind === 'named' ? `variable \`${reassignment.identifier.name.value}\`` : 'a variable'} after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead`,
|
||||
}).withDetail({
|
||||
kind: 'error',
|
||||
loc: reassignment.loc,
|
||||
message: 'Cannot reassign variable after render completes',
|
||||
}),
|
||||
);
|
||||
throw errors;
|
||||
CompilerError.throwInvalidReact({
|
||||
reason:
|
||||
'Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead',
|
||||
description:
|
||||
reassignment.identifier.name !== null &&
|
||||
reassignment.identifier.name.kind === 'named'
|
||||
? `Variable \`${reassignment.identifier.name.value}\` cannot be reassigned after render`
|
||||
: '',
|
||||
loc: reassignment.loc,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {CompilerDiagnostic, CompilerError, Effect, ErrorSeverity} from '..';
|
||||
import {CompilerError, Effect, ErrorSeverity} from '..';
|
||||
import {
|
||||
FunctionEffect,
|
||||
HIRFunction,
|
||||
@@ -57,24 +57,16 @@ export function validateNoFreezingKnownMutableFunctions(
|
||||
if (operand.effect === Effect.Freeze) {
|
||||
const effect = contextMutationEffects.get(operand.identifier.id);
|
||||
if (effect != null) {
|
||||
errors.pushDiagnostic(
|
||||
CompilerDiagnostic.create({
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
category: 'Cannot modify local variables after render completes',
|
||||
description: `This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead`,
|
||||
})
|
||||
.withDetail({
|
||||
kind: 'error',
|
||||
loc: operand.loc,
|
||||
message:
|
||||
'This function may (indirectly) reassign or modify local variables after render',
|
||||
})
|
||||
.withDetail({
|
||||
kind: 'error',
|
||||
loc: effect.loc,
|
||||
message: 'This modifies a local variable',
|
||||
}),
|
||||
);
|
||||
errors.push({
|
||||
reason: `This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead`,
|
||||
loc: operand.loc,
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
});
|
||||
errors.push({
|
||||
reason: `The function modifies a local variable here`,
|
||||
loc: effect.loc,
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {CompilerDiagnostic, CompilerError, ErrorSeverity} from '..';
|
||||
import {CompilerError, ErrorSeverity} from '..';
|
||||
import {HIRFunction} from '../HIR';
|
||||
import {getFunctionCallSignature} from '../Inference/InferReferenceEffects';
|
||||
import {Result} from '../Utils/Result';
|
||||
@@ -34,22 +34,17 @@ export function validateNoImpureFunctionsInRender(
|
||||
callee.identifier.type,
|
||||
);
|
||||
if (signature != null && signature.impure === true) {
|
||||
errors.pushDiagnostic(
|
||||
CompilerDiagnostic.create({
|
||||
category: 'Cannot call impure function during render',
|
||||
description:
|
||||
(signature.canonicalName != null
|
||||
? `\`${signature.canonicalName}\` is an impure function. `
|
||||
: '') +
|
||||
'Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)',
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
suggestions: null,
|
||||
}).withDetail({
|
||||
kind: 'error',
|
||||
loc: callee.loc,
|
||||
message: 'Cannot call impure function',
|
||||
}),
|
||||
);
|
||||
errors.push({
|
||||
reason:
|
||||
'Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)',
|
||||
description:
|
||||
signature.canonicalName != null
|
||||
? `\`${signature.canonicalName}\` is an impure function whose results may change on every call`
|
||||
: null,
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
loc: callee.loc,
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {CompilerDiagnostic, CompilerError, ErrorSeverity} from '..';
|
||||
import {CompilerError, ErrorSeverity} from '..';
|
||||
import {BlockId, HIRFunction} from '../HIR';
|
||||
import {Result} from '../Utils/Result';
|
||||
import {retainWhere} from '../Utils/utils';
|
||||
@@ -34,17 +34,11 @@ export function validateNoJSXInTryStatement(
|
||||
switch (value.kind) {
|
||||
case 'JsxExpression':
|
||||
case 'JsxFragment': {
|
||||
errors.pushDiagnostic(
|
||||
CompilerDiagnostic.create({
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
category: 'Avoid constructing JSX within try/catch',
|
||||
description: `React does not immediately render components when JSX is rendered, so any errors from this component will not be caught by the try/catch. To catch errors in rendering a given component, wrap that component in an error boundary. (https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary)`,
|
||||
}).withDetail({
|
||||
kind: 'error',
|
||||
loc: value.loc,
|
||||
message: 'Avoid constructing JSX within try/catch',
|
||||
}),
|
||||
);
|
||||
errors.push({
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
reason: `Unexpected JSX element within a try statement. To catch errors in rendering a given component, wrap that component in an error boundary. (https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary)`,
|
||||
loc: value.loc,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {
|
||||
CompilerDiagnostic,
|
||||
CompilerError,
|
||||
ErrorSeverity,
|
||||
} from '../CompilerError';
|
||||
import {CompilerError, ErrorSeverity} from '../CompilerError';
|
||||
import {
|
||||
HIRFunction,
|
||||
IdentifierId,
|
||||
@@ -94,21 +90,14 @@ export function validateNoSetStateInEffects(
|
||||
if (arg !== undefined && arg.kind === 'Identifier') {
|
||||
const setState = setStateFunctions.get(arg.identifier.id);
|
||||
if (setState !== undefined) {
|
||||
errors.pushDiagnostic(
|
||||
CompilerDiagnostic.create({
|
||||
category:
|
||||
'Calling setState within an effect can trigger cascading renders',
|
||||
description:
|
||||
'Calling setState directly within a useEffect causes cascading renders that can hurt performance, and is not recommended. Consider alternatives to useEffect. (https://react.dev/learn/you-might-not-need-an-effect)',
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
suggestions: null,
|
||||
}).withDetail({
|
||||
kind: 'error',
|
||||
loc: setState.loc,
|
||||
message:
|
||||
'Avoid calling setState() in the top-level of an effect',
|
||||
}),
|
||||
);
|
||||
errors.push({
|
||||
reason:
|
||||
'Calling setState directly within a useEffect causes cascading renders and is not recommended. Consider alternatives to useEffect. (https://react.dev/learn/you-might-not-need-an-effect)',
|
||||
description: null,
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
loc: setState.loc,
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {
|
||||
CompilerDiagnostic,
|
||||
CompilerError,
|
||||
ErrorSeverity,
|
||||
} from '../CompilerError';
|
||||
import {CompilerError, ErrorSeverity} from '../CompilerError';
|
||||
import {HIRFunction, IdentifierId, isSetStateType} from '../HIR';
|
||||
import {computeUnconditionalBlocks} from '../HIR/ComputeUnconditionalBlocks';
|
||||
import {eachInstructionValueOperand} from '../HIR/visitors';
|
||||
@@ -126,35 +122,23 @@ function validateNoSetStateInRenderImpl(
|
||||
unconditionalSetStateFunctions.has(callee.identifier.id)
|
||||
) {
|
||||
if (activeManualMemoId !== null) {
|
||||
errors.pushDiagnostic(
|
||||
CompilerDiagnostic.create({
|
||||
category:
|
||||
'Calling setState from useMemo may trigger an infinite loop',
|
||||
description:
|
||||
'Each time the memo callback is evaluated it will change state. This can cause a memoization dependency to change, running the memo function again and causing an infinite loop. Instead of setting state in useMemo(), prefer deriving the value during render. (https://react.dev/reference/react/useState)',
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
suggestions: null,
|
||||
}).withDetail({
|
||||
kind: 'error',
|
||||
loc: callee.loc,
|
||||
message: 'Found setState() within useMemo()',
|
||||
}),
|
||||
);
|
||||
errors.push({
|
||||
reason:
|
||||
'Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)',
|
||||
description: null,
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
loc: callee.loc,
|
||||
suggestions: null,
|
||||
});
|
||||
} else if (unconditionalBlocks.has(block.id)) {
|
||||
errors.pushDiagnostic(
|
||||
CompilerDiagnostic.create({
|
||||
category:
|
||||
'Calling setState during render may trigger an infinite loop',
|
||||
description:
|
||||
'Calling setState during render will trigger another render, and can lead to infinite loops. (https://react.dev/reference/react/useState)',
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
suggestions: null,
|
||||
}).withDetail({
|
||||
kind: 'error',
|
||||
loc: callee.loc,
|
||||
message: 'Found setState() within useMemo()',
|
||||
}),
|
||||
);
|
||||
errors.push({
|
||||
reason:
|
||||
'This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)',
|
||||
description: null,
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
loc: callee.loc,
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -5,11 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {
|
||||
CompilerDiagnostic,
|
||||
CompilerError,
|
||||
ErrorSeverity,
|
||||
} from '../CompilerError';
|
||||
import {CompilerError, ErrorSeverity} from '../CompilerError';
|
||||
import {
|
||||
DeclarationId,
|
||||
Effect,
|
||||
@@ -279,37 +275,27 @@ function validateInferredDep(
|
||||
errorDiagnostic = merge(errorDiagnostic ?? compareResult, compareResult);
|
||||
}
|
||||
}
|
||||
errorState.pushDiagnostic(
|
||||
CompilerDiagnostic.create({
|
||||
severity: ErrorSeverity.CannotPreserveMemoization,
|
||||
category:
|
||||
'Compilation skipped because existing memoization could not be preserved',
|
||||
description: [
|
||||
'React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. ',
|
||||
'The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. ',
|
||||
DEBUG ||
|
||||
// If the dependency is a named variable then we can report it. Otherwise only print in debug mode
|
||||
(dep.identifier.name != null && dep.identifier.name.kind === 'named')
|
||||
? `The inferred dependency was \`${prettyPrintScopeDependency(
|
||||
dep,
|
||||
)}\`, but the source dependencies were [${validDepsInMemoBlock
|
||||
.map(dep => printManualMemoDependency(dep, true))
|
||||
.join(', ')}]. ${
|
||||
errorDiagnostic
|
||||
? getCompareDependencyResultDescription(errorDiagnostic)
|
||||
: 'Inferred dependency not present in source'
|
||||
}.`
|
||||
: '',
|
||||
]
|
||||
.join('')
|
||||
.trim(),
|
||||
suggestions: null,
|
||||
}).withDetail({
|
||||
kind: 'error',
|
||||
loc: memoLocation,
|
||||
message: 'Could not preserve existing manual memoization',
|
||||
}),
|
||||
);
|
||||
errorState.push({
|
||||
severity: ErrorSeverity.CannotPreserveMemoization,
|
||||
reason:
|
||||
'React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected',
|
||||
description:
|
||||
DEBUG ||
|
||||
// If the dependency is a named variable then we can report it. Otherwise only print in debug mode
|
||||
(dep.identifier.name != null && dep.identifier.name.kind === 'named')
|
||||
? `The inferred dependency was \`${prettyPrintScopeDependency(
|
||||
dep,
|
||||
)}\`, but the source dependencies were [${validDepsInMemoBlock
|
||||
.map(dep => printManualMemoDependency(dep, true))
|
||||
.join(', ')}]. ${
|
||||
errorDiagnostic
|
||||
? getCompareDependencyResultDescription(errorDiagnostic)
|
||||
: 'Inferred dependency not present in source'
|
||||
}`
|
||||
: null,
|
||||
loc: memoLocation,
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
|
||||
class Visitor extends ReactiveFunctionVisitor<VisitorState> {
|
||||
@@ -533,21 +519,14 @@ class Visitor extends ReactiveFunctionVisitor<VisitorState> {
|
||||
!this.scopes.has(identifier.scope.id) &&
|
||||
!this.prunedScopes.has(identifier.scope.id)
|
||||
) {
|
||||
state.errors.pushDiagnostic(
|
||||
CompilerDiagnostic.create({
|
||||
severity: ErrorSeverity.CannotPreserveMemoization,
|
||||
category:
|
||||
'Compilation skipped because existing memoization could not be preserved',
|
||||
description: [
|
||||
'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.',
|
||||
].join(''),
|
||||
}).withDetail({
|
||||
kind: 'error',
|
||||
loc,
|
||||
message: 'This dependency may be modified later',
|
||||
}),
|
||||
);
|
||||
state.errors.push({
|
||||
reason:
|
||||
'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,
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -581,25 +560,16 @@ class Visitor extends ReactiveFunctionVisitor<VisitorState> {
|
||||
|
||||
for (const identifier of decls) {
|
||||
if (isUnmemoized(identifier, this.scopes)) {
|
||||
state.errors.pushDiagnostic(
|
||||
CompilerDiagnostic.create({
|
||||
severity: ErrorSeverity.CannotPreserveMemoization,
|
||||
category:
|
||||
'Compilation skipped because existing memoization could not be preserved',
|
||||
description: [
|
||||
'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. ',
|
||||
DEBUG
|
||||
? `${printIdentifier(identifier)} was not memoized.`
|
||||
: '',
|
||||
]
|
||||
.join('')
|
||||
.trim(),
|
||||
}).withDetail({
|
||||
kind: 'error',
|
||||
loc,
|
||||
message: 'Could not preserve existing memoization',
|
||||
}),
|
||||
);
|
||||
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: DEBUG
|
||||
? `${printIdentifier(identifier)} was not memoized`
|
||||
: null,
|
||||
severity: ErrorSeverity.CannotPreserveMemoization,
|
||||
loc,
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {
|
||||
CompilerDiagnostic,
|
||||
CompilerError,
|
||||
ErrorSeverity,
|
||||
} from '../CompilerError';
|
||||
import {CompilerError, ErrorSeverity} from '..';
|
||||
import {FunctionExpression, HIRFunction, IdentifierId} from '../HIR';
|
||||
import {Result} from '../Utils/Result';
|
||||
|
||||
@@ -67,41 +63,24 @@ export function validateUseMemo(fn: HIRFunction): Result<void, CompilerError> {
|
||||
}
|
||||
|
||||
if (body.loweredFunc.func.params.length > 0) {
|
||||
const firstParam = body.loweredFunc.func.params[0];
|
||||
const loc =
|
||||
firstParam.kind === 'Identifier'
|
||||
? firstParam.loc
|
||||
: firstParam.place.loc;
|
||||
errors.pushDiagnostic(
|
||||
CompilerDiagnostic.create({
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
category: 'useMemo() callbacks may not accept parameters',
|
||||
description:
|
||||
'useMemo() callbacks are called by React to cache calculations across re-renders. They should not take parameters. Instead, directly reference the props, state, or local variables needed for the computation.',
|
||||
suggestions: null,
|
||||
}).withDetail({
|
||||
kind: 'error',
|
||||
loc,
|
||||
message: '',
|
||||
}),
|
||||
);
|
||||
errors.push({
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
reason: 'useMemo callbacks may not accept any arguments',
|
||||
description: null,
|
||||
loc: body.loc,
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
|
||||
if (body.loweredFunc.func.async || body.loweredFunc.func.generator) {
|
||||
errors.pushDiagnostic(
|
||||
CompilerDiagnostic.create({
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
category:
|
||||
'useMemo callbacks may not be async or generator functions',
|
||||
description:
|
||||
'useMemo() callbacks are called once and must synchronously return a value',
|
||||
suggestions: null,
|
||||
}).withDetail({
|
||||
kind: 'error',
|
||||
loc: body.loc,
|
||||
message: 'Async and generator functions are not supported',
|
||||
}),
|
||||
);
|
||||
errors.push({
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
reason:
|
||||
'useMemo callbacks may not be async or generator functions',
|
||||
description: null,
|
||||
loc: body.loc,
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @validatePreserveExistingMemoizationGuarantees
|
||||
import {useMemo} from 'react';
|
||||
import {makeObject_Primitives, ValidateMemoization} from 'shared-runtime';
|
||||
|
||||
function Component(props) {
|
||||
// Should memoize independently
|
||||
const x = useMemo(() => makeObject_Primitives(), []);
|
||||
|
||||
const rest = useMemo(() => {
|
||||
const [_, ...rest] = props.array;
|
||||
|
||||
// Should be inferred as Array.proto.push which doesn't mutate input
|
||||
rest.push(x);
|
||||
return rest;
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<ValidateMemoization inputs={[]} output={x} />
|
||||
<ValidateMemoization inputs={[props.array]} output={rest} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{array: [0, 1, 2]}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @validatePreserveExistingMemoizationGuarantees
|
||||
import { useMemo } from "react";
|
||||
import { makeObject_Primitives, ValidateMemoization } from "shared-runtime";
|
||||
|
||||
function Component(props) {
|
||||
const $ = _c(9);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = makeObject_Primitives();
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
const x = t0;
|
||||
let rest;
|
||||
if ($[1] !== props.array) {
|
||||
[, ...rest] = props.array;
|
||||
|
||||
rest.push(x);
|
||||
$[1] = props.array;
|
||||
$[2] = rest;
|
||||
} else {
|
||||
rest = $[2];
|
||||
}
|
||||
const rest_0 = rest;
|
||||
let t1;
|
||||
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = <ValidateMemoization inputs={[]} output={x} />;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
}
|
||||
let t2;
|
||||
if ($[4] !== props.array) {
|
||||
t2 = [props.array];
|
||||
$[4] = props.array;
|
||||
$[5] = t2;
|
||||
} else {
|
||||
t2 = $[5];
|
||||
}
|
||||
let t3;
|
||||
if ($[6] !== rest_0 || $[7] !== t2) {
|
||||
t3 = (
|
||||
<>
|
||||
{t1}
|
||||
<ValidateMemoization inputs={t2} output={rest_0} />
|
||||
</>
|
||||
);
|
||||
$[6] = rest_0;
|
||||
$[7] = t2;
|
||||
$[8] = t3;
|
||||
} else {
|
||||
t3 = $[8];
|
||||
}
|
||||
return t3;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ array: [0, 1, 2] }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) <div>{"inputs":[],"output":{"a":0,"b":"value1","c":true}}</div><div>{"inputs":[[0,1,2]],"output":[1,2,{"a":0,"b":"value1","c":true}]}</div>
|
||||
@@ -1,28 +0,0 @@
|
||||
// @validatePreserveExistingMemoizationGuarantees
|
||||
import {useMemo} from 'react';
|
||||
import {makeObject_Primitives, ValidateMemoization} from 'shared-runtime';
|
||||
|
||||
function Component(props) {
|
||||
// Should memoize independently
|
||||
const x = useMemo(() => makeObject_Primitives(), []);
|
||||
|
||||
const rest = useMemo(() => {
|
||||
const [_, ...rest] = props.array;
|
||||
|
||||
// Should be inferred as Array.proto.push which doesn't mutate input
|
||||
rest.push(x);
|
||||
return rest;
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<ValidateMemoization inputs={[]} output={x} />
|
||||
<ValidateMemoization inputs={[props.array]} output={rest} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{array: [0, 1, 2]}],
|
||||
};
|
||||
@@ -36,10 +36,8 @@ function Component() {
|
||||
## Error
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Cannot modify local variables after render completes
|
||||
|
||||
This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
Found 2 errors:
|
||||
Error: This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
|
||||
error.bug-old-inference-false-positive-ref-validation-in-use-effect.ts:20:12
|
||||
18 | );
|
||||
@@ -53,19 +51,24 @@ error.bug-old-inference-false-positive-ref-validation-in-use-effect.ts:20:12
|
||||
> 23 | }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 24 | }, [update]);
|
||||
| ^^^^ This function may (indirectly) reassign or modify local variables after render
|
||||
| ^^^^ This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
25 |
|
||||
26 | return 'ok';
|
||||
27 | }
|
||||
|
||||
|
||||
Error: The function modifies a local variable here
|
||||
|
||||
error.bug-old-inference-false-positive-ref-validation-in-use-effect.ts:14:6
|
||||
12 | ...partialParams,
|
||||
13 | };
|
||||
> 14 | nextParams.param = 'value';
|
||||
| ^^^^^^^^^^ This modifies a local variable
|
||||
| ^^^^^^^^^^ The function modifies a local variable here
|
||||
15 | console.log(nextParams);
|
||||
16 | },
|
||||
17 | [params]
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -29,18 +29,20 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Cannot reassign a variable after render completes
|
||||
Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
|
||||
Reassigning variable `x` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
Variable `x` cannot be reassigned after render.
|
||||
|
||||
error.context-variable-only-chained-assign.ts:10:19
|
||||
8 | };
|
||||
9 | const fn2 = () => {
|
||||
> 10 | const copy2 = (x = 4);
|
||||
| ^ Cannot reassign variable after render completes
|
||||
| ^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
11 | return [invoke(fn1), copy2, identity(copy2)];
|
||||
12 | };
|
||||
13 | return invoke(fn2);
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -18,18 +18,20 @@ function Component() {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Cannot reassign a variable after render completes
|
||||
Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
|
||||
Reassigning variable `x` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
Variable `x` cannot be reassigned after render.
|
||||
|
||||
error.declare-reassign-variable-in-function-declaration.ts:4:4
|
||||
2 | let x = null;
|
||||
3 | function foo() {
|
||||
> 4 | x = 9;
|
||||
| ^ Cannot reassign variable after render completes
|
||||
| ^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
5 | }
|
||||
6 | const y = bar(foo);
|
||||
7 | return <Child y={y} />;
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -16,18 +16,20 @@ function Component() {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Cannot reassign a variable after render completes
|
||||
Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
|
||||
Reassigning variable `callback` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
Variable `callback` cannot be reassigned after render.
|
||||
|
||||
error.function-expression-references-variable-its-assigned-to.ts:3:4
|
||||
1 | function Component() {
|
||||
2 | let callback = () => {
|
||||
> 3 | callback = null;
|
||||
| ^^^^^^^^ Cannot reassign variable after render completes
|
||||
| ^^^^^^^^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
4 | };
|
||||
5 | return <div onClick={callback} />;
|
||||
6 | }
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ function Component(props) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source.
|
||||
The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source.
|
||||
|
||||
error.hoist-optional-member-expression-with-conditional-optional.ts:4:23
|
||||
2 | import {ValidateMemoization} from 'shared-runtime';
|
||||
@@ -47,10 +47,12 @@ error.hoist-optional-member-expression-with-conditional-optional.ts:4:23
|
||||
> 10 | return x;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
> 11 | }, [props?.items, props.cond]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
12 | return (
|
||||
13 | <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />
|
||||
14 | );
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ function Component(props) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source.
|
||||
The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source.
|
||||
|
||||
error.hoist-optional-member-expression-with-conditional.ts:4:23
|
||||
2 | import {ValidateMemoization} from 'shared-runtime';
|
||||
@@ -47,10 +47,12 @@ error.hoist-optional-member-expression-with-conditional.ts:4:23
|
||||
> 10 | return x;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
> 11 | }, [props?.items, props.cond]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
12 | return (
|
||||
13 | <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />
|
||||
14 | );
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -18,8 +18,6 @@ function component(a, b) {
|
||||
Found 1 error:
|
||||
Error: useMemo callbacks may not be async or generator functions
|
||||
|
||||
useMemo() callbacks are called once and must synchronously return a value
|
||||
|
||||
error.invalid-ReactUseMemo-async-callback.ts:2:24
|
||||
1 | function component(a, b) {
|
||||
> 2 | let x = React.useMemo(async () => {
|
||||
@@ -27,10 +25,12 @@ error.invalid-ReactUseMemo-async-callback.ts:2:24
|
||||
> 3 | await a;
|
||||
| ^^^^^^^^^^^^
|
||||
> 4 | }, []);
|
||||
| ^^^^ Async and generator functions are not supported
|
||||
| ^^^^ useMemo callbacks may not be async or generator functions
|
||||
5 | return x;
|
||||
6 | }
|
||||
7 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -23,30 +23,30 @@ function Component({item, cond}) {
|
||||
|
||||
```
|
||||
Found 2 errors:
|
||||
Error: Calling setState from useMemo may trigger an infinite loop
|
||||
|
||||
Each time the memo callback is evaluated it will change state. This can cause a memoization dependency to change, running the memo function again and causing an infinite loop. Instead of setting state in useMemo(), prefer deriving the value during render. (https://react.dev/reference/react/useState)
|
||||
Error: Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
|
||||
error.invalid-conditional-setState-in-useMemo.ts:7:6
|
||||
5 | useMemo(() => {
|
||||
6 | if (cond) {
|
||||
> 7 | setPrevItem(item);
|
||||
| ^^^^^^^^^^^ Found setState() within useMemo()
|
||||
| ^^^^^^^^^^^ Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
8 | setState(0);
|
||||
9 | }
|
||||
10 | }, [cond, key, init]);
|
||||
Error: Calling setState from useMemo may trigger an infinite loop
|
||||
|
||||
Each time the memo callback is evaluated it will change state. This can cause a memoization dependency to change, running the memo function again and causing an infinite loop. Instead of setting state in useMemo(), prefer deriving the value during render. (https://react.dev/reference/react/useState)
|
||||
|
||||
Error: Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
|
||||
error.invalid-conditional-setState-in-useMemo.ts:8:6
|
||||
6 | if (cond) {
|
||||
7 | setPrevItem(item);
|
||||
> 8 | setState(0);
|
||||
| ^^^^^^^^ Found setState() within useMemo()
|
||||
| ^^^^^^^^ Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
9 | }
|
||||
10 | }, [cond, key, init]);
|
||||
11 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -17,10 +17,8 @@ function useFoo() {
|
||||
## Error
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Cannot modify local variables after render completes
|
||||
|
||||
This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
Found 2 errors:
|
||||
Error: This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
|
||||
error.invalid-hook-function-argument-mutates-local-variable.ts:5:10
|
||||
3 | function useFoo() {
|
||||
@@ -30,18 +28,23 @@ error.invalid-hook-function-argument-mutates-local-variable.ts:5:10
|
||||
> 6 | cache.set('key', 'value');
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 7 | });
|
||||
| ^^^^ This function may (indirectly) reassign or modify local variables after render
|
||||
| ^^^^ This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
8 | }
|
||||
9 |
|
||||
|
||||
|
||||
Error: The function modifies a local variable here
|
||||
|
||||
error.invalid-hook-function-argument-mutates-local-variable.ts:6:4
|
||||
4 | const cache = new Map();
|
||||
5 | useHook(() => {
|
||||
> 6 | cache.set('key', 'value');
|
||||
| ^^^^^ This modifies a local variable
|
||||
| ^^^^^ The function modifies a local variable here
|
||||
7 | });
|
||||
8 | }
|
||||
9 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -47,18 +47,20 @@ function Component() {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Cannot reassign a variable after render completes
|
||||
Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
|
||||
Reassigning variable `local` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
Variable `local` cannot be reassigned after render.
|
||||
|
||||
error.invalid-nested-function-reassign-local-variable-in-effect.ts:7:6
|
||||
5 | // Create the reassignment function inside another function, then return it
|
||||
6 | const reassignLocal = newValue => {
|
||||
> 7 | local = newValue;
|
||||
| ^^^^^ Cannot reassign variable after render completes
|
||||
| ^^^^^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
8 | };
|
||||
9 | return reassignLocal;
|
||||
10 | };
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@ function Component(props) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `props.items.edges.nodes`, but the source dependencies were [props.items?.edges?.nodes]. Inferred different dependency than source.
|
||||
The inferred dependency was `props.items.edges.nodes`, but the source dependencies were [props.items?.edges?.nodes]. Inferred different dependency than source.
|
||||
|
||||
error.invalid-optional-member-expression-as-memo-dep-non-optional-in-body.ts:3:23
|
||||
1 | // @validatePreserveExistingMemoizationGuarantees
|
||||
@@ -35,10 +35,12 @@ error.invalid-optional-member-expression-as-memo-dep-non-optional-in-body.ts:3:2
|
||||
> 6 | // deps are optional
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 7 | }, [props.items?.edges?.nodes]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
8 | return <Foo data={data} />;
|
||||
9 | }
|
||||
10 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -17,27 +17,30 @@ function Component() {
|
||||
## Error
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Cannot modify local variables after render completes
|
||||
|
||||
This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
Found 2 errors:
|
||||
Error: This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
|
||||
error.invalid-pass-mutable-function-as-prop.ts:7:18
|
||||
5 | cache.set('key', 'value');
|
||||
6 | };
|
||||
> 7 | return <Foo fn={fn} />;
|
||||
| ^^ This function may (indirectly) reassign or modify local variables after render
|
||||
| ^^ This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
8 | }
|
||||
9 |
|
||||
|
||||
|
||||
Error: The function modifies a local variable here
|
||||
|
||||
error.invalid-pass-mutable-function-as-prop.ts:5:4
|
||||
3 | const cache = new Map();
|
||||
4 | const fn = () => {
|
||||
> 5 | cache.set('key', 'value');
|
||||
| ^^^^^ This modifies a local variable
|
||||
| ^^^^^ The function modifies a local variable here
|
||||
6 | };
|
||||
7 | return <Foo fn={fn} />;
|
||||
8 | }
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -16,18 +16,20 @@ function useFoo() {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Cannot reassign a variable after render completes
|
||||
Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
|
||||
Reassigning variable `x` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
Variable `x` cannot be reassigned after render.
|
||||
|
||||
error.invalid-reassign-local-in-hook-return-value.ts:4:4
|
||||
2 | let x = 0;
|
||||
3 | return value => {
|
||||
> 4 | x = value;
|
||||
| ^ Cannot reassign variable after render completes
|
||||
| ^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
5 | };
|
||||
6 | }
|
||||
7 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -48,18 +48,20 @@ function Component() {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Cannot reassign a variable after render completes
|
||||
Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
|
||||
Reassigning variable `local` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
Variable `local` cannot be reassigned after render.
|
||||
|
||||
error.invalid-reassign-local-variable-in-effect.ts:7:4
|
||||
5 |
|
||||
6 | const reassignLocal = newValue => {
|
||||
> 7 | local = newValue;
|
||||
| ^^^^^ Cannot reassign variable after render completes
|
||||
| ^^^^^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
8 | };
|
||||
9 |
|
||||
10 | const onMount = newValue => {
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -49,18 +49,20 @@ function Component() {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Cannot reassign a variable after render completes
|
||||
Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
|
||||
Reassigning variable `local` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
Variable `local` cannot be reassigned after render.
|
||||
|
||||
error.invalid-reassign-local-variable-in-hook-argument.ts:8:4
|
||||
6 |
|
||||
7 | const reassignLocal = newValue => {
|
||||
> 8 | local = newValue;
|
||||
| ^^^^^ Cannot reassign variable after render completes
|
||||
| ^^^^^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
9 | };
|
||||
10 |
|
||||
11 | const callback = newValue => {
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -42,18 +42,20 @@ function Component() {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Cannot reassign a variable after render completes
|
||||
Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
|
||||
Reassigning variable `local` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
Variable `local` cannot be reassigned after render.
|
||||
|
||||
error.invalid-reassign-local-variable-in-jsx-callback.ts:5:4
|
||||
3 |
|
||||
4 | const reassignLocal = newValue => {
|
||||
> 5 | local = newValue;
|
||||
| ^^^^^ Cannot reassign variable after render completes
|
||||
| ^^^^^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
6 | };
|
||||
7 |
|
||||
8 | const onClick = newValue => {
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -19,10 +19,8 @@ function useFoo() {
|
||||
## Error
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Cannot modify local variables after render completes
|
||||
|
||||
This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
Found 2 errors:
|
||||
Error: This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
|
||||
error.invalid-return-mutable-function-from-hook.ts:7:9
|
||||
5 | useHook(); // for inference to kick in
|
||||
@@ -32,18 +30,23 @@ error.invalid-return-mutable-function-from-hook.ts:7:9
|
||||
> 8 | cache.set('key', 'value');
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 9 | };
|
||||
| ^^^^ This function may (indirectly) reassign or modify local variables after render
|
||||
| ^^^^ This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
10 | }
|
||||
11 |
|
||||
|
||||
|
||||
Error: The function modifies a local variable here
|
||||
|
||||
error.invalid-return-mutable-function-from-hook.ts:8:4
|
||||
6 | const cache = new Map();
|
||||
7 | return () => {
|
||||
> 8 | cache.set('key', 'value');
|
||||
| ^^^^^ This modifies a local variable
|
||||
| ^^^^^ The function modifies a local variable here
|
||||
9 | };
|
||||
10 | }
|
||||
11 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -27,18 +27,18 @@ function useKeyedState({key, init}) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Calling setState from useMemo may trigger an infinite loop
|
||||
|
||||
Each time the memo callback is evaluated it will change state. This can cause a memoization dependency to change, running the memo function again and causing an infinite loop. Instead of setting state in useMemo(), prefer deriving the value during render. (https://react.dev/reference/react/useState)
|
||||
Error: Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
|
||||
error.invalid-setState-in-useMemo-indirect-useCallback.ts:13:4
|
||||
11 |
|
||||
12 | useMemo(() => {
|
||||
> 13 | fn();
|
||||
| ^^ Found setState() within useMemo()
|
||||
| ^^ Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
14 | }, [key, init]);
|
||||
15 |
|
||||
16 | return state;
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -21,30 +21,30 @@ function useKeyedState({key, init}) {
|
||||
|
||||
```
|
||||
Found 2 errors:
|
||||
Error: Calling setState from useMemo may trigger an infinite loop
|
||||
|
||||
Each time the memo callback is evaluated it will change state. This can cause a memoization dependency to change, running the memo function again and causing an infinite loop. Instead of setting state in useMemo(), prefer deriving the value during render. (https://react.dev/reference/react/useState)
|
||||
Error: Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
|
||||
error.invalid-setState-in-useMemo.ts:6:4
|
||||
4 |
|
||||
5 | useMemo(() => {
|
||||
> 6 | setPrevKey(key);
|
||||
| ^^^^^^^^^^ Found setState() within useMemo()
|
||||
| ^^^^^^^^^^ Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
7 | setState(init);
|
||||
8 | }, [key, init]);
|
||||
9 |
|
||||
Error: Calling setState from useMemo may trigger an infinite loop
|
||||
|
||||
Each time the memo callback is evaluated it will change state. This can cause a memoization dependency to change, running the memo function again and causing an infinite loop. Instead of setting state in useMemo(), prefer deriving the value during render. (https://react.dev/reference/react/useState)
|
||||
|
||||
Error: Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
|
||||
error.invalid-setState-in-useMemo.ts:7:4
|
||||
5 | useMemo(() => {
|
||||
6 | setPrevKey(key);
|
||||
> 7 | setState(init);
|
||||
| ^^^^^^^^ Found setState() within useMemo()
|
||||
| ^^^^^^^^ Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
8 | }, [key, init]);
|
||||
9 |
|
||||
10 | return state;
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -47,10 +47,8 @@ hook useMemoMap<TInput: interface {}, TOutput>(
|
||||
## Error
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Cannot modify local variables after render completes
|
||||
|
||||
This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
Found 2 errors:
|
||||
Error: This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
|
||||
undefined:21:9
|
||||
19 | map: TInput => TOutput
|
||||
@@ -88,18 +86,23 @@ undefined:21:9
|
||||
> 36 | };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 37 | }, [map]);
|
||||
| ^^^^^^^^^^^^ This function may (indirectly) reassign or modify local variables after render
|
||||
| ^^^^^^^^^^^^ This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
38 | }
|
||||
39 |
|
||||
|
||||
|
||||
Error: The function modifies a local variable here
|
||||
|
||||
undefined:33:8
|
||||
31 | if (output == null) {
|
||||
32 | output = map(input);
|
||||
> 33 | cache.set(input, output);
|
||||
| ^^^^^ This modifies a local variable
|
||||
| ^^^^^ The function modifies a local variable here
|
||||
34 | }
|
||||
35 | return output;
|
||||
36 | };
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -20,30 +20,30 @@ function Component(props) {
|
||||
|
||||
```
|
||||
Found 2 errors:
|
||||
Error: Calling setState during render may trigger an infinite loop
|
||||
|
||||
Calling setState during render will trigger another render, and can lead to infinite loops. (https://react.dev/reference/react/useState)
|
||||
Error: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
|
||||
error.invalid-unconditional-set-state-in-render.ts:6:2
|
||||
4 | const aliased = setX;
|
||||
5 |
|
||||
> 6 | setX(1);
|
||||
| ^^^^ Found setState() within useMemo()
|
||||
| ^^^^ This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
7 | aliased(2);
|
||||
8 |
|
||||
9 | return x;
|
||||
Error: Calling setState during render may trigger an infinite loop
|
||||
|
||||
Calling setState during render will trigger another render, and can lead to infinite loops. (https://react.dev/reference/react/useState)
|
||||
|
||||
Error: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
|
||||
error.invalid-unconditional-set-state-in-render.ts:7:2
|
||||
5 |
|
||||
6 | setX(1);
|
||||
> 7 | aliased(2);
|
||||
| ^^^^^^^ Found setState() within useMemo()
|
||||
| ^^^^^^^ This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
8 |
|
||||
9 | return x;
|
||||
10 | }
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -18,8 +18,6 @@ function component(a, b) {
|
||||
Found 1 error:
|
||||
Error: useMemo callbacks may not be async or generator functions
|
||||
|
||||
useMemo() callbacks are called once and must synchronously return a value
|
||||
|
||||
error.invalid-useMemo-async-callback.ts:2:18
|
||||
1 | function component(a, b) {
|
||||
> 2 | let x = useMemo(async () => {
|
||||
@@ -27,10 +25,12 @@ error.invalid-useMemo-async-callback.ts:2:18
|
||||
> 3 | await a;
|
||||
| ^^^^^^^^^^^^
|
||||
> 4 | }, []);
|
||||
| ^^^^ Async and generator functions are not supported
|
||||
| ^^^^ useMemo callbacks may not be async or generator functions
|
||||
5 | return x;
|
||||
6 | }
|
||||
7 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -14,17 +14,17 @@ function component(a, b) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: useMemo() callbacks may not accept parameters
|
||||
|
||||
useMemo() callbacks are called by React to cache calculations across re-renders. They should not take parameters. Instead, directly reference the props, state, or local variables needed for the computation.
|
||||
Error: useMemo callbacks may not accept any arguments
|
||||
|
||||
error.invalid-useMemo-callback-args.ts:2:18
|
||||
1 | function component(a, b) {
|
||||
> 2 | let x = useMemo(c => a, []);
|
||||
| ^
|
||||
| ^^^^^^ useMemo callbacks may not accept any arguments
|
||||
3 | return x;
|
||||
4 | }
|
||||
5 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -33,18 +33,20 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Cannot reassign a variable after render completes
|
||||
Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
|
||||
Reassigning variable `a` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
Variable `a` cannot be reassigned after render.
|
||||
|
||||
error.mutable-range-shared-inner-outer-function.ts:8:6
|
||||
6 | const f = () => {
|
||||
7 | if (cond) {
|
||||
> 8 | a = {};
|
||||
| ^ Cannot reassign variable after render completes
|
||||
| ^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
9 | b = [];
|
||||
10 | } else {
|
||||
11 | a = {};
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `Ref.current`, but the source dependencies were []. Inferred dependency not present in source.
|
||||
The inferred dependency was `Ref.current`, but the source dependencies were []. Inferred dependency not present in source.
|
||||
|
||||
error.ref-like-name-not-Ref.ts:11:30
|
||||
9 | const Ref = useCustomRef();
|
||||
@@ -44,10 +44,12 @@ error.ref-like-name-not-Ref.ts:11:30
|
||||
> 12 | Ref.current?.click();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 13 | }, []);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
14 |
|
||||
15 | return <button onClick={onClick} />;
|
||||
16 | }
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `notaref.current`, but the source dependencies were []. Inferred dependency not present in source.
|
||||
The inferred dependency was `notaref.current`, but the source dependencies were []. Inferred dependency not present in source.
|
||||
|
||||
error.ref-like-name-not-a-ref.ts:11:30
|
||||
9 | const notaref = useCustomRef();
|
||||
@@ -44,10 +44,12 @@ error.ref-like-name-not-a-ref.ts:11:30
|
||||
> 12 | notaref.current?.click();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 13 | }, []);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
14 |
|
||||
15 | return <button onClick={onClick} />;
|
||||
16 | }
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -18,18 +18,20 @@ function Component() {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Cannot reassign a variable after render completes
|
||||
Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
|
||||
Reassigning variable `onClick` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
Variable `onClick` cannot be reassigned after render.
|
||||
|
||||
error.todo-function-expression-references-later-variable-declaration.ts:3:4
|
||||
1 | function Component() {
|
||||
2 | let callback = () => {
|
||||
> 3 | onClick = () => {};
|
||||
| ^^^^^^^ Cannot reassign variable after render completes
|
||||
| ^^^^^^^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
4 | };
|
||||
5 | let onClick;
|
||||
6 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -43,18 +43,18 @@ component Component() {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
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.
|
||||
Memoization: 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.
|
||||
|
||||
undefined:18:20
|
||||
16 | // We infer that getIsEnabled returns a mutable value, such that
|
||||
17 | // isEnabled is mutable
|
||||
> 18 | const isEnabled = useMemo(() => getIsEnabled(), [getIsEnabled]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Could not preserve existing memoization
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
||||
19 |
|
||||
20 | // We then infer getLoggingData as capturing that mutable value,
|
||||
21 | // so any calls to this function are then inferred as extending
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -53,9 +53,7 @@ component Component(id) {
|
||||
|
||||
```
|
||||
Found 3 errors:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
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.
|
||||
Memoization: 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.
|
||||
|
||||
undefined:11:18
|
||||
9 | const [index, setIndex] = useState(0);
|
||||
@@ -71,25 +69,25 @@ undefined:11:18
|
||||
> 15 | };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 16 | }, [index, items]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ Could not preserve existing memoization
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ 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.
|
||||
17 |
|
||||
18 | const setCurrentIndex = useCallback(
|
||||
19 | (index: number) => {
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
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.
|
||||
|
||||
Memoization: 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
|
||||
|
||||
undefined:28:12
|
||||
26 | setIndex(index);
|
||||
27 | },
|
||||
> 28 | [index, logData, items]
|
||||
| ^^^^^^^ This dependency may be modified later
|
||||
| ^^^^^^^ 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
|
||||
29 | );
|
||||
30 |
|
||||
31 | if (prevId !== id) {
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
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.
|
||||
|
||||
Memoization: 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.
|
||||
|
||||
undefined:19:4
|
||||
17 |
|
||||
@@ -111,10 +109,12 @@ undefined:19:4
|
||||
> 26 | setIndex(index);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 27 | },
|
||||
| ^^^^^^ Could not preserve existing memoization
|
||||
| ^^^^^^ 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.
|
||||
28 | [index, logData, items]
|
||||
29 | );
|
||||
30 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -51,18 +51,18 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
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.
|
||||
Memoization: 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.
|
||||
|
||||
error.todo-repro-unmemoized-callback-captured-in-context-variable.ts:11:12
|
||||
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(() => ({}), []);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ Could not preserve existing memoization
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ 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 |
|
||||
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
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -23,18 +23,18 @@ function Component(props) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Calling setState during render may trigger an infinite loop
|
||||
|
||||
Calling setState during render will trigger another render, and can lead to infinite loops. (https://react.dev/reference/react/useState)
|
||||
Error: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
|
||||
error.unconditional-set-state-in-render-after-loop-break.ts:11:2
|
||||
9 | }
|
||||
10 | }
|
||||
> 11 | setState(true);
|
||||
| ^^^^^^^^ Found setState() within useMemo()
|
||||
| ^^^^^^^^ This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
12 | return state;
|
||||
13 | }
|
||||
14 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -18,18 +18,18 @@ function Component(props) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Calling setState during render may trigger an infinite loop
|
||||
|
||||
Calling setState during render will trigger another render, and can lead to infinite loops. (https://react.dev/reference/react/useState)
|
||||
Error: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
|
||||
error.unconditional-set-state-in-render-after-loop.ts:6:2
|
||||
4 | for (const _ of props) {
|
||||
5 | }
|
||||
> 6 | setState(true);
|
||||
| ^^^^^^^^ Found setState() within useMemo()
|
||||
| ^^^^^^^^ This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
7 | return state;
|
||||
8 | }
|
||||
9 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -23,18 +23,18 @@ function Component(props) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Calling setState during render may trigger an infinite loop
|
||||
|
||||
Calling setState during render will trigger another render, and can lead to infinite loops. (https://react.dev/reference/react/useState)
|
||||
Error: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
|
||||
error.unconditional-set-state-in-render-with-loop-throw.ts:11:2
|
||||
9 | }
|
||||
10 | }
|
||||
> 11 | setState(true);
|
||||
| ^^^^^^^^ Found setState() within useMemo()
|
||||
| ^^^^^^^^ This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
12 | return state;
|
||||
13 | }
|
||||
14 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -21,18 +21,18 @@ function Component(props) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Calling setState during render may trigger an infinite loop
|
||||
|
||||
Calling setState during render will trigger another render, and can lead to infinite loops. (https://react.dev/reference/react/useState)
|
||||
Error: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
|
||||
error.unconditional-set-state-lambda.ts:8:2
|
||||
6 | setX(1);
|
||||
7 | };
|
||||
> 8 | foo();
|
||||
| ^^^ Found setState() within useMemo()
|
||||
| ^^^ This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
9 |
|
||||
10 | return [x];
|
||||
11 | }
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -29,18 +29,18 @@ function Component(props) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Calling setState during render may trigger an infinite loop
|
||||
|
||||
Calling setState during render will trigger another render, and can lead to infinite loops. (https://react.dev/reference/react/useState)
|
||||
Error: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
|
||||
error.unconditional-set-state-nested-function-expressions.ts:16:2
|
||||
14 | bar();
|
||||
15 | };
|
||||
> 16 | baz();
|
||||
| ^^^ Found setState() within useMemo()
|
||||
| ^^^ This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
|
||||
17 |
|
||||
18 | return [x];
|
||||
19 | }
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
## Logs
|
||||
|
||||
```
|
||||
{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":206},"end":{"line":16,"column":1,"index":433},"filename":"dynamic-gating-bailout-nopanic.ts"},"detail":{"options":{"severity":"CannotPreserveMemoization","category":"Compilation skipped because existing memoization could not be preserved","description":"React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `value`, but the source dependencies were []. Inferred dependency not present in source.","suggestions":null,"details":[{"kind":"error","loc":{"start":{"line":9,"column":31,"index":288},"end":{"line":9,"column":52,"index":309},"filename":"dynamic-gating-bailout-nopanic.ts"},"message":"Could not preserve existing manual memoization"}]}}}
|
||||
{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":206},"end":{"line":16,"column":1,"index":433},"filename":"dynamic-gating-bailout-nopanic.ts"},"detail":{"options":{"reason":"React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected","description":"The inferred dependency was `value`, but the source dependencies were []. Inferred dependency not present in source","severity":"CannotPreserveMemoization","suggestions":null,"loc":{"start":{"line":9,"column":31,"index":288},"end":{"line":9,"column":52,"index":309},"filename":"dynamic-gating-bailout-nopanic.ts"}}}}
|
||||
```
|
||||
|
||||
### Eval output
|
||||
|
||||
@@ -65,7 +65,7 @@ function Component(props) {
|
||||
## Logs
|
||||
|
||||
```
|
||||
{"kind":"CompileError","detail":{"options":{"severity":"InvalidReact","category":"Avoid constructing JSX within try/catch","description":"React does not immediately render components when JSX is rendered, so any errors from this component will not be caught by the try/catch. To catch errors in rendering a given component, wrap that component in an error boundary. (https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary)","details":[{"kind":"error","loc":{"start":{"line":11,"column":11,"index":222},"end":{"line":11,"column":32,"index":243},"filename":"invalid-jsx-in-catch-in-outer-try-with-catch.ts"},"message":"Avoid constructing JSX within try/catch"}]}},"fnLoc":null}
|
||||
{"kind":"CompileError","detail":{"options":{"reason":"Unexpected JSX element within a try statement. To catch errors in rendering a given component, wrap that component in an error boundary. (https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary)","description":null,"severity":"InvalidReact","loc":{"start":{"line":11,"column":11,"index":222},"end":{"line":11,"column":32,"index":243},"filename":"invalid-jsx-in-catch-in-outer-try-with-catch.ts"}}},"fnLoc":null}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":4,"column":0,"index":91},"end":{"line":17,"column":1,"index":298},"filename":"invalid-jsx-in-catch-in-outer-try-with-catch.ts"},"fnName":"Component","memoSlots":4,"memoBlocks":2,"memoValues":2,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
```
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ function Component(props) {
|
||||
## Logs
|
||||
|
||||
```
|
||||
{"kind":"CompileError","detail":{"options":{"severity":"InvalidReact","category":"Avoid constructing JSX within try/catch","description":"React does not immediately render components when JSX is rendered, so any errors from this component will not be caught by the try/catch. To catch errors in rendering a given component, wrap that component in an error boundary. (https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary)","details":[{"kind":"error","loc":{"start":{"line":5,"column":9,"index":104},"end":{"line":5,"column":16,"index":111},"filename":"invalid-jsx-in-try-with-catch.ts"},"message":"Avoid constructing JSX within try/catch"}]}},"fnLoc":null}
|
||||
{"kind":"CompileError","detail":{"options":{"reason":"Unexpected JSX element within a try statement. To catch errors in rendering a given component, wrap that component in an error boundary. (https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary)","description":null,"severity":"InvalidReact","loc":{"start":{"line":5,"column":9,"index":104},"end":{"line":5,"column":16,"index":111},"filename":"invalid-jsx-in-try-with-catch.ts"}}},"fnLoc":null}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":2,"column":0,"index":49},"end":{"line":10,"column":1,"index":160},"filename":"invalid-jsx-in-try-with-catch.ts"},"fnName":"Component","memoSlots":1,"memoBlocks":1,"memoValues":1,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
```
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ function _temp(s) {
|
||||
## Logs
|
||||
|
||||
```
|
||||
{"kind":"CompileError","detail":{"options":{"category":"Calling setState within an effect can trigger cascading renders","description":"Calling setState directly within a useEffect causes cascading renders that can hurt performance, and is not recommended. Consider alternatives to useEffect. (https://react.dev/learn/you-might-not-need-an-effect)","severity":"InvalidReact","suggestions":null,"details":[{"kind":"error","loc":{"start":{"line":13,"column":4,"index":265},"end":{"line":13,"column":5,"index":266},"filename":"invalid-setState-in-useEffect-transitive.ts","identifierName":"g"},"message":"Avoid calling setState() in the top-level of an effect"}]}},"fnLoc":null}
|
||||
{"kind":"CompileError","detail":{"options":{"reason":"Calling setState directly within a useEffect causes cascading renders and is not recommended. Consider alternatives to useEffect. (https://react.dev/learn/you-might-not-need-an-effect)","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":13,"column":4,"index":265},"end":{"line":13,"column":5,"index":266},"filename":"invalid-setState-in-useEffect-transitive.ts","identifierName":"g"}}},"fnLoc":null}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":4,"column":0,"index":92},"end":{"line":16,"column":1,"index":293},"filename":"invalid-setState-in-useEffect-transitive.ts"},"fnName":"Component","memoSlots":2,"memoBlocks":2,"memoValues":2,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
```
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ function _temp(s) {
|
||||
## Logs
|
||||
|
||||
```
|
||||
{"kind":"CompileError","detail":{"options":{"category":"Calling setState within an effect can trigger cascading renders","description":"Calling setState directly within a useEffect causes cascading renders that can hurt performance, and is not recommended. Consider alternatives to useEffect. (https://react.dev/learn/you-might-not-need-an-effect)","severity":"InvalidReact","suggestions":null,"details":[{"kind":"error","loc":{"start":{"line":7,"column":4,"index":180},"end":{"line":7,"column":12,"index":188},"filename":"invalid-setState-in-useEffect.ts","identifierName":"setState"},"message":"Avoid calling setState() in the top-level of an effect"}]}},"fnLoc":null}
|
||||
{"kind":"CompileError","detail":{"options":{"reason":"Calling setState directly within a useEffect causes cascading renders and is not recommended. Consider alternatives to useEffect. (https://react.dev/learn/you-might-not-need-an-effect)","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":7,"column":4,"index":180},"end":{"line":7,"column":12,"index":188},"filename":"invalid-setState-in-useEffect.ts","identifierName":"setState"}}},"fnLoc":null}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":4,"column":0,"index":92},"end":{"line":10,"column":1,"index":225},"filename":"invalid-setState-in-useEffect.ts"},"fnName":"Component","memoSlots":1,"memoBlocks":1,"memoValues":1,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
```
|
||||
|
||||
|
||||
@@ -43,18 +43,20 @@ function Component() {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Error: Cannot reassign a variable after render completes
|
||||
Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
|
||||
Reassigning variable `local` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
Variable `local` cannot be reassigned after render.
|
||||
|
||||
error.invalid-reassign-local-variable-in-jsx-callback.ts:6:4
|
||||
4 |
|
||||
5 | const reassignLocal = newValue => {
|
||||
> 6 | local = newValue;
|
||||
| ^^^^^ Cannot reassign variable after render completes
|
||||
| ^^^^^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
|
||||
7 | };
|
||||
8 |
|
||||
9 | const onClick = newValue => {
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -30,30 +30,30 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```
|
||||
Found 2 errors:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
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.
|
||||
Memoization: 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
|
||||
|
||||
error.invalid-useCallback-captures-reassigned-context.ts:11:37
|
||||
9 |
|
||||
10 | // makeArray() is captured, but depsList contains [props]
|
||||
> 11 | const cb = useCallback(() => [x], [x]);
|
||||
| ^ This dependency may be modified later
|
||||
| ^ 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 |
|
||||
13 | x = makeArray();
|
||||
14 |
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
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.
|
||||
|
||||
Memoization: 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.
|
||||
|
||||
error.invalid-useCallback-captures-reassigned-context.ts:11:25
|
||||
9 |
|
||||
10 | // makeArray() is captured, but depsList contains [props]
|
||||
> 11 | const cb = useCallback(() => [x], [x]);
|
||||
| ^^^^^^^^^ Could not preserve existing memoization
|
||||
| ^^^^^^^^^ 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 |
|
||||
13 | x = makeArray();
|
||||
14 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -31,18 +31,18 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
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.
|
||||
Memoization: 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.
|
||||
|
||||
error.false-positive-useMemo-dropped-infer-always-invalidating.ts:15:9
|
||||
13 | x.push(props);
|
||||
14 |
|
||||
> 15 | return useMemo(() => [x], [x]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ Could not preserve existing memoization
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
||||
16 | }
|
||||
17 |
|
||||
18 | export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -30,18 +30,18 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
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.
|
||||
Memoization: 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
|
||||
|
||||
error.false-positive-useMemo-infer-mutate-deps.ts:14:6
|
||||
12 | return useMemo(() => {
|
||||
13 | return identity(val);
|
||||
> 14 | }, [val]);
|
||||
| ^^^ This dependency may be modified later
|
||||
| ^^^ 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
|
||||
15 | }
|
||||
16 |
|
||||
17 | export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -41,18 +41,18 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
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.
|
||||
Memoization: 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
|
||||
|
||||
error.false-positive-useMemo-overlap-scopes.ts:23:9
|
||||
21 | const result = useMemo(() => {
|
||||
22 | return [Math.max(x[1], a)];
|
||||
> 23 | }, [a, x]);
|
||||
| ^ This dependency may be modified later
|
||||
| ^ 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
|
||||
24 | arrayPush(y, 3);
|
||||
25 | return {result, y};
|
||||
26 | }
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -27,9 +27,9 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propB`, but the source dependencies were [propA, propB.x.y]. Inferred less specific property than source.
|
||||
The inferred dependency was `propB`, but the source dependencies were [propA, propB.x.y]. Inferred less specific property than source.
|
||||
|
||||
error.hoist-useCallback-conditional-access-own-scope.ts:5:21
|
||||
3 |
|
||||
@@ -47,10 +47,12 @@ error.hoist-useCallback-conditional-access-own-scope.ts:5:21
|
||||
> 10 | }
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
> 11 | }, [propA, propB.x.y]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
12 | }
|
||||
13 |
|
||||
14 | export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -30,9 +30,9 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```
|
||||
Found 2 errors:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propA`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source.
|
||||
The inferred dependency was `propA`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source.
|
||||
|
||||
error.hoist-useCallback-infer-conditional-value-block.ts:6:21
|
||||
4 |
|
||||
@@ -54,13 +54,15 @@ error.hoist-useCallback-infer-conditional-value-block.ts:6:21
|
||||
> 13 | }
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
> 14 | }, [propA.a, propB.x.y]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
15 | }
|
||||
16 |
|
||||
17 | export const FIXTURE_ENTRYPOINT = {
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propB`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source.
|
||||
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
The inferred dependency was `propB`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source.
|
||||
|
||||
error.hoist-useCallback-infer-conditional-value-block.ts:6:21
|
||||
4 |
|
||||
@@ -82,10 +84,12 @@ error.hoist-useCallback-infer-conditional-value-block.ts:6:21
|
||||
> 13 | }
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
> 14 | }, [propA.a, propB.x.y]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
15 | }
|
||||
16 |
|
||||
17 | export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -31,30 +31,30 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```
|
||||
Found 2 errors:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
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.
|
||||
Memoization: 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
|
||||
|
||||
error.invalid-useCallback-captures-reassigned-context.ts:12:37
|
||||
10 |
|
||||
11 | // makeArray() is captured, but depsList contains [props]
|
||||
> 12 | const cb = useCallback(() => [x], [x]);
|
||||
| ^ This dependency may be modified later
|
||||
| ^ 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
|
||||
13 |
|
||||
14 | x = makeArray();
|
||||
15 |
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
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.
|
||||
|
||||
Memoization: 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.
|
||||
|
||||
error.invalid-useCallback-captures-reassigned-context.ts:12:25
|
||||
10 |
|
||||
11 | // makeArray() is captured, but depsList contains [props]
|
||||
> 12 | const cb = useCallback(() => [x], [x]);
|
||||
| ^^^^^^^^^ Could not preserve existing memoization
|
||||
| ^^^^^^^^^ 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 |
|
||||
14 | x = makeArray();
|
||||
15 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@ function useHook(maybeRef) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `maybeRef.current`, but the source dependencies were [maybeRef]. Differences in ref.current access.
|
||||
The inferred dependency was `maybeRef.current`, but the source dependencies were [maybeRef]. Differences in ref.current access.
|
||||
|
||||
error.maybe-invalid-useCallback-read-maybeRef.ts:5:21
|
||||
3 |
|
||||
@@ -30,9 +30,11 @@ error.maybe-invalid-useCallback-read-maybeRef.ts:5:21
|
||||
> 6 | return [maybeRef.current];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 7 | }, [maybeRef]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
8 | }
|
||||
9 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@ function useHook(maybeRef, shouldRead) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `maybeRef.current`, but the source dependencies were [shouldRead, maybeRef]. Differences in ref.current access.
|
||||
The inferred dependency was `maybeRef.current`, but the source dependencies were [shouldRead, maybeRef]. Differences in ref.current access.
|
||||
|
||||
error.maybe-invalid-useMemo-read-maybeRef.ts:5:17
|
||||
3 |
|
||||
@@ -30,9 +30,11 @@ error.maybe-invalid-useMemo-read-maybeRef.ts:5:17
|
||||
> 6 | return () => [maybeRef.current];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 7 | }, [shouldRead, maybeRef]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
8 | }
|
||||
9 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -29,9 +29,9 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `ref`, but the source dependencies were []. Inferred dependency not present in source.
|
||||
The inferred dependency was `ref`, but the source dependencies were []. Inferred dependency not present in source.
|
||||
|
||||
error.preserve-use-memo-ref-missing-reactive.ts:9:21
|
||||
7 | const ref = cond ? ref1 : ref2;
|
||||
@@ -45,10 +45,12 @@ error.preserve-use-memo-ref-missing-reactive.ts:9:21
|
||||
> 12 | }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 13 | }, []);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
14 | }
|
||||
15 |
|
||||
16 | export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -29,18 +29,18 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
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.
|
||||
Memoization: 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.
|
||||
|
||||
error.todo-useCallback-captures-invalidating-value.ts:13:21
|
||||
11 | x.push(props);
|
||||
12 |
|
||||
> 13 | return useCallback(() => [x], [x]);
|
||||
| ^^^^^^^^^ Could not preserve existing memoization
|
||||
| ^^^^^^^^^ 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.
|
||||
14 | }
|
||||
15 |
|
||||
16 | export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -20,17 +20,19 @@ function useHook(x) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `aliasedX`, but the source dependencies were [x, aliasedProp]. Inferred different dependency than source.
|
||||
The inferred dependency was `aliasedX`, but the source dependencies were [x, aliasedProp]. Inferred different dependency than source.
|
||||
|
||||
error.useCallback-aliased-var.ts:9:21
|
||||
7 | const aliasedProp = x.y.z;
|
||||
8 |
|
||||
> 9 | return useCallback(() => [aliasedX, x.y.z], [x, aliasedProp]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
10 | }
|
||||
11 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -26,9 +26,9 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propB?.x.y`, but the source dependencies were [propA, propB.x.y]. Inferred different dependency than source.
|
||||
The inferred dependency was `propB?.x.y`, but the source dependencies were [propA, propB.x.y]. Inferred different dependency than source.
|
||||
|
||||
error.useCallback-conditional-access-noAlloc.ts:5:21
|
||||
3 |
|
||||
@@ -44,10 +44,12 @@ error.useCallback-conditional-access-noAlloc.ts:5:21
|
||||
> 9 | };
|
||||
| ^^^^^^^^^^^^
|
||||
> 10 | }, [propA, propB.x.y]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
11 | }
|
||||
12 |
|
||||
13 | export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ function Component({propA, propB}) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propB`, but the source dependencies were [propA?.a, propB.x.y]. Inferred less specific property than source.
|
||||
The inferred dependency was `propB`, but the source dependencies were [propA?.a, propB.x.y]. Inferred less specific property than source.
|
||||
|
||||
error.useCallback-infer-less-specific-conditional-access.ts:6:21
|
||||
4 |
|
||||
@@ -49,9 +49,11 @@ error.useCallback-infer-less-specific-conditional-access.ts:6:21
|
||||
> 13 | }
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
> 14 | }, [propA?.a, propB.x.y]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
15 | }
|
||||
16 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@ function Component({propA}) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propA`, but the source dependencies were [propA.x]. Inferred less specific property than source.
|
||||
The inferred dependency was `propA`, but the source dependencies were [propA.x]. Inferred less specific property than source.
|
||||
|
||||
error.useCallback-property-call-dep.ts:5:21
|
||||
3 |
|
||||
@@ -30,9 +30,11 @@ error.useCallback-property-call-dep.ts:5:21
|
||||
> 6 | return propA.x();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
> 7 | }, [propA.x]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
8 | }
|
||||
9 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -20,17 +20,19 @@ function useHook(x) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `x`, but the source dependencies were [aliasedX, aliasedProp]. Inferred different dependency than source.
|
||||
The inferred dependency was `x`, but the source dependencies were [aliasedX, aliasedProp]. Inferred different dependency than source.
|
||||
|
||||
error.useMemo-aliased-var.ts:9:17
|
||||
7 | const aliasedProp = x.y.z;
|
||||
8 |
|
||||
> 9 | return useMemo(() => [x, x.y.z], [aliasedX, aliasedProp]);
|
||||
| ^^^^^^^^^^^^^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^^^^^^^^^^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
10 | }
|
||||
11 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ function Component({propA, propB}) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propB`, but the source dependencies were [propA?.a, propB.x.y]. Inferred less specific property than source.
|
||||
The inferred dependency was `propB`, but the source dependencies were [propA?.a, propB.x.y]. Inferred less specific property than source.
|
||||
|
||||
error.useMemo-infer-less-specific-conditional-access.ts:6:17
|
||||
4 |
|
||||
@@ -49,9 +49,11 @@ error.useMemo-infer-less-specific-conditional-access.ts:6:17
|
||||
> 13 | }
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
> 14 | }, [propA?.a, propB.x.y]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
15 | }
|
||||
16 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ function Component({propA, propB}) {
|
||||
|
||||
```
|
||||
Found 2 errors:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propA`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source.
|
||||
The inferred dependency was `propA`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source.
|
||||
|
||||
error.useMemo-infer-less-specific-conditional-value-block.ts:6:17
|
||||
4 |
|
||||
@@ -49,12 +49,14 @@ error.useMemo-infer-less-specific-conditional-value-block.ts:6:17
|
||||
> 13 | }
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
> 14 | }, [propA.a, propB.x.y]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
15 | }
|
||||
16 |
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propB`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source.
|
||||
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
The inferred dependency was `propB`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source.
|
||||
|
||||
error.useMemo-infer-less-specific-conditional-value-block.ts:6:17
|
||||
4 |
|
||||
@@ -76,9 +78,11 @@ error.useMemo-infer-less-specific-conditional-value-block.ts:6:17
|
||||
> 13 | }
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
> 14 | }, [propA.a, propB.x.y]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
15 | }
|
||||
16 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@ function Component({propA}) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propA`, but the source dependencies were [propA.x]. Inferred less specific property than source.
|
||||
The inferred dependency was `propA`, but the source dependencies were [propA.x]. Inferred less specific property than source.
|
||||
|
||||
error.useMemo-property-call-chained-object.ts:5:17
|
||||
3 |
|
||||
@@ -36,9 +36,11 @@ error.useMemo-property-call-chained-object.ts:5:17
|
||||
> 8 | };
|
||||
| ^^^^^^^^^^^^
|
||||
> 9 | }, [propA.x]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
10 | }
|
||||
11 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@ function Component({propA}) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propA`, but the source dependencies were [propA.x]. Inferred less specific property than source.
|
||||
The inferred dependency was `propA`, but the source dependencies were [propA.x]. Inferred less specific property than source.
|
||||
|
||||
error.useMemo-property-call-dep.ts:5:17
|
||||
3 |
|
||||
@@ -30,9 +30,11 @@ error.useMemo-property-call-dep.ts:5:17
|
||||
> 6 | return propA.x();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
> 7 | }, [propA.x]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
8 | }
|
||||
9 |
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -31,9 +31,9 @@ function useFoo(input1) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `input1`, but the source dependencies were [y]. Inferred different dependency than source.
|
||||
The inferred dependency was `input1`, but the source dependencies were [y]. Inferred different dependency than source.
|
||||
|
||||
error.useMemo-unrelated-mutation-in-depslist.ts:16:27
|
||||
14 | const x = {};
|
||||
@@ -43,10 +43,12 @@ error.useMemo-unrelated-mutation-in-depslist.ts:16:27
|
||||
> 17 | return [y];
|
||||
| ^^^^^^^^^^^^^^^
|
||||
> 18 | }, [(mutate(x), y)]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
19 |
|
||||
20 | return [x, memoized];
|
||||
21 | }
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ function Component(props) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source.
|
||||
The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source.
|
||||
|
||||
error.todo-optional-member-expression-with-conditional-optional.ts:4:23
|
||||
2 | import {ValidateMemoization} from 'shared-runtime';
|
||||
@@ -47,10 +47,12 @@ error.todo-optional-member-expression-with-conditional-optional.ts:4:23
|
||||
> 10 | return x;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
> 11 | }, [props?.items, props.cond]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
12 | return (
|
||||
13 | <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />
|
||||
14 | );
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ function Component(props) {
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
Memoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source.
|
||||
The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source.
|
||||
|
||||
error.todo-optional-member-expression-with-conditional.ts:4:23
|
||||
2 | import {ValidateMemoization} from 'shared-runtime';
|
||||
@@ -47,10 +47,12 @@ error.todo-optional-member-expression-with-conditional.ts:4:23
|
||||
> 10 | return x;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
> 11 | }, [props?.items, props.cond]);
|
||||
| ^^^^ Could not preserve existing manual memoization
|
||||
| ^^^^ React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected
|
||||
12 | return (
|
||||
13 | <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />
|
||||
14 | );
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import {Stringify} from 'shared-runtime';
|
||||
|
||||
function Component(props) {
|
||||
const {a} = props;
|
||||
const {b, ...rest} = a;
|
||||
// Local mutation of `rest` is allowed since it is a newly allocated object
|
||||
rest.value = props.value;
|
||||
return <Stringify rest={rest} />;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{a: {b: 0, other: 'other'}, value: 42}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { Stringify } from "shared-runtime";
|
||||
|
||||
function Component(props) {
|
||||
const $ = _c(5);
|
||||
const { a } = props;
|
||||
let rest;
|
||||
if ($[0] !== a || $[1] !== props.value) {
|
||||
const { b, ...t0 } = a;
|
||||
rest = t0;
|
||||
|
||||
rest.value = props.value;
|
||||
$[0] = a;
|
||||
$[1] = props.value;
|
||||
$[2] = rest;
|
||||
} else {
|
||||
rest = $[2];
|
||||
}
|
||||
let t0;
|
||||
if ($[3] !== rest) {
|
||||
t0 = <Stringify rest={rest} />;
|
||||
$[3] = rest;
|
||||
$[4] = t0;
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ a: { b: 0, other: "other" }, value: 42 }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) <div>{"rest":{"other":"other","value":42}}</div>
|
||||
@@ -1,14 +0,0 @@
|
||||
import {Stringify} from 'shared-runtime';
|
||||
|
||||
function Component(props) {
|
||||
const {a} = props;
|
||||
const {b, ...rest} = a;
|
||||
// Local mutation of `rest` is allowed since it is a newly allocated object
|
||||
rest.value = props.value;
|
||||
return <Stringify rest={rest} />;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{a: {b: 0, other: 'other'}, value: 42}],
|
||||
};
|
||||
@@ -48,26 +48,32 @@ import { c as _c } from "react/compiler-runtime";
|
||||
import { StaticText1, Stringify, Text } from "shared-runtime";
|
||||
|
||||
function Component(props) {
|
||||
const $ = _c(4);
|
||||
const $ = _c(6);
|
||||
const { buttons } = props;
|
||||
let t0;
|
||||
let nonPrimaryButtons;
|
||||
if ($[0] !== buttons) {
|
||||
const [, ...nonPrimaryButtons] = buttons;
|
||||
|
||||
t0 = nonPrimaryButtons.map(_temp);
|
||||
[, ...nonPrimaryButtons] = buttons;
|
||||
$[0] = buttons;
|
||||
$[1] = t0;
|
||||
$[1] = nonPrimaryButtons;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
nonPrimaryButtons = $[1];
|
||||
}
|
||||
let t0;
|
||||
if ($[2] !== nonPrimaryButtons) {
|
||||
t0 = nonPrimaryButtons.map(_temp);
|
||||
$[2] = nonPrimaryButtons;
|
||||
$[3] = t0;
|
||||
} else {
|
||||
t0 = $[3];
|
||||
}
|
||||
const renderedNonPrimaryButtons = t0;
|
||||
let t1;
|
||||
if ($[2] !== renderedNonPrimaryButtons) {
|
||||
if ($[4] !== renderedNonPrimaryButtons) {
|
||||
t1 = <StaticText1>{renderedNonPrimaryButtons}</StaticText1>;
|
||||
$[2] = renderedNonPrimaryButtons;
|
||||
$[3] = t1;
|
||||
$[4] = renderedNonPrimaryButtons;
|
||||
$[5] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
t1 = $[5];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ function createBridge() {
|
||||
chrome.devtools.panels.elements.onSelectionChanged.removeListener(
|
||||
onBrowserElementSelectionChanged,
|
||||
);
|
||||
if (sourcesPanel && sourcesPanel.onSelectionChanged) {
|
||||
if (sourcesPanel) {
|
||||
currentSelectedSource = null;
|
||||
sourcesPanel.onSelectionChanged.removeListener(
|
||||
onBrowserSourceSelectionChanged,
|
||||
@@ -124,7 +124,7 @@ function createBridge() {
|
||||
chrome.devtools.panels.elements.onSelectionChanged.addListener(
|
||||
onBrowserElementSelectionChanged,
|
||||
);
|
||||
if (sourcesPanel && sourcesPanel.onSelectionChanged) {
|
||||
if (sourcesPanel) {
|
||||
sourcesPanel.onSelectionChanged.addListener(
|
||||
onBrowserSourceSelectionChanged,
|
||||
);
|
||||
@@ -317,7 +317,7 @@ function createSourcesEditorPanel() {
|
||||
}
|
||||
|
||||
const sourcesPanel = chrome.devtools.panels.sources;
|
||||
if (!sourcesPanel || !sourcesPanel.createSidebarPane) {
|
||||
if (!sourcesPanel) {
|
||||
// Firefox doesn't currently support extending the source panel.
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user