Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1517c63a78 | ||
|
|
5fbe88ab40 | ||
|
|
4f34cc4a2e | ||
|
|
3d14fcf03f | ||
|
|
edac0dded9 | ||
|
|
3586a7f9e8 | ||
|
|
f6fb1a07a5 | ||
|
|
7513996f20 | ||
|
|
bb4418d647 | ||
|
|
074e92777c | ||
|
|
ac7da9d46d | ||
|
|
0dca9c2471 | ||
|
|
b9af1404ea | ||
|
|
e9638c33d7 | ||
|
|
28d4bc496b | ||
|
|
dffacc7b80 | ||
|
|
da7487b681 | ||
|
|
9fec565a9b | ||
|
|
996d0eb055 | ||
|
|
d85ec5f5bd | ||
|
|
fe813143e2 | ||
|
|
2f0e7e570d | ||
|
|
56d0ddae18 | ||
|
|
345ca24f13 | ||
|
|
97cdd5d3c3 | ||
|
|
eb7f8b42c9 | ||
|
|
eed2560762 | ||
|
|
463b808176 | ||
|
|
96c61b7f1f | ||
|
|
0bfa404bac | ||
|
|
81e1ee7476 | ||
|
|
4a3ff8eed6 |
@@ -474,7 +474,7 @@ module.exports = {
|
||||
{
|
||||
files: ['packages/react-server-dom-turbopack/**/*.js'],
|
||||
globals: {
|
||||
__turbopack_load__: 'readonly',
|
||||
__turbopack_load_by_url__: 'readonly',
|
||||
__turbopack_require__: 'readonly',
|
||||
},
|
||||
},
|
||||
|
||||
44
.github/workflows/runtime_build_and_test.yml
vendored
44
.github/workflows/runtime_build_and_test.yml
vendored
@@ -6,6 +6,12 @@ on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- compiler/**
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
commit_sha:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
permissions: {}
|
||||
|
||||
@@ -28,7 +34,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}
|
||||
- name: Check cache hit
|
||||
uses: actions/cache/restore@v4
|
||||
id: node_modules
|
||||
@@ -69,7 +75,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}
|
||||
- name: Check cache hit
|
||||
uses: actions/cache/restore@v4
|
||||
id: node_modules
|
||||
@@ -117,7 +123,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}
|
||||
- uses: actions/github-script@v7
|
||||
id: set-matrix
|
||||
with:
|
||||
@@ -136,7 +142,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
@@ -166,7 +172,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
@@ -198,7 +204,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
@@ -254,7 +260,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
@@ -325,7 +331,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
@@ -420,7 +426,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
@@ -465,7 +471,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
@@ -493,7 +499,7 @@ jobs:
|
||||
merge-multiple: true
|
||||
- name: Display structure of build
|
||||
run: ls -R build
|
||||
- run: echo ${{ github.event.pull_request.head.sha || github.sha }} >> build/COMMIT_SHA
|
||||
- run: echo ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }} >> build/COMMIT_SHA
|
||||
- name: Scrape warning messages
|
||||
run: |
|
||||
mkdir -p ./build/__test_utils__
|
||||
@@ -530,7 +536,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
@@ -570,7 +576,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
@@ -607,7 +613,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
@@ -648,7 +654,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
@@ -722,7 +728,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
@@ -779,7 +785,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
@@ -824,7 +830,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
@@ -873,7 +879,7 @@ jobs:
|
||||
node ./scripts/print-warnings/print-warnings.js > build/__test_utils__/ReactAllWarnings.js
|
||||
- name: Display structure of build for PR
|
||||
run: ls -R build
|
||||
- run: echo ${{ github.event.pull_request.head.sha || github.sha }} >> build/COMMIT_SHA
|
||||
- run: echo ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }} >> build/COMMIT_SHA
|
||||
- run: node ./scripts/tasks/danger
|
||||
- name: Archive sizebot results
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
@@ -15,6 +15,11 @@ export enum ErrorSeverity {
|
||||
* misunderstanding on the user’s part.
|
||||
*/
|
||||
InvalidJS = 'InvalidJS',
|
||||
/**
|
||||
* JS syntax that is not supported and which we do not plan to support. Developers should
|
||||
* rewrite to use supported forms.
|
||||
*/
|
||||
UnsupportedJS = 'UnsupportedJS',
|
||||
/**
|
||||
* Code that breaks the rules of React.
|
||||
*/
|
||||
@@ -241,12 +246,16 @@ export class CompilerError extends Error {
|
||||
case ErrorSeverity.InvalidJS:
|
||||
case ErrorSeverity.InvalidReact:
|
||||
case ErrorSeverity.InvalidConfig:
|
||||
case ErrorSeverity.UnsupportedJS: {
|
||||
return true;
|
||||
}
|
||||
case ErrorSeverity.CannotPreserveMemoization:
|
||||
case ErrorSeverity.Todo:
|
||||
case ErrorSeverity.Todo: {
|
||||
return false;
|
||||
default:
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(detail.severity, 'Unhandled error severity');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ import {validateLocalsNotReassignedAfterRender} from '../Validation/ValidateLoca
|
||||
import {outlineFunctions} from '../Optimization/OutlineFunctions';
|
||||
import {propagatePhiTypes} from '../TypeInference/PropagatePhiTypes';
|
||||
import {lowerContextAccess} from '../Optimization/LowerContextAccess';
|
||||
import {validateNoSetStateInPassiveEffects} from '../Validation/ValidateNoSetStateInPassiveEffects';
|
||||
import {validateNoSetStateInEffects} from '../Validation/ValidateNoSetStateInEffects';
|
||||
import {validateNoJSXInTryStatement} from '../Validation/ValidateNoJSXInTryStatement';
|
||||
import {propagateScopeDependenciesHIR} from '../HIR/PropagateScopeDependenciesHIR';
|
||||
import {outlineJSX} from '../Optimization/OutlineJsx';
|
||||
@@ -292,8 +292,8 @@ function runWithEnvironment(
|
||||
validateNoSetStateInRender(hir).unwrap();
|
||||
}
|
||||
|
||||
if (env.config.validateNoSetStateInPassiveEffects) {
|
||||
env.logErrors(validateNoSetStateInPassiveEffects(hir));
|
||||
if (env.config.validateNoSetStateInEffects) {
|
||||
env.logErrors(validateNoSetStateInEffects(hir));
|
||||
}
|
||||
|
||||
if (env.config.validateNoJSXInTryStatements) {
|
||||
|
||||
@@ -35,8 +35,41 @@ function throwInvalidReact(
|
||||
});
|
||||
CompilerError.throw(detail);
|
||||
}
|
||||
|
||||
function isAutodepsSigil(
|
||||
arg: NodePath<t.ArgumentPlaceholder | t.SpreadElement | t.Expression>,
|
||||
): boolean {
|
||||
// Check for AUTODEPS identifier imported from React
|
||||
if (arg.isIdentifier() && arg.node.name === 'AUTODEPS') {
|
||||
const binding = arg.scope.getBinding(arg.node.name);
|
||||
if (binding && binding.path.isImportSpecifier()) {
|
||||
const importSpecifier = binding.path.node as t.ImportSpecifier;
|
||||
if (importSpecifier.imported.type === 'Identifier') {
|
||||
return (importSpecifier.imported as t.Identifier).name === 'AUTODEPS';
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for React.AUTODEPS member expression
|
||||
if (arg.isMemberExpression() && !arg.node.computed) {
|
||||
const object = arg.get('object');
|
||||
const property = arg.get('property');
|
||||
|
||||
if (
|
||||
object.isIdentifier() &&
|
||||
object.node.name === 'React' &&
|
||||
property.isIdentifier() &&
|
||||
property.node.name === 'AUTODEPS'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
function assertValidEffectImportReference(
|
||||
numArgs: number,
|
||||
autodepsIndex: number,
|
||||
paths: Array<NodePath<t.Node>>,
|
||||
context: TraversalState,
|
||||
): void {
|
||||
@@ -49,11 +82,10 @@ function assertValidEffectImportReference(
|
||||
maybeCalleeLoc != null &&
|
||||
context.inferredEffectLocations.has(maybeCalleeLoc);
|
||||
/**
|
||||
* Only error on untransformed references of the form `useMyEffect(...)`
|
||||
* or `moduleNamespace.useMyEffect(...)`, with matching argument counts.
|
||||
* TODO: do we also want a mode to also hard error on non-call references?
|
||||
* Error on effect calls that still have AUTODEPS in their args
|
||||
*/
|
||||
if (args.length === numArgs && !hasInferredEffect) {
|
||||
const hasAutodepsArg = args.some(isAutodepsSigil);
|
||||
if (hasAutodepsArg && !hasInferredEffect) {
|
||||
const maybeErrorDiagnostic = matchCompilerDiagnostic(
|
||||
path,
|
||||
context.transformErrors,
|
||||
@@ -128,12 +160,12 @@ export default function validateNoUntransformedReferences(
|
||||
if (env.inferEffectDependencies) {
|
||||
for (const {
|
||||
function: {source, importSpecifierName},
|
||||
numRequiredArgs,
|
||||
autodepsIndex,
|
||||
} of env.inferEffectDependencies) {
|
||||
const module = getOrInsertWith(moduleLoadChecks, source, () => new Map());
|
||||
module.set(
|
||||
importSpecifierName,
|
||||
assertValidEffectImportReference.bind(null, numRequiredArgs),
|
||||
assertValidEffectImportReference.bind(null, autodepsIndex),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1359,7 +1359,7 @@ function lowerStatement(
|
||||
builder.errors.push({
|
||||
reason: `JavaScript 'with' syntax is not supported`,
|
||||
description: `'with' syntax is considered deprecated and removed from JavaScript standards, consider alternatives`,
|
||||
severity: ErrorSeverity.InvalidJS,
|
||||
severity: ErrorSeverity.UnsupportedJS,
|
||||
loc: stmtPath.node.loc ?? null,
|
||||
suggestions: null,
|
||||
});
|
||||
@@ -1371,13 +1371,15 @@ function lowerStatement(
|
||||
return;
|
||||
}
|
||||
case 'ClassDeclaration': {
|
||||
/*
|
||||
* We can in theory support nested classes, similarly to functions where we track values
|
||||
* captured by the class and consider mutations of the instances to mutate the class itself
|
||||
/**
|
||||
* In theory we could support inline class declarations, but this is rare enough in practice
|
||||
* and complex enough to support that we don't anticipate supporting anytime soon. Developers
|
||||
* are encouraged to lift classes out of component/hook declarations.
|
||||
*/
|
||||
builder.errors.push({
|
||||
reason: `Support nested class declarations`,
|
||||
severity: ErrorSeverity.Todo,
|
||||
reason: 'Inline `class` declarations are not supported',
|
||||
description: `Move class declarations outside of components/hooks`,
|
||||
severity: ErrorSeverity.UnsupportedJS,
|
||||
loc: stmtPath.node.loc ?? null,
|
||||
suggestions: null,
|
||||
});
|
||||
@@ -1388,10 +1390,48 @@ function lowerStatement(
|
||||
});
|
||||
return;
|
||||
}
|
||||
case 'TypeAlias':
|
||||
case 'TSInterfaceDeclaration':
|
||||
case 'TSTypeAliasDeclaration': {
|
||||
// We do not preserve type annotations/syntax through transformation
|
||||
case 'EnumDeclaration':
|
||||
case 'TSEnumDeclaration': {
|
||||
lowerValueToTemporary(builder, {
|
||||
kind: 'UnsupportedNode',
|
||||
loc: stmtPath.node.loc ?? GeneratedSource,
|
||||
node: stmtPath.node,
|
||||
});
|
||||
return;
|
||||
}
|
||||
case 'ExportAllDeclaration':
|
||||
case 'ExportDefaultDeclaration':
|
||||
case 'ExportNamedDeclaration':
|
||||
case 'ImportDeclaration':
|
||||
case 'TSExportAssignment':
|
||||
case 'TSImportEqualsDeclaration': {
|
||||
builder.errors.push({
|
||||
reason:
|
||||
'JavaScript `import` and `export` statements may only appear at the top level of a module',
|
||||
severity: ErrorSeverity.InvalidJS,
|
||||
loc: stmtPath.node.loc ?? null,
|
||||
suggestions: null,
|
||||
});
|
||||
lowerValueToTemporary(builder, {
|
||||
kind: 'UnsupportedNode',
|
||||
loc: stmtPath.node.loc ?? GeneratedSource,
|
||||
node: stmtPath.node,
|
||||
});
|
||||
return;
|
||||
}
|
||||
case 'TSNamespaceExportDeclaration': {
|
||||
builder.errors.push({
|
||||
reason:
|
||||
'TypeScript `namespace` statements may only appear at the top level of a module',
|
||||
severity: ErrorSeverity.InvalidJS,
|
||||
loc: stmtPath.node.loc ?? null,
|
||||
suggestions: null,
|
||||
});
|
||||
lowerValueToTemporary(builder, {
|
||||
kind: 'UnsupportedNode',
|
||||
loc: stmtPath.node.loc ?? GeneratedSource,
|
||||
node: stmtPath.node,
|
||||
});
|
||||
return;
|
||||
}
|
||||
case 'DeclareClass':
|
||||
@@ -1404,30 +1444,14 @@ function lowerStatement(
|
||||
case 'DeclareOpaqueType':
|
||||
case 'DeclareTypeAlias':
|
||||
case 'DeclareVariable':
|
||||
case 'EnumDeclaration':
|
||||
case 'ExportAllDeclaration':
|
||||
case 'ExportDefaultDeclaration':
|
||||
case 'ExportNamedDeclaration':
|
||||
case 'ImportDeclaration':
|
||||
case 'InterfaceDeclaration':
|
||||
case 'OpaqueType':
|
||||
case 'TSDeclareFunction':
|
||||
case 'TSEnumDeclaration':
|
||||
case 'TSExportAssignment':
|
||||
case 'TSImportEqualsDeclaration':
|
||||
case 'TSInterfaceDeclaration':
|
||||
case 'TSModuleDeclaration':
|
||||
case 'TSNamespaceExportDeclaration': {
|
||||
builder.errors.push({
|
||||
reason: `(BuildHIR::lowerStatement) Handle ${stmtPath.type} statements`,
|
||||
severity: ErrorSeverity.Todo,
|
||||
loc: stmtPath.node.loc ?? null,
|
||||
suggestions: null,
|
||||
});
|
||||
lowerValueToTemporary(builder, {
|
||||
kind: 'UnsupportedNode',
|
||||
loc: stmtPath.node.loc ?? GeneratedSource,
|
||||
node: stmtPath.node,
|
||||
});
|
||||
case 'TSTypeAliasDeclaration':
|
||||
case 'TypeAlias': {
|
||||
// We do not preserve type annotations/syntax through transformation
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
@@ -2977,6 +3001,8 @@ function isReorderableExpression(
|
||||
}
|
||||
}
|
||||
}
|
||||
case 'TSAsExpression':
|
||||
case 'TSNonNullExpression':
|
||||
case 'TypeCastExpression': {
|
||||
return isReorderableExpression(
|
||||
builder,
|
||||
@@ -3538,7 +3564,7 @@ function lowerIdentifier(
|
||||
reason: `The 'eval' function is not supported`,
|
||||
description:
|
||||
'Eval is an anti-pattern in JavaScript, and the code executed cannot be evaluated by React Compiler',
|
||||
severity: ErrorSeverity.InvalidJS,
|
||||
severity: ErrorSeverity.UnsupportedJS,
|
||||
loc: exprPath.node.loc ?? null,
|
||||
suggestions: null,
|
||||
});
|
||||
|
||||
@@ -265,21 +265,19 @@ export const EnvironmentConfigSchema = z.object({
|
||||
* {
|
||||
* module: 'react',
|
||||
* imported: 'useEffect',
|
||||
* numRequiredArgs: 1,
|
||||
* autodepsIndex: 1,
|
||||
* },{
|
||||
* module: 'MyExperimentalEffectHooks',
|
||||
* imported: 'useExperimentalEffect',
|
||||
* numRequiredArgs: 2,
|
||||
* autodepsIndex: 2,
|
||||
* },
|
||||
* ]
|
||||
* would insert dependencies for calls of `useEffect` imported from `react` and calls of
|
||||
* useExperimentalEffect` from `MyExperimentalEffectHooks`.
|
||||
*
|
||||
* `numRequiredArgs` tells the compiler the amount of arguments required to append a dependency
|
||||
* array to the end of the call. With the configuration above, we'd insert dependencies for
|
||||
* `useEffect` if it is only given a single argument and it would be appended to the argument list.
|
||||
*
|
||||
* numRequiredArgs must always be greater than 0, otherwise there is no function to analyze for dependencies
|
||||
* `autodepsIndex` tells the compiler which index we expect the AUTODEPS to appear in.
|
||||
* With the configuration above, we'd insert dependencies for `useEffect` if it has two
|
||||
* arguments, and the second is AUTODEPS.
|
||||
*
|
||||
* Still experimental.
|
||||
*/
|
||||
@@ -288,7 +286,7 @@ export const EnvironmentConfigSchema = z.object({
|
||||
z.array(
|
||||
z.object({
|
||||
function: ExternalFunctionSchema,
|
||||
numRequiredArgs: z.number().min(1, 'numRequiredArgs must be > 0'),
|
||||
autodepsIndex: z.number().min(1, 'autodepsIndex must be > 0'),
|
||||
}),
|
||||
),
|
||||
)
|
||||
@@ -320,10 +318,10 @@ export const EnvironmentConfigSchema = z.object({
|
||||
validateNoSetStateInRender: z.boolean().default(true),
|
||||
|
||||
/**
|
||||
* Validates that setState is not called directly within a passive effect (useEffect).
|
||||
* Validates that setState is not called synchronously within an effect (useEffect and friends).
|
||||
* Scheduling a setState (with an event listener, subscription, etc) is valid.
|
||||
*/
|
||||
validateNoSetStateInPassiveEffects: z.boolean().default(false),
|
||||
validateNoSetStateInEffects: z.boolean().default(false),
|
||||
|
||||
/**
|
||||
* Validates against creating JSX within a try block and recommends using an error boundary
|
||||
|
||||
@@ -9,6 +9,7 @@ import {Effect, ValueKind, ValueReason} from './HIR';
|
||||
import {
|
||||
BUILTIN_SHAPES,
|
||||
BuiltInArrayId,
|
||||
BuiltInAutodepsId,
|
||||
BuiltInFireFunctionId,
|
||||
BuiltInFireId,
|
||||
BuiltInMapId,
|
||||
@@ -780,6 +781,7 @@ const REACT_APIS: Array<[string, BuiltInType]> = [
|
||||
BuiltInUseEffectEventId,
|
||||
),
|
||||
],
|
||||
['AUTODEPS', addObject(DEFAULT_SHAPES, BuiltInAutodepsId, [])],
|
||||
];
|
||||
|
||||
TYPED_GLOBALS.push(
|
||||
|
||||
@@ -384,6 +384,7 @@ export const BuiltInFireId = 'BuiltInFire';
|
||||
export const BuiltInFireFunctionId = 'BuiltInFireFunction';
|
||||
export const BuiltInUseEffectEventId = 'BuiltInUseEffectEvent';
|
||||
export const BuiltinEffectEventId = 'BuiltInEffectEventFunction';
|
||||
export const BuiltInAutodepsId = 'BuiltInAutoDepsId';
|
||||
|
||||
// See getReanimatedModuleType() in Globals.ts — this is part of supporting Reanimated's ref-like types
|
||||
export const ReanimatedSharedValueId = 'ReanimatedSharedValueId';
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import generate from '@babel/generator';
|
||||
import {CompilerError} from '../CompilerError';
|
||||
import {printReactiveScopeSummary} from '../ReactiveScopes/PrintReactiveFunction';
|
||||
import DisjointSet from '../Utils/DisjointSet';
|
||||
@@ -466,7 +465,7 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
|
||||
break;
|
||||
}
|
||||
case 'UnsupportedNode': {
|
||||
value = `UnsupportedNode(${generate(instrValue.node).code})`;
|
||||
value = `UnsupportedNode ${instrValue.node.type}`;
|
||||
break;
|
||||
}
|
||||
case 'LoadLocal': {
|
||||
|
||||
@@ -57,6 +57,8 @@ import {
|
||||
} from '../HIR/visitors';
|
||||
import {empty} from '../Utils/Stack';
|
||||
import {getOrInsertWith} from '../Utils/utils';
|
||||
import {deadCodeElimination} from '../Optimization';
|
||||
import {BuiltInAutodepsId} from '../HIR/ObjectShape';
|
||||
|
||||
/**
|
||||
* Infers reactive dependencies captured by useEffect lambdas and adds them as
|
||||
@@ -77,7 +79,7 @@ export function inferEffectDependencies(fn: HIRFunction): void {
|
||||
);
|
||||
moduleTargets.set(
|
||||
effectTarget.function.importSpecifierName,
|
||||
effectTarget.numRequiredArgs,
|
||||
effectTarget.autodepsIndex,
|
||||
);
|
||||
}
|
||||
const autodepFnLoads = new Map<IdentifierId, number>();
|
||||
@@ -135,7 +137,6 @@ export function inferEffectDependencies(fn: HIRFunction): void {
|
||||
}
|
||||
} else if (value.kind === 'LoadGlobal') {
|
||||
loadGlobals.add(lvalue.identifier.id);
|
||||
|
||||
/*
|
||||
* TODO: Handle properties on default exports, like
|
||||
* import React from 'react';
|
||||
@@ -169,8 +170,22 @@ export function inferEffectDependencies(fn: HIRFunction): void {
|
||||
) {
|
||||
const callee =
|
||||
value.kind === 'CallExpression' ? value.callee : value.property;
|
||||
|
||||
const autodepsArgIndex = value.args.findIndex(
|
||||
arg =>
|
||||
arg.kind === 'Identifier' &&
|
||||
arg.identifier.type.kind === 'Object' &&
|
||||
arg.identifier.type.shapeId === BuiltInAutodepsId,
|
||||
);
|
||||
const autodepsArgExpectedIndex = autodepFnLoads.get(
|
||||
callee.identifier.id,
|
||||
);
|
||||
|
||||
if (
|
||||
value.args.length === autodepFnLoads.get(callee.identifier.id) &&
|
||||
value.args.length > 0 &&
|
||||
autodepsArgExpectedIndex != null &&
|
||||
autodepsArgIndex === autodepsArgExpectedIndex &&
|
||||
autodepFnLoads.has(callee.identifier.id) &&
|
||||
value.args[0].kind === 'Identifier'
|
||||
) {
|
||||
// We have a useEffect call with no deps array, so we need to infer the deps
|
||||
@@ -260,7 +275,10 @@ export function inferEffectDependencies(fn: HIRFunction): void {
|
||||
effects: null,
|
||||
},
|
||||
});
|
||||
value.args.push({...depsPlace, effect: Effect.Freeze});
|
||||
value.args[autodepsArgIndex] = {
|
||||
...depsPlace,
|
||||
effect: Effect.Freeze,
|
||||
};
|
||||
fn.env.inferredEffectLocations.add(callee.loc);
|
||||
} else if (loadGlobals.has(value.args[0].identifier.id)) {
|
||||
// Global functions have no reactive dependencies, so we can insert an empty array
|
||||
@@ -275,7 +293,10 @@ export function inferEffectDependencies(fn: HIRFunction): void {
|
||||
effects: null,
|
||||
},
|
||||
});
|
||||
value.args.push({...depsPlace, effect: Effect.Freeze});
|
||||
value.args[autodepsArgIndex] = {
|
||||
...depsPlace,
|
||||
effect: Effect.Freeze,
|
||||
};
|
||||
fn.env.inferredEffectLocations.add(callee.loc);
|
||||
}
|
||||
} else if (
|
||||
@@ -323,6 +344,7 @@ export function inferEffectDependencies(fn: HIRFunction): void {
|
||||
// Renumber instructions and fix scope ranges
|
||||
markInstructionIds(fn.body);
|
||||
fixScopeAndIdentifierRanges(fn.body);
|
||||
deadCodeElimination(fn);
|
||||
|
||||
fn.env.hasInferredEffect = true;
|
||||
}
|
||||
@@ -408,6 +430,7 @@ function rewriteSplices(
|
||||
rewriteBlocks.push(currBlock);
|
||||
|
||||
let cursor = 0;
|
||||
|
||||
for (const rewrite of splices) {
|
||||
while (originalInstrs[cursor].id < rewrite.location) {
|
||||
CompilerError.invariant(
|
||||
@@ -429,7 +452,7 @@ function rewriteSplices(
|
||||
|
||||
if (rewrite.kind === 'instr') {
|
||||
currBlock.instructions.push(rewrite.value);
|
||||
} else {
|
||||
} else if (rewrite.kind === 'block') {
|
||||
const {entry, blocks} = rewrite.value;
|
||||
const entryBlock = blocks.get(entry)!;
|
||||
// splice in all instructions from the entry block
|
||||
|
||||
@@ -829,12 +829,14 @@ class CollectDependenciesVisitor extends ReactiveFunctionVisitor<
|
||||
};
|
||||
}
|
||||
case 'UnsupportedNode': {
|
||||
CompilerError.invariant(false, {
|
||||
reason: `Unexpected unsupported node`,
|
||||
description: null,
|
||||
loc: value.loc,
|
||||
suggestions: null,
|
||||
});
|
||||
const lvalues = [];
|
||||
if (lvalue !== null) {
|
||||
lvalues.push({place: lvalue, level: MemoizationLevel.Never});
|
||||
}
|
||||
return {
|
||||
lvalues,
|
||||
rvalues: [],
|
||||
};
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(
|
||||
|
||||
@@ -75,21 +75,21 @@ const testComplexConfigDefaults: PartialEnvironmentConfig = {
|
||||
source: 'react',
|
||||
importSpecifierName: 'useEffect',
|
||||
},
|
||||
numRequiredArgs: 1,
|
||||
autodepsIndex: 1,
|
||||
},
|
||||
{
|
||||
function: {
|
||||
source: 'shared-runtime',
|
||||
importSpecifierName: 'useSpecialEffect',
|
||||
},
|
||||
numRequiredArgs: 2,
|
||||
autodepsIndex: 2,
|
||||
},
|
||||
{
|
||||
function: {
|
||||
source: 'useEffectWrapper',
|
||||
importSpecifierName: 'default',
|
||||
},
|
||||
numRequiredArgs: 1,
|
||||
autodepsIndex: 1,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -11,20 +11,22 @@ import {
|
||||
IdentifierId,
|
||||
isSetStateType,
|
||||
isUseEffectHookType,
|
||||
isUseInsertionEffectHookType,
|
||||
isUseLayoutEffectHookType,
|
||||
Place,
|
||||
} from '../HIR';
|
||||
import {eachInstructionValueOperand} from '../HIR/visitors';
|
||||
import {Result} from '../Utils/Result';
|
||||
|
||||
/**
|
||||
* Validates against calling setState in the body of a *passive* effect (useEffect),
|
||||
* Validates against calling setState in the body of an effect (useEffect and friends),
|
||||
* while allowing calling setState in callbacks scheduled by the effect.
|
||||
*
|
||||
* Calling setState during execution of a useEffect triggers a re-render, which is
|
||||
* often bad for performance and frequently has more efficient and straightforward
|
||||
* alternatives. See https://react.dev/learn/you-might-not-need-an-effect for examples.
|
||||
*/
|
||||
export function validateNoSetStateInPassiveEffects(
|
||||
export function validateNoSetStateInEffects(
|
||||
fn: HIRFunction,
|
||||
): Result<void, CompilerError> {
|
||||
const setStateFunctions: Map<IdentifierId, Place> = new Map();
|
||||
@@ -79,7 +81,11 @@ export function validateNoSetStateInPassiveEffects(
|
||||
instr.value.kind === 'MethodCall'
|
||||
? instr.value.receiver
|
||||
: instr.value.callee;
|
||||
if (isUseEffectHookType(callee.identifier)) {
|
||||
if (
|
||||
isUseEffectHookType(callee.identifier) ||
|
||||
isUseLayoutEffectHookType(callee.identifier) ||
|
||||
isUseInsertionEffectHookType(callee.identifier)
|
||||
) {
|
||||
const arg = instr.value.args[0];
|
||||
if (arg !== undefined && arg.kind === 'Identifier') {
|
||||
const setState = setStateFunctions.get(arg.identifier.id);
|
||||
@@ -33,12 +33,12 @@ describe('parseConfigPragma()', () => {
|
||||
source: 'react',
|
||||
importSpecifierName: 'useEffect',
|
||||
},
|
||||
numRequiredArgs: 0,
|
||||
autodepsIndex: 0,
|
||||
},
|
||||
],
|
||||
} as any);
|
||||
}).toThrowErrorMatchingInlineSnapshot(
|
||||
`"InvalidConfig: Could not validate environment config. Update React Compiler config to fix the error. Validation error: numRequiredArgs must be > 0 at "inferEffectDependencies[0].numRequiredArgs""`,
|
||||
`"InvalidConfig: Could not validate environment config. Update React Compiler config to fix the error. Validation error: autodepsIndex must be > 0 at "inferEffectDependencies[0].autodepsIndex""`,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ function Component(props) {
|
||||
```
|
||||
1 | function Component(props) {
|
||||
> 2 | eval('props.x = true');
|
||||
| ^^^^ InvalidJS: The 'eval' function is not supported. Eval is an anti-pattern in JavaScript, and the code executed cannot be evaluated by React Compiler (2:2)
|
||||
| ^^^^ UnsupportedJS: The 'eval' function is not supported. Eval is an anti-pattern in JavaScript, and the code executed cannot be evaluated by React Compiler (2:2)
|
||||
3 | return <div />;
|
||||
4 | }
|
||||
5 |
|
||||
|
||||
@@ -84,7 +84,7 @@ let moduleLocal = false;
|
||||
> 3 | var x = [];
|
||||
| ^^^^^^^^^^^ Todo: (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration (3:3)
|
||||
|
||||
Todo: Support nested class declarations (5:10)
|
||||
UnsupportedJS: Inline `class` declarations are not supported. Move class declarations outside of components/hooks (5:10)
|
||||
|
||||
Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement (20:22)
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @flow
|
||||
function Component(props) {
|
||||
enum Bool {
|
||||
True = 'true',
|
||||
False = 'false',
|
||||
}
|
||||
|
||||
let bool: Bool = Bool.False;
|
||||
if (props.value) {
|
||||
bool = Bool.True;
|
||||
}
|
||||
return <div>{bool}</div>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{value: true}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
function Component(props) {
|
||||
const $ = _c(2);
|
||||
enum Bool {
|
||||
True = "true",
|
||||
False = "false",
|
||||
}
|
||||
|
||||
let bool = Bool.False;
|
||||
if (props.value) {
|
||||
bool = Bool.True;
|
||||
}
|
||||
let t0;
|
||||
if ($[0] !== bool) {
|
||||
t0 = <div>{bool}</div>;
|
||||
$[0] = bool;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ value: true }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: exception) Bool is not defined
|
||||
@@ -0,0 +1,18 @@
|
||||
// @flow
|
||||
function Component(props) {
|
||||
enum Bool {
|
||||
True = 'true',
|
||||
False = 'false',
|
||||
}
|
||||
|
||||
let bool: Bool = Bool.False;
|
||||
if (props.value) {
|
||||
bool = Bool.True;
|
||||
}
|
||||
return <div>{bool}</div>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{value: true}],
|
||||
};
|
||||
@@ -3,13 +3,13 @@
|
||||
|
||||
```javascript
|
||||
// @dynamicGating:{"source":"shared-runtime"} @panicThreshold:"none" @inferEffectDependencies
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function ReactiveVariable({propVal}) {
|
||||
'use memo if(invalid identifier)';
|
||||
const arr = [propVal];
|
||||
useEffect(() => print(arr));
|
||||
useEffect(() => print(arr), AUTODEPS);
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
@@ -25,8 +25,8 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
```
|
||||
6 | 'use memo if(invalid identifier)';
|
||||
7 | const arr = [propVal];
|
||||
> 8 | useEffect(() => print(arr));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (8:8)
|
||||
> 8 | useEffect(() => print(arr), AUTODEPS);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (8:8)
|
||||
9 | }
|
||||
10 |
|
||||
11 | export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// @dynamicGating:{"source":"shared-runtime"} @panicThreshold:"none" @inferEffectDependencies
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function ReactiveVariable({propVal}) {
|
||||
'use memo if(invalid identifier)';
|
||||
const arr = [propVal];
|
||||
useEffect(() => print(arr));
|
||||
useEffect(() => print(arr), AUTODEPS);
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
```javascript
|
||||
// @inferEffectDependencies @compilationMode:"infer" @panicThreshold:"none"
|
||||
import useMyEffect from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
function nonReactFn(arg) {
|
||||
useMyEffect(() => [1, 2, arg]);
|
||||
useMyEffect(() => [1, 2, arg], AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -15,12 +16,12 @@ function nonReactFn(arg) {
|
||||
## Error
|
||||
|
||||
```
|
||||
3 |
|
||||
4 | function nonReactFn(arg) {
|
||||
> 5 | useMyEffect(() => [1, 2, arg]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (5:5)
|
||||
6 | }
|
||||
7 |
|
||||
4 |
|
||||
5 | function nonReactFn(arg) {
|
||||
> 6 | useMyEffect(() => [1, 2, arg], AUTODEPS);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (6:6)
|
||||
7 | }
|
||||
8 |
|
||||
```
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// @inferEffectDependencies @compilationMode:"infer" @panicThreshold:"none"
|
||||
import useMyEffect from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
function nonReactFn(arg) {
|
||||
useMyEffect(() => [1, 2, arg]);
|
||||
useMyEffect(() => [1, 2, arg], AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @compilationMode:"infer" @panicThreshold:"none"
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
|
||||
function nonReactFn(arg) {
|
||||
useEffect(() => [1, 2, arg]);
|
||||
useEffect(() => [1, 2, arg], AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -17,8 +17,8 @@ function nonReactFn(arg) {
|
||||
```
|
||||
3 |
|
||||
4 | function nonReactFn(arg) {
|
||||
> 5 | useEffect(() => [1, 2, arg]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (5:5)
|
||||
> 5 | useEffect(() => [1, 2, arg], AUTODEPS);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (5:5)
|
||||
6 | }
|
||||
7 |
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @inferEffectDependencies @compilationMode:"infer" @panicThreshold:"none"
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
|
||||
function nonReactFn(arg) {
|
||||
useEffect(() => [1, 2, arg]);
|
||||
useEffect(() => [1, 2, arg], AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @panicThreshold:"none"
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
|
||||
/**
|
||||
* Error on non-inlined effect functions:
|
||||
@@ -21,7 +21,7 @@ function Component({foo}) {
|
||||
}
|
||||
|
||||
// No inferred dep array, the argument is not a lambda
|
||||
useEffect(f);
|
||||
useEffect(f, AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -32,8 +32,8 @@ function Component({foo}) {
|
||||
```
|
||||
18 |
|
||||
19 | // No inferred dep array, the argument is not a lambda
|
||||
> 20 | useEffect(f);
|
||||
| ^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (20:20)
|
||||
> 20 | useEffect(f, AUTODEPS);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (20:20)
|
||||
21 | }
|
||||
22 |
|
||||
```
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @inferEffectDependencies @panicThreshold:"none"
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
|
||||
/**
|
||||
* Error on non-inlined effect functions:
|
||||
@@ -17,5 +17,5 @@ function Component({foo}) {
|
||||
}
|
||||
|
||||
// No inferred dep array, the argument is not a lambda
|
||||
useEffect(f);
|
||||
useEffect(f, AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// @dynamicGating:{"source":"shared-runtime"} @inferEffectDependencies @panicThreshold:"none"
|
||||
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
/**
|
||||
* TODO: run the non-forget enabled version through the effect inference
|
||||
@@ -13,7 +14,7 @@ import useEffectWrapper from 'useEffectWrapper';
|
||||
function Component({foo}) {
|
||||
'use memo if(getTrue)';
|
||||
const arr = [];
|
||||
useEffectWrapper(() => arr.push(foo));
|
||||
useEffectWrapper(() => arr.push(foo), AUTODEPS);
|
||||
arr.push(2);
|
||||
return arr;
|
||||
}
|
||||
@@ -30,13 +31,13 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
## Error
|
||||
|
||||
```
|
||||
10 | 'use memo if(getTrue)';
|
||||
11 | const arr = [];
|
||||
> 12 | useEffectWrapper(() => arr.push(foo));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (12:12)
|
||||
13 | arr.push(2);
|
||||
14 | return arr;
|
||||
15 | }
|
||||
11 | 'use memo if(getTrue)';
|
||||
12 | const arr = [];
|
||||
> 13 | useEffectWrapper(() => arr.push(foo), AUTODEPS);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (13:13)
|
||||
14 | arr.push(2);
|
||||
15 | return arr;
|
||||
16 | }
|
||||
```
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// @dynamicGating:{"source":"shared-runtime"} @inferEffectDependencies @panicThreshold:"none"
|
||||
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
/**
|
||||
* TODO: run the non-forget enabled version through the effect inference
|
||||
@@ -9,7 +10,7 @@ import useEffectWrapper from 'useEffectWrapper';
|
||||
function Component({foo}) {
|
||||
'use memo if(getTrue)';
|
||||
const arr = [];
|
||||
useEffectWrapper(() => arr.push(foo));
|
||||
useEffectWrapper(() => arr.push(foo), AUTODEPS);
|
||||
arr.push(2);
|
||||
return arr;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
```javascript
|
||||
// @gating @inferEffectDependencies @panicThreshold:"none"
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
/**
|
||||
* TODO: run the non-forget enabled version through the effect inference
|
||||
@@ -11,7 +12,7 @@ import useEffectWrapper from 'useEffectWrapper';
|
||||
*/
|
||||
function Component({foo}) {
|
||||
const arr = [];
|
||||
useEffectWrapper(() => arr.push(foo));
|
||||
useEffectWrapper(() => arr.push(foo), AUTODEPS);
|
||||
arr.push(2);
|
||||
return arr;
|
||||
}
|
||||
@@ -28,13 +29,13 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
## Error
|
||||
|
||||
```
|
||||
8 | function Component({foo}) {
|
||||
9 | const arr = [];
|
||||
> 10 | useEffectWrapper(() => arr.push(foo));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (10:10)
|
||||
11 | arr.push(2);
|
||||
12 | return arr;
|
||||
13 | }
|
||||
9 | function Component({foo}) {
|
||||
10 | const arr = [];
|
||||
> 11 | useEffectWrapper(() => arr.push(foo), AUTODEPS);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (11:11)
|
||||
12 | arr.push(2);
|
||||
13 | return arr;
|
||||
14 | }
|
||||
```
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// @gating @inferEffectDependencies @panicThreshold:"none"
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
/**
|
||||
* TODO: run the non-forget enabled version through the effect inference
|
||||
@@ -7,7 +8,7 @@ import useEffectWrapper from 'useEffectWrapper';
|
||||
*/
|
||||
function Component({foo}) {
|
||||
const arr = [];
|
||||
useEffectWrapper(() => arr.push(foo));
|
||||
useEffectWrapper(() => arr.push(foo), AUTODEPS);
|
||||
arr.push(2);
|
||||
return arr;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import React from 'react';
|
||||
|
||||
function NonReactiveDepInEffect() {
|
||||
const obj = makeObject_Primitives();
|
||||
React.useEffect(() => print(obj));
|
||||
React.useEffect(() => print(obj), React.AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -18,8 +18,8 @@ function NonReactiveDepInEffect() {
|
||||
```
|
||||
4 | function NonReactiveDepInEffect() {
|
||||
5 | const obj = makeObject_Primitives();
|
||||
> 6 | React.useEffect(() => print(obj));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (6:6)
|
||||
> 6 | React.useEffect(() => print(obj), React.AUTODEPS);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (6:6)
|
||||
7 | }
|
||||
8 |
|
||||
```
|
||||
|
||||
@@ -3,5 +3,5 @@ import React from 'react';
|
||||
|
||||
function NonReactiveDepInEffect() {
|
||||
const obj = makeObject_Primitives();
|
||||
React.useEffect(() => print(obj));
|
||||
React.useEffect(() => print(obj), React.AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
```javascript
|
||||
// @inferEffectDependencies @panicThreshold:"none"
|
||||
import {useSpecialEffect} from 'shared-runtime';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
/**
|
||||
* Note that a react compiler-based transform still has limitations on JS syntax.
|
||||
@@ -11,13 +12,17 @@ import {useSpecialEffect} from 'shared-runtime';
|
||||
*/
|
||||
function Component({prop1}) {
|
||||
'use memo';
|
||||
useSpecialEffect(() => {
|
||||
try {
|
||||
console.log(prop1);
|
||||
} finally {
|
||||
console.log('exiting');
|
||||
}
|
||||
}, [prop1]);
|
||||
useSpecialEffect(
|
||||
() => {
|
||||
try {
|
||||
console.log(prop1);
|
||||
} finally {
|
||||
console.log('exiting');
|
||||
}
|
||||
},
|
||||
[prop1],
|
||||
AUTODEPS
|
||||
);
|
||||
return <div>{prop1}</div>;
|
||||
}
|
||||
|
||||
@@ -27,25 +32,33 @@ function Component({prop1}) {
|
||||
## Error
|
||||
|
||||
```
|
||||
8 | function Component({prop1}) {
|
||||
9 | 'use memo';
|
||||
> 10 | useSpecialEffect(() => {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 11 | try {
|
||||
| ^^^^^^^^^
|
||||
> 12 | console.log(prop1);
|
||||
| ^^^^^^^^^
|
||||
> 13 | } finally {
|
||||
| ^^^^^^^^^
|
||||
> 14 | console.log('exiting');
|
||||
| ^^^^^^^^^
|
||||
> 15 | }
|
||||
| ^^^^^^^^^
|
||||
> 16 | }, [prop1]);
|
||||
| ^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics.. (Bailout reason: Todo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause (11:15)) (10:16)
|
||||
17 | return <div>{prop1}</div>;
|
||||
18 | }
|
||||
19 |
|
||||
9 | function Component({prop1}) {
|
||||
10 | 'use memo';
|
||||
> 11 | useSpecialEffect(
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
> 12 | () => {
|
||||
| ^^^^^^^^^^^
|
||||
> 13 | try {
|
||||
| ^^^^^^^^^^^
|
||||
> 14 | console.log(prop1);
|
||||
| ^^^^^^^^^^^
|
||||
> 15 | } finally {
|
||||
| ^^^^^^^^^^^
|
||||
> 16 | console.log('exiting');
|
||||
| ^^^^^^^^^^^
|
||||
> 17 | }
|
||||
| ^^^^^^^^^^^
|
||||
> 18 | },
|
||||
| ^^^^^^^^^^^
|
||||
> 19 | [prop1],
|
||||
| ^^^^^^^^^^^
|
||||
> 20 | AUTODEPS
|
||||
| ^^^^^^^^^^^
|
||||
> 21 | );
|
||||
| ^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics.. (Bailout reason: Todo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause (13:17)) (11:21)
|
||||
22 | return <div>{prop1}</div>;
|
||||
23 | }
|
||||
24 |
|
||||
```
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// @inferEffectDependencies @panicThreshold:"none"
|
||||
import {useSpecialEffect} from 'shared-runtime';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
/**
|
||||
* Note that a react compiler-based transform still has limitations on JS syntax.
|
||||
@@ -7,12 +8,16 @@ import {useSpecialEffect} from 'shared-runtime';
|
||||
*/
|
||||
function Component({prop1}) {
|
||||
'use memo';
|
||||
useSpecialEffect(() => {
|
||||
try {
|
||||
console.log(prop1);
|
||||
} finally {
|
||||
console.log('exiting');
|
||||
}
|
||||
}, [prop1]);
|
||||
useSpecialEffect(
|
||||
() => {
|
||||
try {
|
||||
console.log(prop1);
|
||||
} finally {
|
||||
console.log('exiting');
|
||||
}
|
||||
},
|
||||
[prop1],
|
||||
AUTODEPS
|
||||
);
|
||||
return <div>{prop1}</div>;
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @panicThreshold:"none"
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
|
||||
function Component({propVal}) {
|
||||
'use no memo';
|
||||
useEffect(() => [propVal]);
|
||||
useEffect(() => [propVal], AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -18,8 +18,8 @@ function Component({propVal}) {
|
||||
```
|
||||
4 | function Component({propVal}) {
|
||||
5 | 'use no memo';
|
||||
> 6 | useEffect(() => [propVal]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (6:6)
|
||||
> 6 | useEffect(() => [propVal], AUTODEPS);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (6:6)
|
||||
7 | }
|
||||
8 |
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// @inferEffectDependencies @panicThreshold:"none"
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
|
||||
function Component({propVal}) {
|
||||
'use no memo';
|
||||
useEffect(() => [propVal]);
|
||||
useEffect(() => [propVal], AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @panicThreshold:"none"
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function Component({foo}) {
|
||||
const arr = [];
|
||||
// Taking either arr[0].value or arr as a dependency is reasonable
|
||||
// as long as developers know what to expect.
|
||||
useEffect(() => print(arr[0].value));
|
||||
useEffect(() => print(arr[0].value), AUTODEPS);
|
||||
arr.push({value: foo});
|
||||
return arr;
|
||||
}
|
||||
@@ -21,7 +21,7 @@ function Component({foo}) {
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @panicThreshold:"none"
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, AUTODEPS } from "react";
|
||||
import { print } from "shared-runtime";
|
||||
|
||||
function Component(t0) {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// @inferEffectDependencies @panicThreshold:"none"
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function Component({foo}) {
|
||||
const arr = [];
|
||||
// Taking either arr[0].value or arr as a dependency is reasonable
|
||||
// as long as developers know what to expect.
|
||||
useEffect(() => print(arr[0].value));
|
||||
useEffect(() => print(arr[0].value), AUTODEPS);
|
||||
arr.push({value: foo});
|
||||
return arr;
|
||||
}
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function Component({foo}) {
|
||||
const arr = [];
|
||||
// Taking either arr[0].value or arr as a dependency is reasonable
|
||||
// as long as developers know what to expect.
|
||||
useEffect(() => print(arr[0]?.value));
|
||||
useEffect(() => print(arr[0]?.value), AUTODEPS);
|
||||
arr.push({value: foo});
|
||||
return arr;
|
||||
}
|
||||
@@ -26,7 +26,7 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, AUTODEPS } from "react";
|
||||
import { print } from "shared-runtime";
|
||||
|
||||
function Component(t0) {
|
||||
@@ -48,9 +48,9 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
## Logs
|
||||
|
||||
```
|
||||
{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":139},"end":{"line":12,"column":1,"index":384},"filename":"mutate-after-useeffect-optional-chain.ts"},"detail":{"reason":"Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect()","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":10,"column":2,"index":345},"end":{"line":10,"column":5,"index":348},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}}}
|
||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":9,"column":2,"index":304},"end":{"line":9,"column":39,"index":341},"filename":"mutate-after-useeffect-optional-chain.ts"},"decorations":[{"start":{"line":9,"column":24,"index":326},"end":{"line":9,"column":27,"index":329},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}]}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":139},"end":{"line":12,"column":1,"index":384},"filename":"mutate-after-useeffect-optional-chain.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":149},"end":{"line":12,"column":1,"index":404},"filename":"mutate-after-useeffect-optional-chain.ts"},"detail":{"reason":"Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect()","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":10,"column":2,"index":365},"end":{"line":10,"column":5,"index":368},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}}}
|
||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":9,"column":2,"index":314},"end":{"line":9,"column":49,"index":361},"filename":"mutate-after-useeffect-optional-chain.ts"},"decorations":[{"start":{"line":9,"column":24,"index":336},"end":{"line":9,"column":27,"index":339},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}]}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":149},"end":{"line":12,"column":1,"index":404},"filename":"mutate-after-useeffect-optional-chain.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
```
|
||||
|
||||
### Eval output
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function Component({foo}) {
|
||||
const arr = [];
|
||||
// Taking either arr[0].value or arr as a dependency is reasonable
|
||||
// as long as developers know what to expect.
|
||||
useEffect(() => print(arr[0]?.value));
|
||||
useEffect(() => print(arr[0]?.value), AUTODEPS);
|
||||
arr.push({value: foo});
|
||||
return arr;
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
```javascript
|
||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
|
||||
|
||||
import {useEffect, useRef} from 'react';
|
||||
import {useEffect, useRef, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function Component({arrRef}) {
|
||||
// Avoid taking arr.current as a dependency
|
||||
useEffect(() => print(arrRef.current));
|
||||
useEffect(() => print(arrRef.current), AUTODEPS);
|
||||
arrRef.current.val = 2;
|
||||
return arrRef;
|
||||
}
|
||||
@@ -26,7 +26,7 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
```javascript
|
||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
|
||||
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useEffect, useRef, AUTODEPS } from "react";
|
||||
import { print } from "shared-runtime";
|
||||
|
||||
function Component(t0) {
|
||||
@@ -47,9 +47,9 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
## Logs
|
||||
|
||||
```
|
||||
{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":148},"end":{"line":11,"column":1,"index":311},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"reason":"Mutating component props or hook arguments is not allowed. Consider using a local variable instead","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":9,"column":2,"index":269},"end":{"line":9,"column":16,"index":283},"filename":"mutate-after-useeffect-ref-access.ts"}}}
|
||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":227},"end":{"line":8,"column":40,"index":265},"filename":"mutate-after-useeffect-ref-access.ts"},"decorations":[{"start":{"line":8,"column":24,"index":249},"end":{"line":8,"column":30,"index":255},"filename":"mutate-after-useeffect-ref-access.ts","identifierName":"arrRef"}]}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":148},"end":{"line":11,"column":1,"index":311},"filename":"mutate-after-useeffect-ref-access.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":158},"end":{"line":11,"column":1,"index":331},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"reason":"Mutating component props or hook arguments is not allowed. Consider using a local variable instead","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":9,"column":2,"index":289},"end":{"line":9,"column":16,"index":303},"filename":"mutate-after-useeffect-ref-access.ts"}}}
|
||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":237},"end":{"line":8,"column":50,"index":285},"filename":"mutate-after-useeffect-ref-access.ts"},"decorations":[{"start":{"line":8,"column":24,"index":259},"end":{"line":8,"column":30,"index":265},"filename":"mutate-after-useeffect-ref-access.ts","identifierName":"arrRef"}]}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":158},"end":{"line":11,"column":1,"index":331},"filename":"mutate-after-useeffect-ref-access.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
```
|
||||
|
||||
### Eval output
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
|
||||
|
||||
import {useEffect, useRef} from 'react';
|
||||
import {useEffect, useRef, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function Component({arrRef}) {
|
||||
// Avoid taking arr.current as a dependency
|
||||
useEffect(() => print(arrRef.current));
|
||||
useEffect(() => print(arrRef.current), AUTODEPS);
|
||||
arrRef.current.val = 2;
|
||||
return arrRef;
|
||||
}
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
|
||||
function Component({foo}) {
|
||||
const arr = [];
|
||||
useEffect(() => {
|
||||
arr.push(foo);
|
||||
});
|
||||
}, AUTODEPS);
|
||||
arr.push(2);
|
||||
return arr;
|
||||
}
|
||||
@@ -25,7 +25,7 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, AUTODEPS } from "react";
|
||||
|
||||
function Component(t0) {
|
||||
const { foo } = t0;
|
||||
@@ -47,9 +47,9 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
## Logs
|
||||
|
||||
```
|
||||
{"kind":"CompileError","fnLoc":{"start":{"line":4,"column":0,"index":101},"end":{"line":11,"column":1,"index":222},"filename":"mutate-after-useeffect.ts"},"detail":{"reason":"Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect()","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":9,"column":2,"index":194},"end":{"line":9,"column":5,"index":197},"filename":"mutate-after-useeffect.ts","identifierName":"arr"}}}
|
||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":6,"column":2,"index":149},"end":{"line":8,"column":4,"index":190},"filename":"mutate-after-useeffect.ts"},"decorations":[{"start":{"line":7,"column":4,"index":171},"end":{"line":7,"column":7,"index":174},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":4,"index":171},"end":{"line":7,"column":7,"index":174},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":13,"index":180},"end":{"line":7,"column":16,"index":183},"filename":"mutate-after-useeffect.ts","identifierName":"foo"}]}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":4,"column":0,"index":101},"end":{"line":11,"column":1,"index":222},"filename":"mutate-after-useeffect.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
{"kind":"CompileError","fnLoc":{"start":{"line":4,"column":0,"index":111},"end":{"line":11,"column":1,"index":242},"filename":"mutate-after-useeffect.ts"},"detail":{"reason":"Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect()","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":9,"column":2,"index":214},"end":{"line":9,"column":5,"index":217},"filename":"mutate-after-useeffect.ts","identifierName":"arr"}}}
|
||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":6,"column":2,"index":159},"end":{"line":8,"column":14,"index":210},"filename":"mutate-after-useeffect.ts"},"decorations":[{"start":{"line":7,"column":4,"index":181},"end":{"line":7,"column":7,"index":184},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":4,"index":181},"end":{"line":7,"column":7,"index":184},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":13,"index":190},"end":{"line":7,"column":16,"index":193},"filename":"mutate-after-useeffect.ts","identifierName":"foo"}]}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":4,"column":0,"index":111},"end":{"line":11,"column":1,"index":242},"filename":"mutate-after-useeffect.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
```
|
||||
|
||||
### Eval output
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
|
||||
function Component({foo}) {
|
||||
const arr = [];
|
||||
useEffect(() => {
|
||||
arr.push(foo);
|
||||
});
|
||||
}, AUTODEPS);
|
||||
arr.push(2);
|
||||
return arr;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
|
||||
function Component({foo}) {
|
||||
useEffect(AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
3 |
|
||||
4 | function Component({foo}) {
|
||||
> 5 | useEffect(AUTODEPS);
|
||||
| ^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (5:5)
|
||||
6 | }
|
||||
7 |
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// @inferEffectDependencies
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
|
||||
function Component({foo}) {
|
||||
useEffect(AUTODEPS);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {AUTODEPS} from 'react';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
|
||||
function Component({foo}) {
|
||||
useEffectWrapper(
|
||||
() => {
|
||||
console.log(foo);
|
||||
},
|
||||
[foo],
|
||||
AUTODEPS
|
||||
);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
4 |
|
||||
5 | function Component({foo}) {
|
||||
> 6 | useEffectWrapper(
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
> 7 | () => {
|
||||
| ^^^^^^^^^^^
|
||||
> 8 | console.log(foo);
|
||||
| ^^^^^^^^^^^
|
||||
> 9 | },
|
||||
| ^^^^^^^^^^^
|
||||
> 10 | [foo],
|
||||
| ^^^^^^^^^^^
|
||||
> 11 | AUTODEPS
|
||||
| ^^^^^^^^^^^
|
||||
> 12 | );
|
||||
| ^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (6:12)
|
||||
13 | }
|
||||
14 |
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// @inferEffectDependencies
|
||||
import {AUTODEPS} from 'react';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
|
||||
function Component({foo}) {
|
||||
useEffectWrapper(
|
||||
() => {
|
||||
console.log(foo);
|
||||
},
|
||||
[foo],
|
||||
AUTODEPS
|
||||
);
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {useEffect, useRef} from 'react';
|
||||
import {useEffect, useRef, AUTODEPS} from 'react';
|
||||
function useCustomRef() {
|
||||
const ref = useRef();
|
||||
return ref;
|
||||
@@ -12,7 +12,7 @@ function NonReactiveWrapper() {
|
||||
const ref = useCustomRef();
|
||||
useEffect(() => {
|
||||
print(ref);
|
||||
});
|
||||
}, AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -21,7 +21,7 @@ function NonReactiveWrapper() {
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useEffect, useRef, AUTODEPS } from "react";
|
||||
function useCustomRef() {
|
||||
const ref = useRef();
|
||||
return ref;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @inferEffectDependencies
|
||||
import {useEffect, useRef} from 'react';
|
||||
import {useEffect, useRef, AUTODEPS} from 'react';
|
||||
function useCustomRef() {
|
||||
const ref = useRef();
|
||||
return ref;
|
||||
@@ -8,5 +8,5 @@ function NonReactiveWrapper() {
|
||||
const ref = useCustomRef();
|
||||
useEffect(() => {
|
||||
print(ref);
|
||||
});
|
||||
}, AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ import * as SharedRuntime from 'shared-runtime';
|
||||
|
||||
function NonReactiveDepInEffect() {
|
||||
const obj = makeObject_Primitives();
|
||||
React.useEffect(() => print(obj));
|
||||
SharedRuntime.useSpecialEffect(() => print(obj), [obj]);
|
||||
React.useEffect(() => print(obj), React.AUTODEPS);
|
||||
SharedRuntime.useSpecialEffect(() => print(obj), [obj], React.AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -4,6 +4,6 @@ import * as SharedRuntime from 'shared-runtime';
|
||||
|
||||
function NonReactiveDepInEffect() {
|
||||
const obj = makeObject_Primitives();
|
||||
React.useEffect(() => print(obj));
|
||||
SharedRuntime.useSpecialEffect(() => print(obj), [obj]);
|
||||
React.useEffect(() => print(obj), React.AUTODEPS);
|
||||
SharedRuntime.useSpecialEffect(() => print(obj), [obj], React.AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {print, useSpecialEffect} from 'shared-runtime';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
function CustomConfig({propVal}) {
|
||||
// Insertion
|
||||
useSpecialEffect(() => print(propVal), [propVal]);
|
||||
useSpecialEffect(() => print(propVal), [propVal], AUTODEPS);
|
||||
// No insertion
|
||||
useSpecialEffect(() => print(propVal), [propVal], [propVal]);
|
||||
}
|
||||
@@ -19,6 +20,7 @@ function CustomConfig({propVal}) {
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
|
||||
import { print, useSpecialEffect } from "shared-runtime";
|
||||
import { AUTODEPS } from "react";
|
||||
|
||||
function CustomConfig(t0) {
|
||||
const $ = _c(7);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// @inferEffectDependencies
|
||||
import {print, useSpecialEffect} from 'shared-runtime';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
function CustomConfig({propVal}) {
|
||||
// Insertion
|
||||
useSpecialEffect(() => print(propVal), [propVal]);
|
||||
useSpecialEffect(() => print(propVal), [propVal], AUTODEPS);
|
||||
// No insertion
|
||||
useSpecialEffect(() => print(propVal), [propVal], [propVal]);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {useEffect, useRef} from 'react';
|
||||
import {useEffect, useRef, AUTODEPS} from 'react';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
|
||||
const moduleNonReactive = 0;
|
||||
@@ -24,7 +24,7 @@ function Component({foo, bar}) {
|
||||
console.log(ref.current);
|
||||
console.log(localNonPrimitiveReactive);
|
||||
console.log(localNonPrimitiveNonreactive);
|
||||
});
|
||||
}, AUTODEPS);
|
||||
|
||||
// Optional chains and property accesses
|
||||
// TODO: we may be able to save bytes by omitting property accesses if the
|
||||
@@ -32,11 +32,11 @@ function Component({foo, bar}) {
|
||||
useEffect(() => {
|
||||
console.log(bar?.baz);
|
||||
console.log(bar.qux);
|
||||
});
|
||||
}, AUTODEPS);
|
||||
|
||||
useEffectWrapper(() => {
|
||||
console.log(foo);
|
||||
});
|
||||
}, AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -45,7 +45,7 @@ function Component({foo, bar}) {
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useEffect, useRef, AUTODEPS } from "react";
|
||||
import useEffectWrapper from "useEffectWrapper";
|
||||
|
||||
const moduleNonReactive = 0;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @inferEffectDependencies
|
||||
import {useEffect, useRef} from 'react';
|
||||
import {useEffect, useRef, AUTODEPS} from 'react';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
|
||||
const moduleNonReactive = 0;
|
||||
@@ -20,7 +20,7 @@ function Component({foo, bar}) {
|
||||
console.log(ref.current);
|
||||
console.log(localNonPrimitiveReactive);
|
||||
console.log(localNonPrimitiveNonreactive);
|
||||
});
|
||||
}, AUTODEPS);
|
||||
|
||||
// Optional chains and property accesses
|
||||
// TODO: we may be able to save bytes by omitting property accesses if the
|
||||
@@ -28,9 +28,9 @@ function Component({foo, bar}) {
|
||||
useEffect(() => {
|
||||
console.log(bar?.baz);
|
||||
console.log(bar.qux);
|
||||
});
|
||||
}, AUTODEPS);
|
||||
|
||||
useEffectWrapper(() => {
|
||||
console.log(foo);
|
||||
});
|
||||
}, AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
// @inferEffectDependencies @noEmit
|
||||
import {print} from 'shared-runtime';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
function ReactiveVariable({propVal}) {
|
||||
const arr = [propVal];
|
||||
useEffectWrapper(() => print(arr));
|
||||
useEffectWrapper(() => print(arr), AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -19,10 +20,11 @@ function ReactiveVariable({propVal}) {
|
||||
// @inferEffectDependencies @noEmit
|
||||
import { print } from "shared-runtime";
|
||||
import useEffectWrapper from "useEffectWrapper";
|
||||
import { AUTODEPS } from "react";
|
||||
|
||||
function ReactiveVariable({ propVal }) {
|
||||
const arr = [propVal];
|
||||
useEffectWrapper(() => print(arr));
|
||||
useEffectWrapper(() => print(arr), AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// @inferEffectDependencies @noEmit
|
||||
import {print} from 'shared-runtime';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
function ReactiveVariable({propVal}) {
|
||||
const arr = [propVal];
|
||||
useEffectWrapper(() => print(arr));
|
||||
useEffectWrapper(() => print(arr), AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
// @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly
|
||||
import {print} from 'shared-runtime';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
function Foo({propVal}) {
|
||||
const arr = [propVal];
|
||||
useEffectWrapper(() => print(arr));
|
||||
useEffectWrapper(() => print(arr), AUTODEPS);
|
||||
|
||||
const arr2 = [];
|
||||
useEffectWrapper(() => arr2.push(propVal));
|
||||
useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
arr2.push(2);
|
||||
return {arr, arr2};
|
||||
}
|
||||
@@ -30,13 +31,14 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
// @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly
|
||||
import { print } from "shared-runtime";
|
||||
import useEffectWrapper from "useEffectWrapper";
|
||||
import { AUTODEPS } from "react";
|
||||
|
||||
function Foo({ propVal }) {
|
||||
const arr = [propVal];
|
||||
useEffectWrapper(() => print(arr));
|
||||
useEffectWrapper(() => print(arr), AUTODEPS);
|
||||
|
||||
const arr2 = [];
|
||||
useEffectWrapper(() => arr2.push(propVal));
|
||||
useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
arr2.push(2);
|
||||
return { arr, arr2 };
|
||||
}
|
||||
@@ -52,10 +54,10 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
## Logs
|
||||
|
||||
```
|
||||
{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":163},"end":{"line":13,"column":1,"index":357},"filename":"retry-no-emit.ts"},"detail":{"reason":"Updating a value previously passed as an argument to a hook is not allowed. Consider moving the mutation before calling the hook","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":11,"column":2,"index":320},"end":{"line":11,"column":6,"index":324},"filename":"retry-no-emit.ts","identifierName":"arr2"}}}
|
||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":7,"column":2,"index":216},"end":{"line":7,"column":36,"index":250},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":7,"column":31,"index":245},"end":{"line":7,"column":34,"index":248},"filename":"retry-no-emit.ts","identifierName":"arr"}]}
|
||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":10,"column":2,"index":274},"end":{"line":10,"column":44,"index":316},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":10,"column":25,"index":297},"end":{"line":10,"column":29,"index":301},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":10,"column":25,"index":297},"end":{"line":10,"column":29,"index":301},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":10,"column":35,"index":307},"end":{"line":10,"column":42,"index":314},"filename":"retry-no-emit.ts","identifierName":"propVal"}]}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":163},"end":{"line":13,"column":1,"index":357},"filename":"retry-no-emit.ts"},"fnName":"Foo","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":195},"end":{"line":14,"column":1,"index":409},"filename":"retry-no-emit.ts"},"detail":{"reason":"Updating a value previously passed as an argument to a hook is not allowed. Consider moving the mutation before calling the hook","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":12,"column":2,"index":372},"end":{"line":12,"column":6,"index":376},"filename":"retry-no-emit.ts","identifierName":"arr2"}}}
|
||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":248},"end":{"line":8,"column":46,"index":292},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":8,"column":31,"index":277},"end":{"line":8,"column":34,"index":280},"filename":"retry-no-emit.ts","identifierName":"arr"}]}
|
||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":11,"column":2,"index":316},"end":{"line":11,"column":54,"index":368},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":11,"column":25,"index":339},"end":{"line":11,"column":29,"index":343},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":11,"column":25,"index":339},"end":{"line":11,"column":29,"index":343},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":11,"column":35,"index":349},"end":{"line":11,"column":42,"index":356},"filename":"retry-no-emit.ts","identifierName":"propVal"}]}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":195},"end":{"line":14,"column":1,"index":409},"filename":"retry-no-emit.ts"},"fnName":"Foo","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
```
|
||||
|
||||
### Eval output
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
// @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly
|
||||
import {print} from 'shared-runtime';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
function Foo({propVal}) {
|
||||
const arr = [propVal];
|
||||
useEffectWrapper(() => print(arr));
|
||||
useEffectWrapper(() => print(arr), AUTODEPS);
|
||||
|
||||
const arr2 = [];
|
||||
useEffectWrapper(() => arr2.push(propVal));
|
||||
useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
arr2.push(2);
|
||||
return {arr, arr2};
|
||||
}
|
||||
|
||||
@@ -4,15 +4,16 @@
|
||||
```javascript
|
||||
// @compilationMode:"all" @inferEffectDependencies @panicThreshold:"none" @noEmit
|
||||
import {print} from 'shared-runtime';
|
||||
import {AUTODEPS} from 'react';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
|
||||
function Foo({propVal}) {
|
||||
'use memo';
|
||||
const arr = [propVal];
|
||||
useEffectWrapper(() => print(arr));
|
||||
useEffectWrapper(() => print(arr), AUTODEPS);
|
||||
|
||||
const arr2 = [];
|
||||
useEffectWrapper(() => arr2.push(propVal));
|
||||
useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
arr2.push(2);
|
||||
|
||||
return {arr, arr2};
|
||||
@@ -31,15 +32,16 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
```javascript
|
||||
// @compilationMode:"all" @inferEffectDependencies @panicThreshold:"none" @noEmit
|
||||
import { print } from "shared-runtime";
|
||||
import { AUTODEPS } from "react";
|
||||
import useEffectWrapper from "useEffectWrapper";
|
||||
|
||||
function Foo({ propVal }) {
|
||||
"use memo";
|
||||
const arr = [propVal];
|
||||
useEffectWrapper(() => print(arr));
|
||||
useEffectWrapper(() => print(arr), AUTODEPS);
|
||||
|
||||
const arr2 = [];
|
||||
useEffectWrapper(() => arr2.push(propVal));
|
||||
useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
arr2.push(2);
|
||||
|
||||
return { arr, arr2 };
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
// @compilationMode:"all" @inferEffectDependencies @panicThreshold:"none" @noEmit
|
||||
import {print} from 'shared-runtime';
|
||||
import {AUTODEPS} from 'react';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
|
||||
function Foo({propVal}) {
|
||||
'use memo';
|
||||
const arr = [propVal];
|
||||
useEffectWrapper(() => print(arr));
|
||||
useEffectWrapper(() => print(arr), AUTODEPS);
|
||||
|
||||
const arr2 = [];
|
||||
useEffectWrapper(() => arr2.push(propVal));
|
||||
useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
arr2.push(2);
|
||||
|
||||
return {arr, arr2};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {makeObject_Primitives, print} from 'shared-runtime';
|
||||
|
||||
/**
|
||||
@@ -25,7 +25,7 @@ import {makeObject_Primitives, print} from 'shared-runtime';
|
||||
*/
|
||||
function NonReactiveDepInEffect() {
|
||||
const obj = makeObject_Primitives();
|
||||
useEffect(() => print(obj));
|
||||
useEffect(() => print(obj), AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -34,7 +34,7 @@ function NonReactiveDepInEffect() {
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, AUTODEPS } from "react";
|
||||
import { makeObject_Primitives, print } from "shared-runtime";
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @inferEffectDependencies
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {makeObject_Primitives, print} from 'shared-runtime';
|
||||
|
||||
/**
|
||||
@@ -21,5 +21,5 @@ import {makeObject_Primitives, print} from 'shared-runtime';
|
||||
*/
|
||||
function NonReactiveDepInEffect() {
|
||||
const obj = makeObject_Primitives();
|
||||
useEffect(() => print(obj));
|
||||
useEffect(() => print(obj), AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {useEffect, useEffectEvent} from 'react';
|
||||
import {useEffect, useEffectEvent, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
/**
|
||||
@@ -11,7 +11,7 @@ import {print} from 'shared-runtime';
|
||||
*/
|
||||
function NonReactiveEffectEvent() {
|
||||
const fn = useEffectEvent(() => print('hello world'));
|
||||
useEffect(() => fn());
|
||||
useEffect(() => fn(), AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -20,7 +20,7 @@ function NonReactiveEffectEvent() {
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
|
||||
import { useEffect, useEffectEvent } from "react";
|
||||
import { useEffect, useEffectEvent, AUTODEPS } from "react";
|
||||
import { print } from "shared-runtime";
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @inferEffectDependencies
|
||||
import {useEffect, useEffectEvent} from 'react';
|
||||
import {useEffect, useEffectEvent, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
/**
|
||||
@@ -7,5 +7,5 @@ import {print} from 'shared-runtime';
|
||||
*/
|
||||
function NonReactiveEffectEvent() {
|
||||
const fn = useEffectEvent(() => print('hello world'));
|
||||
useEffect(() => fn());
|
||||
useEffect(() => fn(), AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
/**
|
||||
@@ -19,7 +19,7 @@ function RefsInEffects() {
|
||||
useEffect(() => {
|
||||
print(ref.current);
|
||||
print(wrapped.foo.current);
|
||||
});
|
||||
}, AUTODEPS);
|
||||
}
|
||||
|
||||
function useRefHelper() {
|
||||
@@ -36,7 +36,7 @@ function useDeeperRefHelper() {
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, AUTODEPS } from "react";
|
||||
import { print } from "shared-runtime";
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @inferEffectDependencies
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
/**
|
||||
@@ -15,7 +15,7 @@ function RefsInEffects() {
|
||||
useEffect(() => {
|
||||
print(ref.current);
|
||||
print(wrapped.foo.current);
|
||||
});
|
||||
}, AUTODEPS);
|
||||
}
|
||||
|
||||
function useRefHelper() {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {useEffect, useRef} from 'react';
|
||||
import {useEffect, useRef, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
/**
|
||||
@@ -14,7 +14,7 @@ import {print} from 'shared-runtime';
|
||||
*/
|
||||
function NonReactiveRefInEffect() {
|
||||
const ref = useRef('initial value');
|
||||
useEffect(() => print(ref.current));
|
||||
useEffect(() => print(ref.current), AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -23,7 +23,7 @@ function NonReactiveRefInEffect() {
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useEffect, useRef, AUTODEPS } from "react";
|
||||
import { print } from "shared-runtime";
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @inferEffectDependencies
|
||||
import {useEffect, useRef} from 'react';
|
||||
import {useEffect, useRef, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
/**
|
||||
@@ -10,5 +10,5 @@ import {print} from 'shared-runtime';
|
||||
*/
|
||||
function NonReactiveRefInEffect() {
|
||||
const ref = useRef('initial value');
|
||||
useEffect(() => print(ref.current));
|
||||
useEffect(() => print(ref.current), AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {useEffect, useState} from 'react';
|
||||
import {useEffect, useState, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
/**
|
||||
@@ -14,7 +14,7 @@ import {print} from 'shared-runtime';
|
||||
*/
|
||||
function NonReactiveSetStateInEffect() {
|
||||
const [_, setState] = useState('initial value');
|
||||
useEffect(() => print(setState));
|
||||
useEffect(() => print(setState), AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -23,7 +23,7 @@ function NonReactiveSetStateInEffect() {
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useState, AUTODEPS } from "react";
|
||||
import { print } from "shared-runtime";
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @inferEffectDependencies
|
||||
import {useEffect, useState} from 'react';
|
||||
import {useEffect, useState, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
/**
|
||||
@@ -10,5 +10,5 @@ import {print} from 'shared-runtime';
|
||||
*/
|
||||
function NonReactiveSetStateInEffect() {
|
||||
const [_, setState] = useState('initial value');
|
||||
useEffect(() => print(setState));
|
||||
useEffect(() => print(setState), AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
/**
|
||||
* This compiled output is technically incorrect but this is currently the same
|
||||
@@ -14,7 +14,7 @@ import {print} from 'shared-runtime';
|
||||
* before OutlineFunctions
|
||||
*/
|
||||
function OutlinedFunctionInEffect() {
|
||||
useEffect(() => print('hello world!'));
|
||||
useEffect(() => print('hello world!'), AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -23,7 +23,7 @@ function OutlinedFunctionInEffect() {
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, AUTODEPS } from "react";
|
||||
import { print } from "shared-runtime";
|
||||
/**
|
||||
* This compiled output is technically incorrect but this is currently the same
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @inferEffectDependencies
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
/**
|
||||
* This compiled output is technically incorrect but this is currently the same
|
||||
@@ -10,5 +10,5 @@ import {print} from 'shared-runtime';
|
||||
* before OutlineFunctions
|
||||
*/
|
||||
function OutlinedFunctionInEffect() {
|
||||
useEffect(() => print('hello world!'));
|
||||
useEffect(() => print('hello world!'), AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {useIdentity, mutate, makeObject} from 'shared-runtime';
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
|
||||
/**
|
||||
* When a semantically non-reactive value has a pruned scope (i.e. the object
|
||||
@@ -48,7 +48,7 @@ function PrunedNonReactive() {
|
||||
useIdentity(null);
|
||||
mutate(obj);
|
||||
|
||||
useEffect(() => print(obj.value));
|
||||
useEffect(() => print(obj.value), AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -58,7 +58,7 @@ function PrunedNonReactive() {
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
|
||||
import { useIdentity, mutate, makeObject } from "shared-runtime";
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, AUTODEPS } from "react";
|
||||
|
||||
/**
|
||||
* When a semantically non-reactive value has a pruned scope (i.e. the object
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @inferEffectDependencies
|
||||
import {useIdentity, mutate, makeObject} from 'shared-runtime';
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
|
||||
/**
|
||||
* When a semantically non-reactive value has a pruned scope (i.e. the object
|
||||
@@ -44,5 +44,5 @@ function PrunedNonReactive() {
|
||||
useIdentity(null);
|
||||
mutate(obj);
|
||||
|
||||
useEffect(() => print(obj.value));
|
||||
useEffect(() => print(obj.value), AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function ReactiveMemberExprMerge({propVal}) {
|
||||
const obj = {a: {b: propVal}};
|
||||
useEffect(() => print(obj.a, obj.a.b));
|
||||
useEffect(() => print(obj.a, obj.a.b), AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -17,7 +17,7 @@ function ReactiveMemberExprMerge({propVal}) {
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, AUTODEPS } from "react";
|
||||
import { print } from "shared-runtime";
|
||||
|
||||
function ReactiveMemberExprMerge(t0) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// @inferEffectDependencies
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function ReactiveMemberExprMerge({propVal}) {
|
||||
const obj = {a: {b: propVal}};
|
||||
useEffect(() => print(obj.a, obj.a.b));
|
||||
useEffect(() => print(obj.a, obj.a.b), AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function ReactiveMemberExpr({propVal}) {
|
||||
const obj = {a: {b: propVal}};
|
||||
useEffect(() => print(obj.a.b));
|
||||
useEffect(() => print(obj.a.b), AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -17,7 +17,7 @@ function ReactiveMemberExpr({propVal}) {
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, AUTODEPS } from "react";
|
||||
import { print } from "shared-runtime";
|
||||
|
||||
function ReactiveMemberExpr(t0) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// @inferEffectDependencies
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function ReactiveMemberExpr({propVal}) {
|
||||
const obj = {a: {b: propVal}};
|
||||
useEffect(() => print(obj.a.b));
|
||||
useEffect(() => print(obj.a.b), AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -3,15 +3,16 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print, shallowCopy} from 'shared-runtime';
|
||||
|
||||
function ReactiveMemberExpr({cond, propVal}) {
|
||||
const obj = {a: cond ? {b: propVal} : null, c: null};
|
||||
const other = shallowCopy({a: {b: {c: {d: {e: {f: propVal + 1}}}}}});
|
||||
const primitive = shallowCopy(propVal);
|
||||
useEffect(() =>
|
||||
print(obj.a?.b, other?.a?.b?.c?.d?.e.f, primitive.a?.b.c?.d?.e.f)
|
||||
useEffect(
|
||||
() => print(obj.a?.b, other?.a?.b?.c?.d?.e.f, primitive.a?.b.c?.d?.e.f),
|
||||
AUTODEPS
|
||||
);
|
||||
}
|
||||
|
||||
@@ -26,7 +27,7 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, AUTODEPS } from "react";
|
||||
import { print, shallowCopy } from "shared-runtime";
|
||||
|
||||
function ReactiveMemberExpr(t0) {
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
// @inferEffectDependencies
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print, shallowCopy} from 'shared-runtime';
|
||||
|
||||
function ReactiveMemberExpr({cond, propVal}) {
|
||||
const obj = {a: cond ? {b: propVal} : null, c: null};
|
||||
const other = shallowCopy({a: {b: {c: {d: {e: {f: propVal + 1}}}}}});
|
||||
const primitive = shallowCopy(propVal);
|
||||
useEffect(() =>
|
||||
print(obj.a?.b, other?.a?.b?.c?.d?.e.f, primitive.a?.b.c?.d?.e.f)
|
||||
useEffect(
|
||||
() => print(obj.a?.b, other?.a?.b?.c?.d?.e.f, primitive.a?.b.c?.d?.e.f),
|
||||
AUTODEPS
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function ReactiveMemberExpr({cond, propVal}) {
|
||||
const obj = {a: cond ? {b: propVal} : null, c: null};
|
||||
useEffect(() => print(obj.a?.b));
|
||||
useEffect(() => print(obj.c?.d));
|
||||
useEffect(() => print(obj.a?.b), AUTODEPS);
|
||||
useEffect(() => print(obj.c?.d), AUTODEPS);
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
@@ -23,7 +23,7 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, AUTODEPS } from "react";
|
||||
import { print } from "shared-runtime";
|
||||
|
||||
function ReactiveMemberExpr(t0) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// @inferEffectDependencies
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function ReactiveMemberExpr({cond, propVal}) {
|
||||
const obj = {a: cond ? {b: propVal} : null, c: null};
|
||||
useEffect(() => print(obj.a?.b));
|
||||
useEffect(() => print(obj.c?.d));
|
||||
useEffect(() => print(obj.a?.b), AUTODEPS);
|
||||
useEffect(() => print(obj.c?.d), AUTODEPS);
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {useRef, useEffect} from 'react';
|
||||
import {useRef, useEffect, AUTODEPS} from 'react';
|
||||
import {print, mutate} from 'shared-runtime';
|
||||
|
||||
function Component({cond}) {
|
||||
@@ -14,7 +14,7 @@ function Component({cond}) {
|
||||
useEffect(() => {
|
||||
mutate(derived.current);
|
||||
print(derived.current);
|
||||
});
|
||||
}, AUTODEPS);
|
||||
return arr;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ function Component({cond}) {
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
|
||||
import { useRef, useEffect } from "react";
|
||||
import { useRef, useEffect, AUTODEPS } from "react";
|
||||
import { print, mutate } from "shared-runtime";
|
||||
|
||||
function Component(t0) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @inferEffectDependencies
|
||||
import {useRef, useEffect} from 'react';
|
||||
import {useRef, useEffect, AUTODEPS} from 'react';
|
||||
import {print, mutate} from 'shared-runtime';
|
||||
|
||||
function Component({cond}) {
|
||||
@@ -10,6 +10,6 @@ function Component({cond}) {
|
||||
useEffect(() => {
|
||||
mutate(derived.current);
|
||||
print(derived.current);
|
||||
});
|
||||
}, AUTODEPS);
|
||||
return arr;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {useEffect, useRef} from 'react';
|
||||
import {useEffect, useRef, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
/*
|
||||
@@ -18,7 +18,7 @@ function ReactiveRefInEffect(props) {
|
||||
} else {
|
||||
ref = ref2;
|
||||
}
|
||||
useEffect(() => print(ref));
|
||||
useEffect(() => print(ref), AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -27,7 +27,7 @@ function ReactiveRefInEffect(props) {
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useEffect, useRef, AUTODEPS } from "react";
|
||||
import { print } from "shared-runtime";
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @inferEffectDependencies
|
||||
import {useEffect, useRef} from 'react';
|
||||
import {useEffect, useRef, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
/*
|
||||
@@ -14,5 +14,5 @@ function ReactiveRefInEffect(props) {
|
||||
} else {
|
||||
ref = ref2;
|
||||
}
|
||||
useEffect(() => print(ref));
|
||||
useEffect(() => print(ref), AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {useEffect, useState} from 'react';
|
||||
import {useEffect, useState, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
/*
|
||||
@@ -18,7 +18,7 @@ function ReactiveRefInEffect(props) {
|
||||
} else {
|
||||
setState = setState2;
|
||||
}
|
||||
useEffect(() => print(setState));
|
||||
useEffect(() => print(setState), AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -27,7 +27,7 @@ function ReactiveRefInEffect(props) {
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useState, AUTODEPS } from "react";
|
||||
import { print } from "shared-runtime";
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @inferEffectDependencies
|
||||
import {useEffect, useState} from 'react';
|
||||
import {useEffect, useState, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
/*
|
||||
@@ -14,5 +14,5 @@ function ReactiveRefInEffect(props) {
|
||||
} else {
|
||||
setState = setState2;
|
||||
}
|
||||
useEffect(() => print(setState));
|
||||
useEffect(() => print(setState), AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function ReactiveVariable({propVal}) {
|
||||
const arr = [propVal];
|
||||
useEffect(() => print(arr));
|
||||
useEffect(() => print(arr), AUTODEPS);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -17,7 +17,7 @@ function ReactiveVariable({propVal}) {
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, AUTODEPS } from "react";
|
||||
import { print } from "shared-runtime";
|
||||
|
||||
function ReactiveVariable(t0) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// @inferEffectDependencies
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function ReactiveVariable({propVal}) {
|
||||
const arr = [propVal];
|
||||
useEffect(() => print(arr));
|
||||
useEffect(() => print(arr), AUTODEPS);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @loggerTestOnly @validateNoSetStateInPassiveEffects
|
||||
// @loggerTestOnly @validateNoSetStateInEffects
|
||||
import {useEffect, useState} from 'react';
|
||||
|
||||
function Component() {
|
||||
@@ -24,7 +24,7 @@ function Component() {
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @loggerTestOnly @validateNoSetStateInPassiveEffects
|
||||
import { c as _c } from "react/compiler-runtime"; // @loggerTestOnly @validateNoSetStateInEffects
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
function Component() {
|
||||
@@ -65,8 +65,8 @@ function _temp(s) {
|
||||
## Logs
|
||||
|
||||
```
|
||||
{"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":272},"end":{"line":13,"column":5,"index":273},"filename":"invalid-setState-in-useEffect-transitive.ts","identifierName":"g"}}},"fnLoc":null}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":4,"column":0,"index":99},"end":{"line":16,"column":1,"index":300},"filename":"invalid-setState-in-useEffect-transitive.ts"},"fnName":"Component","memoSlots":2,"memoBlocks":2,"memoValues":2,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
{"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}
|
||||
```
|
||||
|
||||
### Eval output
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// @loggerTestOnly @validateNoSetStateInPassiveEffects
|
||||
// @loggerTestOnly @validateNoSetStateInEffects
|
||||
import {useEffect, useState} from 'react';
|
||||
|
||||
function Component() {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @loggerTestOnly @validateNoSetStateInPassiveEffects
|
||||
// @loggerTestOnly @validateNoSetStateInEffects
|
||||
import {useEffect, useState} from 'react';
|
||||
|
||||
function Component() {
|
||||
@@ -18,7 +18,7 @@ function Component() {
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @loggerTestOnly @validateNoSetStateInPassiveEffects
|
||||
import { c as _c } from "react/compiler-runtime"; // @loggerTestOnly @validateNoSetStateInEffects
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
function Component() {
|
||||
@@ -45,8 +45,8 @@ function _temp(s) {
|
||||
## Logs
|
||||
|
||||
```
|
||||
{"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":187},"end":{"line":7,"column":12,"index":195},"filename":"invalid-setState-in-useEffect.ts","identifierName":"setState"}}},"fnLoc":null}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":4,"column":0,"index":99},"end":{"line":10,"column":1,"index":232},"filename":"invalid-setState-in-useEffect.ts"},"fnName":"Component","memoSlots":1,"memoBlocks":1,"memoValues":1,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
{"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}
|
||||
```
|
||||
|
||||
### Eval output
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// @loggerTestOnly @validateNoSetStateInPassiveEffects
|
||||
// @loggerTestOnly @validateNoSetStateInEffects
|
||||
import {useEffect, useState} from 'react';
|
||||
|
||||
function Component() {
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function Component({foo}) {
|
||||
const arr = [];
|
||||
// Taking either arr[0].value or arr as a dependency is reasonable
|
||||
// as long as developers know what to expect.
|
||||
useEffect(() => print(arr[0]?.value));
|
||||
useEffect(() => print(arr[0]?.value), AUTODEPS);
|
||||
arr.push({value: foo});
|
||||
return arr;
|
||||
}
|
||||
@@ -26,7 +26,7 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, AUTODEPS } from "react";
|
||||
import { print } from "shared-runtime";
|
||||
|
||||
function Component(t0) {
|
||||
@@ -48,9 +48,9 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
## Logs
|
||||
|
||||
```
|
||||
{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":171},"end":{"line":12,"column":1,"index":416},"filename":"mutate-after-useeffect-optional-chain.ts"},"detail":{"reason":"Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect()","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":10,"column":2,"index":377},"end":{"line":10,"column":5,"index":380},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}}}
|
||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":9,"column":2,"index":336},"end":{"line":9,"column":39,"index":373},"filename":"mutate-after-useeffect-optional-chain.ts"},"decorations":[{"start":{"line":9,"column":24,"index":358},"end":{"line":9,"column":27,"index":361},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}]}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":171},"end":{"line":12,"column":1,"index":416},"filename":"mutate-after-useeffect-optional-chain.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":181},"end":{"line":12,"column":1,"index":436},"filename":"mutate-after-useeffect-optional-chain.ts"},"detail":{"reason":"Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect()","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":10,"column":2,"index":397},"end":{"line":10,"column":5,"index":400},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}}}
|
||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":9,"column":2,"index":346},"end":{"line":9,"column":49,"index":393},"filename":"mutate-after-useeffect-optional-chain.ts"},"decorations":[{"start":{"line":9,"column":24,"index":368},"end":{"line":9,"column":27,"index":371},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}]}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":181},"end":{"line":12,"column":1,"index":436},"filename":"mutate-after-useeffect-optional-chain.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
```
|
||||
|
||||
### Eval output
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||
import {useEffect} from 'react';
|
||||
import {useEffect, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function Component({foo}) {
|
||||
const arr = [];
|
||||
// Taking either arr[0].value or arr as a dependency is reasonable
|
||||
// as long as developers know what to expect.
|
||||
useEffect(() => print(arr[0]?.value));
|
||||
useEffect(() => print(arr[0]?.value), AUTODEPS);
|
||||
arr.push({value: foo});
|
||||
return arr;
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
```javascript
|
||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||
|
||||
import {useEffect, useRef} from 'react';
|
||||
import {useEffect, useRef, AUTODEPS} from 'react';
|
||||
import {print} from 'shared-runtime';
|
||||
|
||||
function Component({arrRef}) {
|
||||
// Avoid taking arr.current as a dependency
|
||||
useEffect(() => print(arrRef.current));
|
||||
useEffect(() => print(arrRef.current), AUTODEPS);
|
||||
arrRef.current.val = 2;
|
||||
return arrRef;
|
||||
}
|
||||
@@ -26,7 +26,7 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
```javascript
|
||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useEffect, useRef, AUTODEPS } from "react";
|
||||
import { print } from "shared-runtime";
|
||||
|
||||
function Component(t0) {
|
||||
@@ -47,9 +47,9 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
## Logs
|
||||
|
||||
```
|
||||
{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":180},"end":{"line":11,"column":1,"index":343},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"reason":"Mutating component props or hook arguments is not allowed. Consider using a local variable instead","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":9,"column":2,"index":301},"end":{"line":9,"column":16,"index":315},"filename":"mutate-after-useeffect-ref-access.ts"}}}
|
||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":259},"end":{"line":8,"column":40,"index":297},"filename":"mutate-after-useeffect-ref-access.ts"},"decorations":[{"start":{"line":8,"column":24,"index":281},"end":{"line":8,"column":30,"index":287},"filename":"mutate-after-useeffect-ref-access.ts","identifierName":"arrRef"}]}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":180},"end":{"line":11,"column":1,"index":343},"filename":"mutate-after-useeffect-ref-access.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":190},"end":{"line":11,"column":1,"index":363},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"reason":"Mutating component props or hook arguments is not allowed. Consider using a local variable instead","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":9,"column":2,"index":321},"end":{"line":9,"column":16,"index":335},"filename":"mutate-after-useeffect-ref-access.ts"}}}
|
||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":269},"end":{"line":8,"column":50,"index":317},"filename":"mutate-after-useeffect-ref-access.ts"},"decorations":[{"start":{"line":8,"column":24,"index":291},"end":{"line":8,"column":30,"index":297},"filename":"mutate-after-useeffect-ref-access.ts","identifierName":"arrRef"}]}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":190},"end":{"line":11,"column":1,"index":363},"filename":"mutate-after-useeffect-ref-access.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
```
|
||||
|
||||
### Eval output
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user