mirror of
https://github.com/facebook/react.git
synced 2026-02-21 19:31:52 +00:00
[compiler] Deprecate noEmit, add outputMode (#35112)
This deprecates the `noEmit: boolean` flag and adds `outputMode: 'client' | 'client-no-memo' | 'ssr' | 'lint'` as the replacement. OutputMode defaults to null and takes precedence if specified, otherwise we use 'client' mode for noEmit=false and 'lint' mode for noEmit=true. Key points: * Retrying failed compilation switches from 'client' mode to 'client-no-memo' * Validations are enabled behind Environment.proto.shouldEnableValidations, enabled for all modes except 'client-no-memo'. Similar for dropping manual memoization. * OptimizeSSR is now gated by the outputMode==='ssr', not a feature flag * Creation of reactive scopes, and related codegen logic, is now gated by outputMode==='client'
This commit is contained in:
@@ -102,14 +102,25 @@ export type PluginOptions = Partial<{
|
||||
|
||||
panicThreshold: PanicThresholdOptions;
|
||||
|
||||
/*
|
||||
/**
|
||||
* @deprecated
|
||||
*
|
||||
* When enabled, Forget will continue statically analyzing and linting code, but skip over codegen
|
||||
* passes.
|
||||
*
|
||||
* NOTE: ignored if `outputMode` is specified
|
||||
*
|
||||
* Defaults to false
|
||||
*/
|
||||
noEmit: boolean;
|
||||
|
||||
/**
|
||||
* If specified, overrides `noEmit` and controls the output mode of the compiler.
|
||||
*
|
||||
* Defaults to null
|
||||
*/
|
||||
outputMode: CompilerOutputMode | null;
|
||||
|
||||
/*
|
||||
* Determines the strategy for determining which functions to compile. Note that regardless of
|
||||
* which mode is enabled, a component can be opted out by adding the string literal
|
||||
@@ -212,6 +223,19 @@ const CompilationModeSchema = z.enum([
|
||||
|
||||
export type CompilationMode = z.infer<typeof CompilationModeSchema>;
|
||||
|
||||
const CompilerOutputModeSchema = z.enum([
|
||||
// Build optimized for SSR, with client features removed
|
||||
'ssr',
|
||||
// Build optimized for the client, with auto memoization
|
||||
'client',
|
||||
// Build optimized for the client without auto memo
|
||||
'client-no-memo',
|
||||
// Lint mode, the output is unused but validations should run
|
||||
'lint',
|
||||
]);
|
||||
|
||||
export type CompilerOutputMode = z.infer<typeof CompilerOutputModeSchema>;
|
||||
|
||||
/**
|
||||
* Represents 'events' that may occur during compilation. Events are only
|
||||
* recorded when a logger is set (through the config).
|
||||
@@ -293,6 +317,7 @@ export const defaultOptions: ParsedPluginOptions = {
|
||||
logger: null,
|
||||
gating: null,
|
||||
noEmit: false,
|
||||
outputMode: null,
|
||||
dynamicGating: null,
|
||||
eslintSuppressionRules: null,
|
||||
flowSuppressions: true,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import {NodePath} from '@babel/traverse';
|
||||
import * as t from '@babel/types';
|
||||
import prettyFormat from 'pretty-format';
|
||||
import {Logger, ProgramContext} from '.';
|
||||
import {CompilerOutputMode, Logger, ProgramContext} from '.';
|
||||
import {
|
||||
HIRFunction,
|
||||
ReactiveFunction,
|
||||
@@ -24,7 +24,6 @@ import {
|
||||
pruneUnusedLabelsHIR,
|
||||
} from '../HIR';
|
||||
import {
|
||||
CompilerMode,
|
||||
Environment,
|
||||
EnvironmentConfig,
|
||||
ReactFunctionType,
|
||||
@@ -120,7 +119,7 @@ function run(
|
||||
>,
|
||||
config: EnvironmentConfig,
|
||||
fnType: ReactFunctionType,
|
||||
mode: CompilerMode,
|
||||
mode: CompilerOutputMode,
|
||||
programContext: ProgramContext,
|
||||
logger: Logger | null,
|
||||
filename: string | null,
|
||||
@@ -170,7 +169,7 @@ function runWithEnvironment(
|
||||
validateUseMemo(hir).unwrap();
|
||||
|
||||
if (
|
||||
env.isInferredMemoEnabled &&
|
||||
env.enableDropManualMemoization &&
|
||||
!env.config.enablePreserveExistingManualUseMemo &&
|
||||
!env.config.disableMemoizationForDebugging &&
|
||||
!env.config.enableChangeDetectionForDebugging
|
||||
@@ -206,7 +205,7 @@ function runWithEnvironment(
|
||||
inferTypes(hir);
|
||||
log({kind: 'hir', name: 'InferTypes', value: hir});
|
||||
|
||||
if (env.isInferredMemoEnabled) {
|
||||
if (env.enableValidations) {
|
||||
if (env.config.validateHooksUsage) {
|
||||
validateHooksUsage(hir).unwrap();
|
||||
}
|
||||
@@ -232,13 +231,13 @@ function runWithEnvironment(
|
||||
|
||||
const mutabilityAliasingErrors = inferMutationAliasingEffects(hir);
|
||||
log({kind: 'hir', name: 'InferMutationAliasingEffects', value: hir});
|
||||
if (env.isInferredMemoEnabled) {
|
||||
if (env.enableValidations) {
|
||||
if (mutabilityAliasingErrors.isErr()) {
|
||||
throw mutabilityAliasingErrors.unwrapErr();
|
||||
}
|
||||
}
|
||||
|
||||
if (env.config.enableOptimizeForSSR) {
|
||||
if (env.outputMode === 'ssr') {
|
||||
optimizeForSSR(hir);
|
||||
log({kind: 'hir', name: 'OptimizeForSSR', value: hir});
|
||||
}
|
||||
@@ -259,14 +258,14 @@ function runWithEnvironment(
|
||||
isFunctionExpression: false,
|
||||
});
|
||||
log({kind: 'hir', name: 'InferMutationAliasingRanges', value: hir});
|
||||
if (env.isInferredMemoEnabled) {
|
||||
if (env.enableValidations) {
|
||||
if (mutabilityAliasingRangeErrors.isErr()) {
|
||||
throw mutabilityAliasingRangeErrors.unwrapErr();
|
||||
}
|
||||
validateLocalsNotReassignedAfterRender(hir);
|
||||
}
|
||||
|
||||
if (env.isInferredMemoEnabled) {
|
||||
if (env.enableValidations) {
|
||||
if (env.config.assertValidMutableRanges) {
|
||||
assertValidMutableRanges(hir);
|
||||
}
|
||||
@@ -310,20 +309,18 @@ function runWithEnvironment(
|
||||
value: hir,
|
||||
});
|
||||
|
||||
if (env.isInferredMemoEnabled) {
|
||||
if (env.config.validateStaticComponents) {
|
||||
env.logErrors(validateStaticComponents(hir));
|
||||
}
|
||||
if (env.enableValidations && env.config.validateStaticComponents) {
|
||||
env.logErrors(validateStaticComponents(hir));
|
||||
}
|
||||
|
||||
if (env.enableMemoization) {
|
||||
/**
|
||||
* Only create reactive scopes (which directly map to generated memo blocks)
|
||||
* if inferred memoization is enabled. This makes all later passes which
|
||||
* transform reactive-scope labeled instructions no-ops.
|
||||
*/
|
||||
if (!env.config.enableOptimizeForSSR) {
|
||||
inferReactiveScopeVariables(hir);
|
||||
log({kind: 'hir', name: 'InferReactiveScopeVariables', value: hir});
|
||||
}
|
||||
inferReactiveScopeVariables(hir);
|
||||
log({kind: 'hir', name: 'InferReactiveScopeVariables', value: hir});
|
||||
}
|
||||
|
||||
const fbtOperands = memoizeFbtAndMacroOperandsInSameScope(hir);
|
||||
@@ -588,7 +585,7 @@ export function compileFn(
|
||||
>,
|
||||
config: EnvironmentConfig,
|
||||
fnType: ReactFunctionType,
|
||||
mode: CompilerMode,
|
||||
mode: CompilerOutputMode,
|
||||
programContext: ProgramContext,
|
||||
logger: Logger | null,
|
||||
filename: string | null,
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
validateRestrictedImports,
|
||||
} from './Imports';
|
||||
import {
|
||||
CompilerOutputMode,
|
||||
CompilerReactTarget,
|
||||
ParsedPluginOptions,
|
||||
PluginOptions,
|
||||
@@ -421,9 +422,17 @@ export function compileProgram(
|
||||
);
|
||||
const compiledFns: Array<CompileResult> = [];
|
||||
|
||||
// outputMode takes precedence if specified
|
||||
const outputMode: CompilerOutputMode =
|
||||
pass.opts.outputMode ?? (pass.opts.noEmit ? 'lint' : 'client');
|
||||
while (queue.length !== 0) {
|
||||
const current = queue.shift()!;
|
||||
const compiled = processFn(current.fn, current.fnType, programContext);
|
||||
const compiled = processFn(
|
||||
current.fn,
|
||||
current.fnType,
|
||||
programContext,
|
||||
outputMode,
|
||||
);
|
||||
|
||||
if (compiled != null) {
|
||||
for (const outlined of compiled.outlined) {
|
||||
@@ -581,6 +590,7 @@ function processFn(
|
||||
fn: BabelFn,
|
||||
fnType: ReactFunctionType,
|
||||
programContext: ProgramContext,
|
||||
outputMode: CompilerOutputMode,
|
||||
): null | CodegenFunction {
|
||||
let directives: {
|
||||
optIn: t.Directive | null;
|
||||
@@ -616,18 +626,27 @@ function processFn(
|
||||
}
|
||||
|
||||
let compiledFn: CodegenFunction;
|
||||
const compileResult = tryCompileFunction(fn, fnType, programContext);
|
||||
const compileResult = tryCompileFunction(
|
||||
fn,
|
||||
fnType,
|
||||
programContext,
|
||||
outputMode,
|
||||
);
|
||||
if (compileResult.kind === 'error') {
|
||||
if (directives.optOut != null) {
|
||||
logError(compileResult.error, programContext, fn.node.loc ?? null);
|
||||
} else {
|
||||
handleError(compileResult.error, programContext, fn.node.loc ?? null);
|
||||
}
|
||||
const retryResult = retryCompileFunction(fn, fnType, programContext);
|
||||
if (retryResult == null) {
|
||||
if (outputMode === 'client') {
|
||||
const retryResult = retryCompileFunction(fn, fnType, programContext);
|
||||
if (retryResult == null) {
|
||||
return null;
|
||||
}
|
||||
compiledFn = retryResult;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
compiledFn = retryResult;
|
||||
} else {
|
||||
compiledFn = compileResult.compiledFn;
|
||||
}
|
||||
@@ -663,7 +682,7 @@ function processFn(
|
||||
|
||||
if (programContext.hasModuleScopeOptOut) {
|
||||
return null;
|
||||
} else if (programContext.opts.noEmit) {
|
||||
} else if (programContext.opts.outputMode === 'lint') {
|
||||
/**
|
||||
* inferEffectDependencies + noEmit is currently only used for linting. In
|
||||
* this mode, add source locations for where the compiler *can* infer effect
|
||||
@@ -693,6 +712,7 @@ function tryCompileFunction(
|
||||
fn: BabelFn,
|
||||
fnType: ReactFunctionType,
|
||||
programContext: ProgramContext,
|
||||
outputMode: CompilerOutputMode,
|
||||
):
|
||||
| {kind: 'compile'; compiledFn: CodegenFunction}
|
||||
| {kind: 'error'; error: unknown} {
|
||||
@@ -719,7 +739,7 @@ function tryCompileFunction(
|
||||
fn,
|
||||
programContext.opts.environment,
|
||||
fnType,
|
||||
'all_features',
|
||||
outputMode,
|
||||
programContext,
|
||||
programContext.opts.logger,
|
||||
programContext.filename,
|
||||
@@ -757,7 +777,7 @@ function retryCompileFunction(
|
||||
fn,
|
||||
environment,
|
||||
fnType,
|
||||
'no_inferred_memo',
|
||||
'client-no-memo',
|
||||
programContext,
|
||||
programContext.opts.logger,
|
||||
programContext.filename,
|
||||
|
||||
@@ -9,7 +9,7 @@ import * as t from '@babel/types';
|
||||
import {ZodError, z} from 'zod/v4';
|
||||
import {fromZodError} from 'zod-validation-error/v4';
|
||||
import {CompilerError} from '../CompilerError';
|
||||
import {Logger, ProgramContext} from '../Entrypoint';
|
||||
import {CompilerOutputMode, Logger, ProgramContext} from '../Entrypoint';
|
||||
import {Err, Ok, Result} from '../Utils/Result';
|
||||
import {
|
||||
DEFAULT_GLOBALS,
|
||||
@@ -51,6 +51,7 @@ import {Scope as BabelScope, NodePath} from '@babel/traverse';
|
||||
import {TypeSchema} from './TypeSchema';
|
||||
import {FlowTypeEnv} from '../Flood/Types';
|
||||
import {defaultModuleTypeProvider} from './DefaultModuleTypeProvider';
|
||||
import {assertExhaustive} from '../Utils/utils';
|
||||
|
||||
export const ReactElementSymbolSchema = z.object({
|
||||
elementSymbol: z.union([
|
||||
@@ -691,8 +692,6 @@ export const EnvironmentConfigSchema = z.object({
|
||||
* by React to only execute in response to events, not during render.
|
||||
*/
|
||||
enableInferEventHandlers: z.boolean().default(false),
|
||||
|
||||
enableOptimizeForSSR: z.boolean().default(false),
|
||||
});
|
||||
|
||||
export type EnvironmentConfig = z.infer<typeof EnvironmentConfigSchema>;
|
||||
@@ -732,7 +731,7 @@ export class Environment {
|
||||
code: string | null;
|
||||
config: EnvironmentConfig;
|
||||
fnType: ReactFunctionType;
|
||||
compilerMode: CompilerMode;
|
||||
outputMode: CompilerOutputMode;
|
||||
programContext: ProgramContext;
|
||||
hasFireRewrite: boolean;
|
||||
hasInferredEffect: boolean;
|
||||
@@ -747,7 +746,7 @@ export class Environment {
|
||||
constructor(
|
||||
scope: BabelScope,
|
||||
fnType: ReactFunctionType,
|
||||
compilerMode: CompilerMode,
|
||||
outputMode: CompilerOutputMode,
|
||||
config: EnvironmentConfig,
|
||||
contextIdentifiers: Set<t.Identifier>,
|
||||
parentFunction: NodePath<t.Function>, // the outermost function being compiled
|
||||
@@ -758,7 +757,7 @@ export class Environment {
|
||||
) {
|
||||
this.#scope = scope;
|
||||
this.fnType = fnType;
|
||||
this.compilerMode = compilerMode;
|
||||
this.outputMode = outputMode;
|
||||
this.config = config;
|
||||
this.filename = filename;
|
||||
this.code = code;
|
||||
@@ -854,8 +853,65 @@ export class Environment {
|
||||
return this.#flowTypeEnvironment;
|
||||
}
|
||||
|
||||
get isInferredMemoEnabled(): boolean {
|
||||
return this.compilerMode !== 'no_inferred_memo';
|
||||
get enableDropManualMemoization(): boolean {
|
||||
switch (this.outputMode) {
|
||||
case 'lint': {
|
||||
// linting drops to be more compatible with compiler analysis
|
||||
return true;
|
||||
}
|
||||
case 'client':
|
||||
case 'ssr': {
|
||||
return true;
|
||||
}
|
||||
case 'client-no-memo': {
|
||||
return false;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(
|
||||
this.outputMode,
|
||||
`Unexpected output mode '${this.outputMode}'`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get enableMemoization(): boolean {
|
||||
switch (this.outputMode) {
|
||||
case 'client':
|
||||
case 'lint': {
|
||||
// linting also enables memoization so that we can check if manual memoization is preserved
|
||||
return true;
|
||||
}
|
||||
case 'ssr':
|
||||
case 'client-no-memo': {
|
||||
return false;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(
|
||||
this.outputMode,
|
||||
`Unexpected output mode '${this.outputMode}'`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get enableValidations(): boolean {
|
||||
switch (this.outputMode) {
|
||||
case 'client':
|
||||
case 'lint':
|
||||
case 'ssr': {
|
||||
return true;
|
||||
}
|
||||
case 'client-no-memo': {
|
||||
return false;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(
|
||||
this.outputMode,
|
||||
`Unexpected output mode '${this.outputMode}'`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get nextIdentifierId(): IdentifierId {
|
||||
|
||||
@@ -2452,7 +2452,7 @@ function computeEffectsForLegacySignature(
|
||||
}),
|
||||
});
|
||||
}
|
||||
if (signature.knownIncompatible != null && state.env.isInferredMemoEnabled) {
|
||||
if (signature.knownIncompatible != null && state.env.enableValidations) {
|
||||
const errors = new CompilerError();
|
||||
errors.pushDiagnostic(
|
||||
CompilerDiagnostic.create({
|
||||
|
||||
@@ -319,7 +319,7 @@ function pruneableValue(value: InstructionValue, state: State): boolean {
|
||||
}
|
||||
case 'CallExpression':
|
||||
case 'MethodCall': {
|
||||
if (state.env.config.enableOptimizeForSSR) {
|
||||
if (state.env.outputMode === 'ssr') {
|
||||
const calleee =
|
||||
value.kind === 'CallExpression' ? value.callee : value.property;
|
||||
const hookKind = getHookKind(state.env, calleee.identifier);
|
||||
|
||||
@@ -159,7 +159,7 @@ export function codegenFunction(
|
||||
const compiled = compileResult.unwrap();
|
||||
|
||||
const hookGuard = fn.env.config.enableEmitHookGuards;
|
||||
if (hookGuard != null && fn.env.isInferredMemoEnabled) {
|
||||
if (hookGuard != null && fn.env.outputMode === 'client') {
|
||||
compiled.body = t.blockStatement([
|
||||
createHookGuard(
|
||||
hookGuard,
|
||||
@@ -259,7 +259,7 @@ export function codegenFunction(
|
||||
if (
|
||||
emitInstrumentForget != null &&
|
||||
fn.id != null &&
|
||||
fn.env.isInferredMemoEnabled
|
||||
fn.env.outputMode === 'client'
|
||||
) {
|
||||
/*
|
||||
* Technically, this is a conditional hook call. However, we expect
|
||||
@@ -591,7 +591,10 @@ function codegenBlockNoReset(
|
||||
}
|
||||
|
||||
function wrapCacheDep(cx: Context, value: t.Expression): t.Expression {
|
||||
if (cx.env.config.enableEmitFreeze != null && cx.env.isInferredMemoEnabled) {
|
||||
if (
|
||||
cx.env.config.enableEmitFreeze != null &&
|
||||
cx.env.outputMode === 'client'
|
||||
) {
|
||||
const emitFreezeIdentifier = cx.env.programContext.addImportSpecifier(
|
||||
cx.env.config.enableEmitFreeze,
|
||||
).name;
|
||||
@@ -1772,7 +1775,7 @@ function createCallExpression(
|
||||
}
|
||||
|
||||
const hookGuard = env.config.enableEmitHookGuards;
|
||||
if (hookGuard != null && isHook && env.isInferredMemoEnabled) {
|
||||
if (hookGuard != null && isHook && env.outputMode === 'client') {
|
||||
const iife = t.functionExpression(
|
||||
null,
|
||||
[],
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @dynamicGating:{"source":"shared-runtime"} @noEmit
|
||||
// @dynamicGating:{"source":"shared-runtime"} @outputMode:"lint"
|
||||
|
||||
function Foo() {
|
||||
'use memo if(getTrue)';
|
||||
@@ -19,7 +19,7 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
// @dynamicGating:{"source":"shared-runtime"} @noEmit
|
||||
// @dynamicGating:{"source":"shared-runtime"} @outputMode:"lint"
|
||||
|
||||
function Foo() {
|
||||
"use memo if(getTrue)";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// @dynamicGating:{"source":"shared-runtime"} @noEmit
|
||||
// @dynamicGating:{"source":"shared-runtime"} @outputMode:"lint"
|
||||
|
||||
function Foo() {
|
||||
'use memo if(getTrue)';
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @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), AUTODEPS);
|
||||
|
||||
const arr2 = [];
|
||||
useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
arr2.push(2);
|
||||
return {arr, arr2};
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Foo,
|
||||
params: [{propVal: 1}],
|
||||
sequentialRenders: [{propVal: 1}, {propVal: 2}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
// @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), AUTODEPS);
|
||||
|
||||
const arr2 = [];
|
||||
useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
arr2.push(2);
|
||||
return { arr, arr2 };
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Foo,
|
||||
params: [{ propVal: 1 }],
|
||||
sequentialRenders: [{ propVal: 1 }, { propVal: 2 }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Logs
|
||||
|
||||
```
|
||||
{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":195},"end":{"line":14,"column":1,"index":409},"filename":"retry-no-emit.ts"},"detail":{"options":{"category":"Immutability","reason":"This value cannot be modified","description":"Modifying a value previously passed as an argument to a hook is not allowed. Consider moving the modification before calling the hook","details":[{"kind":"error","loc":{"start":{"line":12,"column":2,"index":372},"end":{"line":12,"column":6,"index":376},"filename":"retry-no-emit.ts","identifierName":"arr2"},"message":"value cannot be modified"}]}}}
|
||||
{"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
|
||||
(kind: ok) {"arr":[1],"arr2":[2]}
|
||||
{"arr":[2],"arr2":[2]}
|
||||
logs: [[ 1 ],[ 2 ]]
|
||||
@@ -0,0 +1,48 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @outputMode:"lint" @panicThreshold:"none"
|
||||
import {print} from 'shared-runtime';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
function Foo({propVal}) {
|
||||
const arr = [propVal];
|
||||
useEffectWrapper(() => print(arr), AUTODEPS);
|
||||
|
||||
const arr2 = [];
|
||||
useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
arr2.push(2);
|
||||
return {arr, arr2};
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Foo,
|
||||
params: [{propVal: 1}],
|
||||
sequentialRenders: [{propVal: 1}, {propVal: 2}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
|
||||
Error: Cannot infer dependencies of this effect. This will break your build!
|
||||
|
||||
To resolve, either pass a dependency array or fix reported compiler bailout diagnostics.
|
||||
|
||||
error.infer-effect-deps-with-rule-violation--lint.ts:8:2
|
||||
6 | function Foo({propVal}) {
|
||||
7 | const arr = [propVal];
|
||||
> 8 | useEffectWrapper(() => print(arr), AUTODEPS);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cannot infer dependencies
|
||||
9 |
|
||||
10 | const arr2 = [];
|
||||
11 | useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
```
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly
|
||||
// @inferEffectDependencies @outputMode:"lint" @panicThreshold:"none"
|
||||
import {print} from 'shared-runtime';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @outputMode:"lint" @panicThreshold:"none"
|
||||
import {print} from 'shared-runtime';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
function Foo({propVal}) {
|
||||
'use memo';
|
||||
const arr = [propVal];
|
||||
useEffectWrapper(() => print(arr), AUTODEPS);
|
||||
|
||||
const arr2 = [];
|
||||
useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
arr2.push(2);
|
||||
return {arr, arr2};
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Foo,
|
||||
params: [{propVal: 1}],
|
||||
sequentialRenders: [{propVal: 1}, {propVal: 2}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
Found 1 error:
|
||||
|
||||
Error: Cannot infer dependencies of this effect. This will break your build!
|
||||
|
||||
To resolve, either pass a dependency array or fix reported compiler bailout diagnostics.
|
||||
|
||||
error.infer-effect-deps-with-rule-violation-use-memo-opt-in--lint.ts:9:2
|
||||
7 | 'use memo';
|
||||
8 | const arr = [propVal];
|
||||
> 9 | useEffectWrapper(() => print(arr), AUTODEPS);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cannot infer dependencies
|
||||
10 |
|
||||
11 | const arr2 = [];
|
||||
12 | useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
```
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// @compilationMode:"all" @inferEffectDependencies @panicThreshold:"none" @noEmit
|
||||
// @inferEffectDependencies @outputMode:"lint" @panicThreshold:"none"
|
||||
import {print} from 'shared-runtime';
|
||||
import {AUTODEPS} from 'react';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
function Foo({propVal}) {
|
||||
'use memo';
|
||||
@@ -11,7 +11,6 @@ function Foo({propVal}) {
|
||||
const arr2 = [];
|
||||
useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
arr2.push(2);
|
||||
|
||||
return {arr, arr2};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @panicThreshold:"none"
|
||||
import {print} from 'shared-runtime';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
function Foo({propVal}) {
|
||||
const arr = [propVal];
|
||||
useEffectWrapper(() => print(arr), AUTODEPS);
|
||||
|
||||
const arr2 = [];
|
||||
useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
arr2.push(2);
|
||||
return {arr, arr2};
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Foo,
|
||||
params: [{propVal: 1}],
|
||||
sequentialRenders: [{propVal: 1}, {propVal: 2}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @panicThreshold:"none"
|
||||
import { print } from "shared-runtime";
|
||||
import useEffectWrapper from "useEffectWrapper";
|
||||
import { AUTODEPS } from "react";
|
||||
|
||||
function Foo(t0) {
|
||||
const { propVal } = t0;
|
||||
const arr = [propVal];
|
||||
useEffectWrapper(() => print(arr), [arr]);
|
||||
|
||||
const arr2 = [];
|
||||
useEffectWrapper(() => arr2.push(propVal), [arr2, propVal]);
|
||||
arr2.push(2);
|
||||
return { arr, arr2 };
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Foo,
|
||||
params: [{ propVal: 1 }],
|
||||
sequentialRenders: [{ propVal: 1 }, { propVal: 2 }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) {"arr":[1],"arr2":[2]}
|
||||
{"arr":[2],"arr2":[2]}
|
||||
logs: [[ 1 ],[ 2 ]]
|
||||
@@ -1,4 +1,4 @@
|
||||
// @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||
// @inferEffectDependencies @panicThreshold:"none"
|
||||
import {print} from 'shared-runtime';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
@@ -2,10 +2,10 @@
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @compilationMode:"all" @inferEffectDependencies @panicThreshold:"none" @noEmit
|
||||
// @inferEffectDependencies @panicThreshold:"none"
|
||||
import {print} from 'shared-runtime';
|
||||
import {AUTODEPS} from 'react';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
function Foo({propVal}) {
|
||||
'use memo';
|
||||
@@ -15,7 +15,6 @@ function Foo({propVal}) {
|
||||
const arr2 = [];
|
||||
useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
arr2.push(2);
|
||||
|
||||
return {arr, arr2};
|
||||
}
|
||||
|
||||
@@ -30,20 +29,21 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
// @compilationMode:"all" @inferEffectDependencies @panicThreshold:"none" @noEmit
|
||||
// @inferEffectDependencies @panicThreshold:"none"
|
||||
import { print } from "shared-runtime";
|
||||
import { AUTODEPS } from "react";
|
||||
import useEffectWrapper from "useEffectWrapper";
|
||||
import { AUTODEPS } from "react";
|
||||
|
||||
function Foo({ propVal }) {
|
||||
function Foo(t0) {
|
||||
"use memo";
|
||||
const { propVal } = t0;
|
||||
|
||||
const arr = [propVal];
|
||||
useEffectWrapper(() => print(arr), AUTODEPS);
|
||||
useEffectWrapper(() => print(arr), [arr]);
|
||||
|
||||
const arr2 = [];
|
||||
useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
useEffectWrapper(() => arr2.push(propVal), [arr2, propVal]);
|
||||
arr2.push(2);
|
||||
|
||||
return { arr, arr2 };
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// @inferEffectDependencies @panicThreshold:"none"
|
||||
import {print} from 'shared-runtime';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
function Foo({propVal}) {
|
||||
'use memo';
|
||||
const arr = [propVal];
|
||||
useEffectWrapper(() => print(arr), AUTODEPS);
|
||||
|
||||
const arr2 = [];
|
||||
useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
arr2.push(2);
|
||||
return {arr, arr2};
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Foo,
|
||||
params: [{propVal: 1}],
|
||||
sequentialRenders: [{propVal: 1}, {propVal: 2}],
|
||||
};
|
||||
@@ -2,7 +2,7 @@
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @noEmit
|
||||
// @inferEffectDependencies @outputMode:"lint"
|
||||
import {print} from 'shared-runtime';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
@@ -17,7 +17,7 @@ function ReactiveVariable({propVal}) {
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @noEmit
|
||||
// @inferEffectDependencies @outputMode:"lint"
|
||||
import { print } from "shared-runtime";
|
||||
import useEffectWrapper from "useEffectWrapper";
|
||||
import { AUTODEPS } from "react";
|
||||
@@ -1,4 +1,4 @@
|
||||
// @inferEffectDependencies @noEmit
|
||||
// @inferEffectDependencies @outputMode:"lint"
|
||||
import {print} from 'shared-runtime';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
@@ -1,66 +0,0 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||
import {print} from 'shared-runtime';
|
||||
import useEffectWrapper from 'useEffectWrapper';
|
||||
import {AUTODEPS} from 'react';
|
||||
|
||||
function Foo({propVal}) {
|
||||
const arr = [propVal];
|
||||
useEffectWrapper(() => print(arr), AUTODEPS);
|
||||
|
||||
const arr2 = [];
|
||||
useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
arr2.push(2);
|
||||
return {arr, arr2};
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Foo,
|
||||
params: [{propVal: 1}],
|
||||
sequentialRenders: [{propVal: 1}, {propVal: 2}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
// @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||
import { print } from "shared-runtime";
|
||||
import useEffectWrapper from "useEffectWrapper";
|
||||
import { AUTODEPS } from "react";
|
||||
|
||||
function Foo({ propVal }) {
|
||||
const arr = [propVal];
|
||||
useEffectWrapper(() => print(arr), AUTODEPS);
|
||||
|
||||
const arr2 = [];
|
||||
useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
|
||||
arr2.push(2);
|
||||
return { arr, arr2 };
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Foo,
|
||||
params: [{ propVal: 1 }],
|
||||
sequentialRenders: [{ propVal: 1 }, { propVal: 2 }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Logs
|
||||
|
||||
```
|
||||
{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":227},"end":{"line":14,"column":1,"index":441},"filename":"retry-no-emit.ts"},"detail":{"options":{"category":"Immutability","reason":"This value cannot be modified","description":"Modifying a value previously passed as an argument to a hook is not allowed. Consider moving the modification before calling the hook","details":[{"kind":"error","loc":{"start":{"line":12,"column":2,"index":404},"end":{"line":12,"column":6,"index":408},"filename":"retry-no-emit.ts","identifierName":"arr2"},"message":"value cannot be modified"}]}}}
|
||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":280},"end":{"line":8,"column":46,"index":324},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":8,"column":31,"index":309},"end":{"line":8,"column":34,"index":312},"filename":"retry-no-emit.ts","identifierName":"arr"}]}
|
||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":11,"column":2,"index":348},"end":{"line":11,"column":54,"index":400},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":11,"column":25,"index":371},"end":{"line":11,"column":29,"index":375},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":11,"column":25,"index":371},"end":{"line":11,"column":29,"index":375},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":11,"column":35,"index":381},"end":{"line":11,"column":42,"index":388},"filename":"retry-no-emit.ts","identifierName":"propVal"}]}
|
||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":227},"end":{"line":14,"column":1,"index":441},"filename":"retry-no-emit.ts"},"fnName":"Foo","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) {"arr":[1],"arr2":[2]}
|
||||
{"arr":[2],"arr2":[2]}
|
||||
logs: [[ 1 ],[ 2 ]]
|
||||
@@ -20,10 +20,40 @@ function Component() {
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
// @enableOptimizeForSSR
|
||||
import { c as _c } from "react/compiler-runtime"; // @enableOptimizeForSSR
|
||||
function Component() {
|
||||
const state = 0;
|
||||
return <input value={state} />;
|
||||
const $ = _c(4);
|
||||
const [state, setState] = useState(0);
|
||||
const ref = useRef(null);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = (e) => {
|
||||
setState(e.target.value);
|
||||
};
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
const onChange = t0;
|
||||
let t1;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = () => {
|
||||
log(ref.current.value);
|
||||
};
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
useEffect(t1);
|
||||
let t2;
|
||||
if ($[2] !== state) {
|
||||
t2 = <input value={state} onChange={onChange} ref={ref} />;
|
||||
$[2] = state;
|
||||
$[3] = t2;
|
||||
} else {
|
||||
t2 = $[3];
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -22,12 +22,40 @@ function Component() {
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
// @enableOptimizeForSSR
|
||||
import { c as _c } from "react/compiler-runtime"; // @enableOptimizeForSSR
|
||||
function Component() {
|
||||
const state = 0;
|
||||
const $ = _c(4);
|
||||
const [state, setState] = useState(0);
|
||||
const ref = useRef(null);
|
||||
const onChange = undefined;
|
||||
return <CustomInput value={state} onChange={onChange} ref={ref} />;
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = (e) => {
|
||||
setState(e.target.value);
|
||||
};
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
const onChange = t0;
|
||||
let t1;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = () => {
|
||||
log(ref.current.value);
|
||||
};
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
useEffect(t1);
|
||||
let t2;
|
||||
if ($[2] !== state) {
|
||||
t2 = <CustomInput value={state} onChange={onChange} ref={ref} />;
|
||||
$[2] = state;
|
||||
$[3] = t2;
|
||||
} else {
|
||||
t2 = $[3];
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -25,13 +25,43 @@ function Component() {
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
// @enableOptimizeForSSR
|
||||
import { c as _c } from "react/compiler-runtime"; // @enableOptimizeForSSR
|
||||
function Component() {
|
||||
useTransition();
|
||||
const state = 0;
|
||||
const $ = _c(4);
|
||||
const [, startTransition] = useTransition();
|
||||
const [state, setState] = useState(0);
|
||||
const ref = useRef(null);
|
||||
const onChange = undefined;
|
||||
return <CustomInput value={state} onChange={onChange} ref={ref} />;
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = (e) => {
|
||||
startTransition(() => {
|
||||
setState.call(null, e.target.value);
|
||||
});
|
||||
};
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
const onChange = t0;
|
||||
let t1;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = () => {
|
||||
log(ref.current.value);
|
||||
};
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
useEffect(t1);
|
||||
let t2;
|
||||
if ($[2] !== state) {
|
||||
t2 = <CustomInput value={state} onChange={onChange} ref={ref} />;
|
||||
$[2] = state;
|
||||
$[3] = t2;
|
||||
} else {
|
||||
t2 = $[3];
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -25,7 +25,7 @@ function Component() {
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
// @enableOptimizeForSSR
|
||||
import { c as _c } from "react/compiler-runtime"; // @enableOptimizeForSSR
|
||||
|
||||
import { useReducer } from "react";
|
||||
|
||||
@@ -34,8 +34,41 @@ const initializer = (x) => {
|
||||
};
|
||||
|
||||
function Component() {
|
||||
const state = initializer(0);
|
||||
return <input value={state} />;
|
||||
const $ = _c(4);
|
||||
const [state, dispatch] = useReducer(_temp, 0, initializer);
|
||||
const ref = useRef(null);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = (e) => {
|
||||
dispatch(e.target.value);
|
||||
};
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
const onChange = t0;
|
||||
let t1;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = () => {
|
||||
log(ref.current.value);
|
||||
};
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
useEffect(t1);
|
||||
let t2;
|
||||
if ($[2] !== state) {
|
||||
t2 = <input value={state} onChange={onChange} ref={ref} />;
|
||||
$[2] = state;
|
||||
$[3] = t2;
|
||||
} else {
|
||||
t2 = $[3];
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
function _temp(_, next) {
|
||||
return next;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -23,13 +23,46 @@ function Component() {
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
// @enableOptimizeForSSR
|
||||
import { c as _c } from "react/compiler-runtime"; // @enableOptimizeForSSR
|
||||
|
||||
import { useReducer } from "react";
|
||||
|
||||
function Component() {
|
||||
const state = 0;
|
||||
return <input value={state} />;
|
||||
const $ = _c(4);
|
||||
const [state, dispatch] = useReducer(_temp, 0);
|
||||
const ref = useRef(null);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = (e) => {
|
||||
dispatch(e.target.value);
|
||||
};
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
const onChange = t0;
|
||||
let t1;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = () => {
|
||||
log(ref.current.value);
|
||||
};
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
useEffect(t1);
|
||||
let t2;
|
||||
if ($[2] !== state) {
|
||||
t2 = <input value={state} onChange={onChange} ref={ref} />;
|
||||
$[2] = state;
|
||||
$[3] = t2;
|
||||
} else {
|
||||
t2 = $[3];
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
function _temp(_, next) {
|
||||
return next;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @noEmit
|
||||
// @outputMode:"lint"
|
||||
|
||||
function Foo() {
|
||||
'use memo';
|
||||
@@ -19,7 +19,7 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
// @noEmit
|
||||
// @outputMode:"lint"
|
||||
|
||||
function Foo() {
|
||||
"use memo";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// @noEmit
|
||||
// @outputMode:"lint"
|
||||
|
||||
function Foo() {
|
||||
'use memo';
|
||||
|
||||
@@ -21,7 +21,7 @@ import {isDeepStrictEqual} from 'util';
|
||||
import type {ParseResult} from '@babel/parser';
|
||||
|
||||
const COMPILER_OPTIONS: PluginOptions = {
|
||||
noEmit: true,
|
||||
outputMode: 'lint',
|
||||
panicThreshold: 'none',
|
||||
// Don't emit errors on Flow suppressions--Flow already gave a signal
|
||||
flowSuppressions: false,
|
||||
|
||||
Reference in New Issue
Block a user