Repository: facebook/react Branch: main Commit: 80b1cab39776 Files: 6660 Total size: 25.0 MB Directory structure: gitextract_j2mop8l5/ ├── .claude/ │ ├── instructions.md │ ├── settings.json │ └── skills/ │ ├── extract-errors/ │ │ └── SKILL.md │ ├── feature-flags/ │ │ └── SKILL.md │ ├── fix/ │ │ └── SKILL.md │ ├── flags/ │ │ └── SKILL.md │ ├── flow/ │ │ └── SKILL.md │ ├── test/ │ │ └── SKILL.md │ └── verify/ │ └── SKILL.md ├── .codesandbox/ │ └── ci.json ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .git-blame-ignore-revs ├── .gitattributes ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ ├── compiler_bug_report.yml │ │ ├── config.yml │ │ └── devtools_bug_report.yml │ ├── PULL_REQUEST_TEMPLATE.md │ ├── dependabot.yml │ └── workflows/ │ ├── compiler_discord_notify.yml │ ├── compiler_playground.yml │ ├── compiler_prereleases.yml │ ├── compiler_prereleases_manual.yml │ ├── compiler_prereleases_nightly.yml │ ├── compiler_typescript.yml │ ├── devtools_discord_notify.yml │ ├── devtools_regression_tests.yml │ ├── runtime_build_and_test.yml │ ├── runtime_commit_artifacts.yml │ ├── runtime_discord_notify.yml │ ├── runtime_eslint_plugin_e2e.yml │ ├── runtime_fuzz_tests.yml │ ├── runtime_prereleases.yml │ ├── runtime_prereleases_manual.yml │ ├── runtime_prereleases_nightly.yml │ ├── runtime_releases_from_npm_manual.yml │ ├── shared_check_maintainer.yml │ ├── shared_cleanup_merged_branch_caches.yml │ ├── shared_cleanup_stale_branch_caches.yml │ ├── shared_close_direct_sync_branch_prs.yml │ ├── shared_label_core_team_prs.yml │ ├── shared_lint.yml │ └── shared_stale.yml ├── .gitignore ├── .mailmap ├── .nvmrc ├── .prettierignore ├── .prettierrc.js ├── .watchmanconfig ├── CHANGELOG.md ├── CLAUDE.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── MAINTAINERS ├── README.md ├── ReactVersions.js ├── SECURITY.md ├── babel.config-react-compiler.js ├── babel.config-ts.js ├── babel.config.js ├── compiler/ │ ├── .claude/ │ │ ├── agents/ │ │ │ └── investigate-error.md │ │ └── settings.json │ ├── .eslintrc.js │ ├── .gitignore │ ├── CHANGELOG.md │ ├── CLAUDE.md │ ├── README.md │ ├── apps/ │ │ └── playground/ │ │ ├── .eslintrc.json │ │ ├── .gitignore │ │ ├── README.md │ │ ├── __tests__/ │ │ │ ├── e2e/ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ └── page.spec.ts/ │ │ │ │ │ ├── 01-user-output.txt │ │ │ │ │ ├── 02-default-output.txt │ │ │ │ │ ├── compilationMode-all-output.txt │ │ │ │ │ ├── compilationMode-infer-output.txt │ │ │ │ │ ├── default-config.txt │ │ │ │ │ ├── function-scope-beats-module-scope-output.txt │ │ │ │ │ ├── module-scope-use-memo-output.txt │ │ │ │ │ ├── module-scope-use-no-memo-output.txt │ │ │ │ │ ├── parse-flow-output.txt │ │ │ │ │ ├── parse-typescript-output.txt │ │ │ │ │ ├── todo-function-scope-does-not-beat-module-scope-output.txt │ │ │ │ │ ├── use-memo-output.txt │ │ │ │ │ └── use-no-memo-output.txt │ │ │ │ └── page.spec.ts │ │ │ └── parseConfigOverrides.test.mjs │ │ ├── app/ │ │ │ ├── layout.tsx │ │ │ └── page.tsx │ │ ├── colors.js │ │ ├── components/ │ │ │ ├── AccordionWindow.tsx │ │ │ ├── Editor/ │ │ │ │ ├── ConfigEditor.tsx │ │ │ │ ├── EditorImpl.tsx │ │ │ │ ├── Input.tsx │ │ │ │ ├── Output.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── monacoOptions.ts │ │ │ ├── Header.tsx │ │ │ ├── Icons/ │ │ │ │ ├── IconChevron.tsx │ │ │ │ └── IconGitHub.tsx │ │ │ ├── Logo.tsx │ │ │ ├── Message.tsx │ │ │ ├── StoreContext.tsx │ │ │ ├── TabbedWindow.tsx │ │ │ └── index.ts │ │ ├── hooks/ │ │ │ ├── index.ts │ │ │ └── useMountEffect.ts │ │ ├── lib/ │ │ │ ├── compilation.ts │ │ │ ├── createContext.ts │ │ │ ├── defaultStore.ts │ │ │ ├── reactCompilerMonacoDiagnostics.ts │ │ │ ├── stores/ │ │ │ │ ├── index.ts │ │ │ │ ├── messages.ts │ │ │ │ └── store.ts │ │ │ ├── transitionTypes.ts │ │ │ └── types.d.ts │ │ ├── next.config.js │ │ ├── package.json │ │ ├── playwright.config.js │ │ ├── postcss.config.js │ │ ├── public/ │ │ │ ├── graphvizlib.wasm │ │ │ └── site.webmanifest │ │ ├── scripts/ │ │ │ ├── downloadFonts.js │ │ │ └── link-compiler.sh │ │ ├── styles/ │ │ │ └── globals.css │ │ ├── tailwind.config.js │ │ ├── tsconfig.json │ │ └── vercel.json │ ├── docs/ │ │ ├── DESIGN_GOALS.md │ │ └── DEVELOPMENT_GUIDE.md │ ├── fixtures/ │ │ └── .gitkeep │ ├── package.json │ ├── packages/ │ │ ├── babel-plugin-react-compiler/ │ │ │ ├── README.md │ │ │ ├── docs/ │ │ │ │ └── passes/ │ │ │ │ ├── 01-lower.md │ │ │ │ ├── 02-enterSSA.md │ │ │ │ ├── 03-eliminateRedundantPhi.md │ │ │ │ ├── 04-constantPropagation.md │ │ │ │ ├── 05-deadCodeElimination.md │ │ │ │ ├── 06-inferTypes.md │ │ │ │ ├── 07-analyseFunctions.md │ │ │ │ ├── 08-inferMutationAliasingEffects.md │ │ │ │ ├── 09-inferMutationAliasingRanges.md │ │ │ │ ├── 10-inferReactivePlaces.md │ │ │ │ ├── 11-inferReactiveScopeVariables.md │ │ │ │ ├── 12-rewriteInstructionKindsBasedOnReassignment.md │ │ │ │ ├── 13-alignMethodCallScopes.md │ │ │ │ ├── 14-alignObjectMethodScopes.md │ │ │ │ ├── 15-alignReactiveScopesToBlockScopesHIR.md │ │ │ │ ├── 16-mergeOverlappingReactiveScopesHIR.md │ │ │ │ ├── 17-buildReactiveScopeTerminalsHIR.md │ │ │ │ ├── 18-flattenReactiveLoopsHIR.md │ │ │ │ ├── 19-flattenScopesWithHooksOrUseHIR.md │ │ │ │ ├── 20-propagateScopeDependenciesHIR.md │ │ │ │ ├── 21-buildReactiveFunction.md │ │ │ │ ├── 22-pruneUnusedLabels.md │ │ │ │ ├── 23-pruneNonEscapingScopes.md │ │ │ │ ├── 24-pruneNonReactiveDependencies.md │ │ │ │ ├── 25-pruneUnusedScopes.md │ │ │ │ ├── 26-mergeReactiveScopesThatInvalidateTogether.md │ │ │ │ ├── 27-pruneAlwaysInvalidatingScopes.md │ │ │ │ ├── 28-propagateEarlyReturns.md │ │ │ │ ├── 29-promoteUsedTemporaries.md │ │ │ │ ├── 30-renameVariables.md │ │ │ │ ├── 31-codegenReactiveFunction.md │ │ │ │ ├── 34-optimizePropsMethodCalls.md │ │ │ │ ├── 35-optimizeForSSR.md │ │ │ │ ├── 36-outlineJSX.md │ │ │ │ ├── 37-outlineFunctions.md │ │ │ │ ├── 38-memoizeFbtAndMacroOperandsInSameScope.md │ │ │ │ ├── 39-validateContextVariableLValues.md │ │ │ │ ├── 40-validateUseMemo.md │ │ │ │ ├── 41-validateHooksUsage.md │ │ │ │ ├── 42-validateNoCapitalizedCalls.md │ │ │ │ ├── 43-validateLocalsNotReassignedAfterRender.md │ │ │ │ ├── 44-validateNoSetStateInRender.md │ │ │ │ ├── 45-validateNoDerivedComputationsInEffects.md │ │ │ │ ├── 46-validateNoSetStateInEffects.md │ │ │ │ ├── 47-validateNoJSXInTryStatement.md │ │ │ │ ├── 48-validateNoImpureValuesInRender.md │ │ │ │ ├── 49-validateNoRefAccessInRender.md │ │ │ │ ├── 50-validateNoFreezingKnownMutableFunctions.md │ │ │ │ ├── 51-validateExhaustiveDependencies.md │ │ │ │ ├── 53-validatePreservedManualMemoization.md │ │ │ │ ├── 54-validateStaticComponents.md │ │ │ │ ├── 55-validateSourceLocations.md │ │ │ │ └── README.md │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── scripts/ │ │ │ │ ├── babel-plugin-annotate-react-code.ts │ │ │ │ ├── build-react-hooks-fixures.js │ │ │ │ ├── eslint-plugin-react-hooks-test-cases.js │ │ │ │ ├── jest/ │ │ │ │ │ ├── e2e-classic.config.js │ │ │ │ │ ├── e2e-forget.config.js │ │ │ │ │ ├── main.config.js │ │ │ │ │ ├── makeE2EConfig.js │ │ │ │ │ ├── makeSnapshotResolver.js │ │ │ │ │ ├── makeTransform.ts │ │ │ │ │ ├── snapshot-resolver-no-forget.js │ │ │ │ │ ├── snapshot-resolver-with-forget.js │ │ │ │ │ ├── transform-no-forget.js │ │ │ │ │ └── transform-with-forget.js │ │ │ │ ├── link-react-compiler-runtime.sh │ │ │ │ └── ts-analyze-trace.sh │ │ │ ├── src/ │ │ │ │ ├── Babel/ │ │ │ │ │ ├── BabelPlugin.ts │ │ │ │ │ └── RunReactCompilerBabelPlugin.ts │ │ │ │ ├── CompilerError.ts │ │ │ │ ├── Entrypoint/ │ │ │ │ │ ├── Gating.ts │ │ │ │ │ ├── Imports.ts │ │ │ │ │ ├── Options.ts │ │ │ │ │ ├── Pipeline.ts │ │ │ │ │ ├── Program.ts │ │ │ │ │ ├── Reanimated.ts │ │ │ │ │ ├── Suppression.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── Flood/ │ │ │ │ │ ├── FlowTypes.ts │ │ │ │ │ ├── TypeErrors.ts │ │ │ │ │ ├── TypeUtils.ts │ │ │ │ │ └── Types.ts │ │ │ │ ├── HIR/ │ │ │ │ │ ├── AssertConsistentIdentifiers.ts │ │ │ │ │ ├── AssertTerminalBlocksExist.ts │ │ │ │ │ ├── AssertValidBlockNesting.ts │ │ │ │ │ ├── AssertValidMutableRanges.ts │ │ │ │ │ ├── BuildHIR.ts │ │ │ │ │ ├── BuildReactiveScopeTerminalsHIR.ts │ │ │ │ │ ├── CollectHoistablePropertyLoads.ts │ │ │ │ │ ├── CollectOptionalChainDependencies.ts │ │ │ │ │ ├── ComputeUnconditionalBlocks.ts │ │ │ │ │ ├── DefaultModuleTypeProvider.ts │ │ │ │ │ ├── DeriveMinimalDependenciesHIR.ts │ │ │ │ │ ├── Dominator.ts │ │ │ │ │ ├── Environment.ts │ │ │ │ │ ├── FindContextIdentifiers.ts │ │ │ │ │ ├── Globals.ts │ │ │ │ │ ├── HIR.ts │ │ │ │ │ ├── HIRBuilder.ts │ │ │ │ │ ├── MergeConsecutiveBlocks.ts │ │ │ │ │ ├── MergeOverlappingReactiveScopesHIR.ts │ │ │ │ │ ├── ObjectShape.ts │ │ │ │ │ ├── PrintHIR.ts │ │ │ │ │ ├── PropagateScopeDependenciesHIR.ts │ │ │ │ │ ├── PruneUnusedLabelsHIR.ts │ │ │ │ │ ├── ScopeDependencyUtils.ts │ │ │ │ │ ├── TypeSchema.ts │ │ │ │ │ ├── Types.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── visitors.ts │ │ │ │ ├── Inference/ │ │ │ │ │ ├── AliasingEffects.ts │ │ │ │ │ ├── AnalyseFunctions.ts │ │ │ │ │ ├── ControlDominators.ts │ │ │ │ │ ├── DropManualMemoization.ts │ │ │ │ │ ├── InferMutationAliasingEffects.ts │ │ │ │ │ ├── InferMutationAliasingRanges.ts │ │ │ │ │ ├── InferReactivePlaces.ts │ │ │ │ │ ├── InlineImmediatelyInvokedFunctionExpressions.ts │ │ │ │ │ ├── MUTABILITY_ALIASING_MODEL.md │ │ │ │ │ └── index.ts │ │ │ │ ├── Optimization/ │ │ │ │ │ ├── ConstantPropagation.ts │ │ │ │ │ ├── DeadCodeElimination.ts │ │ │ │ │ ├── OptimizeForSSR.ts │ │ │ │ │ ├── OptimizePropsMethodCalls.ts │ │ │ │ │ ├── OutlineFunctions.ts │ │ │ │ │ ├── OutlineJsx.ts │ │ │ │ │ ├── PruneMaybeThrows.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── ReactiveScopes/ │ │ │ │ │ ├── AlignMethodCallScopes.ts │ │ │ │ │ ├── AlignObjectMethodScopes.ts │ │ │ │ │ ├── AlignReactiveScopesToBlockScopesHIR.ts │ │ │ │ │ ├── AssertScopeInstructionsWithinScope.ts │ │ │ │ │ ├── AssertWellFormedBreakTargets.ts │ │ │ │ │ ├── BuildReactiveFunction.ts │ │ │ │ │ ├── CodegenReactiveFunction.ts │ │ │ │ │ ├── CollectReactiveIdentifiers.ts │ │ │ │ │ ├── CollectReferencedGlobals.ts │ │ │ │ │ ├── ExtractScopeDeclarationsFromDestructuring.ts │ │ │ │ │ ├── FlattenReactiveLoopsHIR.ts │ │ │ │ │ ├── FlattenScopesWithHooksOrUseHIR.ts │ │ │ │ │ ├── InferReactiveScopeVariables.ts │ │ │ │ │ ├── MemoizeFbtAndMacroOperandsInSameScope.ts │ │ │ │ │ ├── MergeReactiveScopesThatInvalidateTogether.ts │ │ │ │ │ ├── PrintReactiveFunction.ts │ │ │ │ │ ├── PromoteUsedTemporaries.ts │ │ │ │ │ ├── PropagateEarlyReturns.ts │ │ │ │ │ ├── PruneAllReactiveScopes.ts │ │ │ │ │ ├── PruneAlwaysInvalidatingScopes.ts │ │ │ │ │ ├── PruneHoistedContexts.ts │ │ │ │ │ ├── PruneNonEscapingScopes.ts │ │ │ │ │ ├── PruneNonReactiveDependencies.ts │ │ │ │ │ ├── PruneTemporaryLValues.ts │ │ │ │ │ ├── PruneUnusedLabels.ts │ │ │ │ │ ├── PruneUnusedScopes.ts │ │ │ │ │ ├── RenameVariables.ts │ │ │ │ │ ├── StabilizeBlockIds.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── visitors.ts │ │ │ │ ├── SSA/ │ │ │ │ │ ├── EliminateRedundantPhi.ts │ │ │ │ │ ├── EnterSSA.ts │ │ │ │ │ ├── RewriteInstructionKindsBasedOnReassignment.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── Transform/ │ │ │ │ │ ├── NameAnonymousFunctions.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── TypeInference/ │ │ │ │ │ ├── InferTypes.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── Utils/ │ │ │ │ │ ├── ComponentDeclaration.ts │ │ │ │ │ ├── DisjointSet.ts │ │ │ │ │ ├── HookDeclaration.ts │ │ │ │ │ ├── Keyword.ts │ │ │ │ │ ├── Result.ts │ │ │ │ │ ├── RuntimeDiagnosticConstants.ts │ │ │ │ │ ├── Stack.ts │ │ │ │ │ ├── TestUtils.ts │ │ │ │ │ ├── todo.ts │ │ │ │ │ ├── types.d.ts │ │ │ │ │ └── utils.ts │ │ │ │ ├── Validation/ │ │ │ │ │ ├── ValidateContextVariableLValues.ts │ │ │ │ │ ├── ValidateExhaustiveDependencies.ts │ │ │ │ │ ├── ValidateHooksUsage.ts │ │ │ │ │ ├── ValidateLocalsNotReassignedAfterRender.ts │ │ │ │ │ ├── ValidateNoCapitalizedCalls.ts │ │ │ │ │ ├── ValidateNoDerivedComputationsInEffects.ts │ │ │ │ │ ├── ValidateNoDerivedComputationsInEffects_exp.ts │ │ │ │ │ ├── ValidateNoFreezingKnownMutableFunctions.ts │ │ │ │ │ ├── ValidateNoImpureFunctionsInRender.ts │ │ │ │ │ ├── ValidateNoJSXInTryStatement.ts │ │ │ │ │ ├── ValidateNoRefAccessInRender.ts │ │ │ │ │ ├── ValidateNoSetStateInEffects.ts │ │ │ │ │ ├── ValidateNoSetStateInRender.ts │ │ │ │ │ ├── ValidatePreservedManualMemoization.ts │ │ │ │ │ ├── ValidateSourceLocations.ts │ │ │ │ │ ├── ValidateStaticComponents.ts │ │ │ │ │ ├── ValidateUseMemo.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── __tests__/ │ │ │ │ │ ├── DisjointSet-test.ts │ │ │ │ │ ├── Logger-test.ts │ │ │ │ │ ├── Result-test.ts │ │ │ │ │ ├── e2e/ │ │ │ │ │ │ ├── constant-prop.e2e.js │ │ │ │ │ │ ├── expectLogs.js │ │ │ │ │ │ ├── hello.e2e.js │ │ │ │ │ │ ├── update-button.e2e.js │ │ │ │ │ │ ├── update-expressions.e2e.js │ │ │ │ │ │ └── use-state.e2e.js │ │ │ │ │ ├── envConfig-test.ts │ │ │ │ │ ├── fixtures/ │ │ │ │ │ │ ├── compiler/ │ │ │ │ │ │ │ ├── alias-capture-in-method-receiver-and-mutate.expect.md │ │ │ │ │ │ │ ├── alias-capture-in-method-receiver-and-mutate.js │ │ │ │ │ │ │ ├── alias-capture-in-method-receiver.expect.md │ │ │ │ │ │ │ ├── alias-capture-in-method-receiver.js │ │ │ │ │ │ │ ├── alias-computed-load.expect.md │ │ │ │ │ │ │ ├── alias-computed-load.js │ │ │ │ │ │ │ ├── alias-nested-member-path-mutate.expect.md │ │ │ │ │ │ │ ├── alias-nested-member-path-mutate.js │ │ │ │ │ │ │ ├── alias-nested-member-path.expect.md │ │ │ │ │ │ │ ├── alias-nested-member-path.js │ │ │ │ │ │ │ ├── alias-while.expect.md │ │ │ │ │ │ │ ├── alias-while.js │ │ │ │ │ │ │ ├── aliased-nested-scope-fn-expr.expect.md │ │ │ │ │ │ │ ├── aliased-nested-scope-fn-expr.tsx │ │ │ │ │ │ │ ├── aliased-nested-scope-truncated-dep.expect.md │ │ │ │ │ │ │ ├── aliased-nested-scope-truncated-dep.tsx │ │ │ │ │ │ │ ├── align-scope-starts-within-cond.expect.md │ │ │ │ │ │ │ ├── align-scope-starts-within-cond.ts │ │ │ │ │ │ │ ├── align-scopes-iife-return-modified-later-logical.expect.md │ │ │ │ │ │ │ ├── align-scopes-iife-return-modified-later-logical.ts │ │ │ │ │ │ │ ├── align-scopes-nested-block-structure.expect.md │ │ │ │ │ │ │ ├── align-scopes-nested-block-structure.ts │ │ │ │ │ │ │ ├── align-scopes-reactive-scope-overlaps-if.expect.md │ │ │ │ │ │ │ ├── align-scopes-reactive-scope-overlaps-if.ts │ │ │ │ │ │ │ ├── align-scopes-reactive-scope-overlaps-label.expect.md │ │ │ │ │ │ │ ├── align-scopes-reactive-scope-overlaps-label.ts │ │ │ │ │ │ │ ├── align-scopes-reactive-scope-overlaps-try.expect.md │ │ │ │ │ │ │ ├── align-scopes-reactive-scope-overlaps-try.ts │ │ │ │ │ │ │ ├── align-scopes-trycatch-nested-overlapping-range.expect.md │ │ │ │ │ │ │ ├── align-scopes-trycatch-nested-overlapping-range.ts │ │ │ │ │ │ │ ├── align-scopes-within-nested-valueblock-in-array.expect.md │ │ │ │ │ │ │ ├── align-scopes-within-nested-valueblock-in-array.tsx │ │ │ │ │ │ │ ├── allocating-logical-expression-instruction-scope.expect.md │ │ │ │ │ │ │ ├── allocating-logical-expression-instruction-scope.ts │ │ │ │ │ │ │ ├── allocating-primitive-as-dep-nested-scope.expect.md │ │ │ │ │ │ │ ├── allocating-primitive-as-dep-nested-scope.js │ │ │ │ │ │ │ ├── allocating-primitive-as-dep.expect.md │ │ │ │ │ │ │ ├── allocating-primitive-as-dep.js │ │ │ │ │ │ │ ├── allow-assigning-ref-accessing-function-to-object-property-if-not-mutated.expect.md │ │ │ │ │ │ │ ├── allow-assigning-ref-accessing-function-to-object-property-if-not-mutated.js │ │ │ │ │ │ │ ├── allow-assigning-to-global-in-function-spread-as-jsx.expect.md │ │ │ │ │ │ │ ├── allow-assigning-to-global-in-function-spread-as-jsx.js │ │ │ │ │ │ │ ├── allow-global-mutation-in-effect-indirect-usecallback.expect.md │ │ │ │ │ │ │ ├── allow-global-mutation-in-effect-indirect-usecallback.js │ │ │ │ │ │ │ ├── allow-global-mutation-in-effect-indirect.expect.md │ │ │ │ │ │ │ ├── allow-global-mutation-in-effect-indirect.js │ │ │ │ │ │ │ ├── allow-global-mutation-unused-usecallback.expect.md │ │ │ │ │ │ │ ├── allow-global-mutation-unused-usecallback.js │ │ │ │ │ │ │ ├── allow-global-reassignment-in-effect-indirect.expect.md │ │ │ │ │ │ │ ├── allow-global-reassignment-in-effect-indirect.js │ │ │ │ │ │ │ ├── allow-global-reassignment-in-effect.expect.md │ │ │ │ │ │ │ ├── allow-global-reassignment-in-effect.js │ │ │ │ │ │ │ ├── allow-merge-refs-pattern.expect.md │ │ │ │ │ │ │ ├── allow-merge-refs-pattern.js │ │ │ │ │ │ │ ├── allow-modify-global-in-callback-jsx.expect.md │ │ │ │ │ │ │ ├── allow-modify-global-in-callback-jsx.js │ │ │ │ │ │ │ ├── allow-mutate-global-in-effect-fixpoint.expect.md │ │ │ │ │ │ │ ├── allow-mutate-global-in-effect-fixpoint.js │ │ │ │ │ │ │ ├── allow-mutating-ref-in-callback-passed-to-jsx-indirect.expect.md │ │ │ │ │ │ │ ├── allow-mutating-ref-in-callback-passed-to-jsx-indirect.tsx │ │ │ │ │ │ │ ├── allow-mutating-ref-in-callback-passed-to-jsx.expect.md │ │ │ │ │ │ │ ├── allow-mutating-ref-in-callback-passed-to-jsx.tsx │ │ │ │ │ │ │ ├── allow-mutating-ref-property-in-callback-passed-to-jsx-indirect.expect.md │ │ │ │ │ │ │ ├── allow-mutating-ref-property-in-callback-passed-to-jsx-indirect.tsx │ │ │ │ │ │ │ ├── allow-mutating-ref-property-in-callback-passed-to-jsx.expect.md │ │ │ │ │ │ │ ├── allow-mutating-ref-property-in-callback-passed-to-jsx.tsx │ │ │ │ │ │ │ ├── allow-passing-ref-to-render-helper-props-object.expect.md │ │ │ │ │ │ │ ├── allow-passing-ref-to-render-helper-props-object.js │ │ │ │ │ │ │ ├── allow-passing-ref-to-render-helper.expect.md │ │ │ │ │ │ │ ├── allow-passing-ref-to-render-helper.js │ │ │ │ │ │ │ ├── allow-passing-refs-as-props.expect.md │ │ │ │ │ │ │ ├── allow-passing-refs-as-props.js │ │ │ │ │ │ │ ├── allow-reassignment-to-global-function-jsx-prop.expect.md │ │ │ │ │ │ │ ├── allow-reassignment-to-global-function-jsx-prop.js │ │ │ │ │ │ │ ├── allow-ref-access-in-effect-indirect.expect.md │ │ │ │ │ │ │ ├── allow-ref-access-in-effect-indirect.js │ │ │ │ │ │ │ ├── allow-ref-access-in-effect.expect.md │ │ │ │ │ │ │ ├── allow-ref-access-in-effect.js │ │ │ │ │ │ │ ├── allow-ref-access-in-unused-callback-nested.expect.md │ │ │ │ │ │ │ ├── allow-ref-access-in-unused-callback-nested.js │ │ │ │ │ │ │ ├── allow-ref-initialization-undefined.expect.md │ │ │ │ │ │ │ ├── allow-ref-initialization-undefined.js │ │ │ │ │ │ │ ├── allow-ref-initialization.expect.md │ │ │ │ │ │ │ ├── allow-ref-initialization.js │ │ │ │ │ │ │ ├── allow-ref-lazy-initialization-with-logical.expect.md │ │ │ │ │ │ │ ├── allow-ref-lazy-initialization-with-logical.js │ │ │ │ │ │ │ ├── allow-ref-type-cast-in-render.expect.md │ │ │ │ │ │ │ ├── allow-ref-type-cast-in-render.js │ │ │ │ │ │ │ ├── array-access-assignment.expect.md │ │ │ │ │ │ │ ├── array-access-assignment.js │ │ │ │ │ │ │ ├── array-at-closure.expect.md │ │ │ │ │ │ │ ├── array-at-closure.js │ │ │ │ │ │ │ ├── array-at-effect.expect.md │ │ │ │ │ │ │ ├── array-at-effect.js │ │ │ │ │ │ │ ├── array-at-mutate-after-capture.expect.md │ │ │ │ │ │ │ ├── array-at-mutate-after-capture.js │ │ │ │ │ │ │ ├── array-concat-should-capture.expect.md │ │ │ │ │ │ │ ├── array-concat-should-capture.ts │ │ │ │ │ │ │ ├── array-expression-spread.expect.md │ │ │ │ │ │ │ ├── array-expression-spread.js │ │ │ │ │ │ │ ├── array-from-arg1-captures-arg0.expect.md │ │ │ │ │ │ │ ├── array-from-arg1-captures-arg0.js │ │ │ │ │ │ │ ├── array-from-captures-arg0.expect.md │ │ │ │ │ │ │ ├── array-from-captures-arg0.js │ │ │ │ │ │ │ ├── array-from-maybemutates-arg0.expect.md │ │ │ │ │ │ │ ├── array-from-maybemutates-arg0.js │ │ │ │ │ │ │ ├── array-join.expect.md │ │ │ │ │ │ │ ├── array-join.js │ │ │ │ │ │ │ ├── array-map-captures-receiver-noAlias.expect.md │ │ │ │ │ │ │ ├── array-map-captures-receiver-noAlias.js │ │ │ │ │ │ │ ├── array-map-frozen-array-noAlias.expect.md │ │ │ │ │ │ │ ├── array-map-frozen-array-noAlias.js │ │ │ │ │ │ │ ├── array-map-frozen-array.expect.md │ │ │ │ │ │ │ ├── array-map-frozen-array.js │ │ │ │ │ │ │ ├── array-map-mutable-array-mutating-lambda-noAlias.expect.md │ │ │ │ │ │ │ ├── array-map-mutable-array-mutating-lambda-noAlias.js │ │ │ │ │ │ │ ├── array-map-mutable-array-mutating-lambda.expect.md │ │ │ │ │ │ │ ├── array-map-mutable-array-mutating-lambda.js │ │ │ │ │ │ │ ├── array-map-mutable-array-non-mutating-lambda-mutated-result.expect.md │ │ │ │ │ │ │ ├── array-map-mutable-array-non-mutating-lambda-mutated-result.js │ │ │ │ │ │ │ ├── array-map-noAlias-escaping-function.expect.md │ │ │ │ │ │ │ ├── array-map-noAlias-escaping-function.js │ │ │ │ │ │ │ ├── array-pattern-params.expect.md │ │ │ │ │ │ │ ├── array-pattern-params.js │ │ │ │ │ │ │ ├── array-pattern-spread-creates-array.expect.md │ │ │ │ │ │ │ ├── array-pattern-spread-creates-array.js │ │ │ │ │ │ │ ├── array-properties.expect.md │ │ │ │ │ │ │ ├── array-properties.js │ │ │ │ │ │ │ ├── array-property-call.expect.md │ │ │ │ │ │ │ ├── array-property-call.js │ │ │ │ │ │ │ ├── array-push-effect.expect.md │ │ │ │ │ │ │ ├── array-push-effect.js │ │ │ │ │ │ │ ├── array-spread-later-mutated.expect.md │ │ │ │ │ │ │ ├── array-spread-later-mutated.js │ │ │ │ │ │ │ ├── array-spread-mutable-iterator.expect.md │ │ │ │ │ │ │ ├── array-spread-mutable-iterator.js │ │ │ │ │ │ │ ├── arrow-expr-directive.expect.md │ │ │ │ │ │ │ ├── arrow-expr-directive.js │ │ │ │ │ │ │ ├── arrow-function-one-line-directive.expect.md │ │ │ │ │ │ │ ├── arrow-function-one-line-directive.js │ │ │ │ │ │ │ ├── arrow-function-with-implicit-return.expect.md │ │ │ │ │ │ │ ├── arrow-function-with-implicit-return.js │ │ │ │ │ │ │ ├── assignment-expression-computed.expect.md │ │ │ │ │ │ │ ├── assignment-expression-computed.js │ │ │ │ │ │ │ ├── assignment-expression-nested-path.expect.md │ │ │ │ │ │ │ ├── assignment-expression-nested-path.js │ │ │ │ │ │ │ ├── assignment-in-nested-if.expect.md │ │ │ │ │ │ │ ├── assignment-in-nested-if.js │ │ │ │ │ │ │ ├── assignment-variations-complex-lvalue-array.expect.md │ │ │ │ │ │ │ ├── assignment-variations-complex-lvalue-array.js │ │ │ │ │ │ │ ├── assignment-variations-complex-lvalue.expect.md │ │ │ │ │ │ │ ├── assignment-variations-complex-lvalue.js │ │ │ │ │ │ │ ├── assignment-variations.expect.md │ │ │ │ │ │ │ ├── assignment-variations.js │ │ │ │ │ │ │ ├── await-side-effecting-promise.expect.md │ │ │ │ │ │ │ ├── await-side-effecting-promise.js │ │ │ │ │ │ │ ├── await.expect.md │ │ │ │ │ │ │ ├── await.js │ │ │ │ │ │ │ ├── babel-existing-react-import.expect.md │ │ │ │ │ │ │ ├── babel-existing-react-import.js │ │ │ │ │ │ │ ├── babel-existing-react-kitchensink-import.expect.md │ │ │ │ │ │ │ ├── babel-existing-react-kitchensink-import.js │ │ │ │ │ │ │ ├── babel-existing-react-namespace-import.expect.md │ │ │ │ │ │ │ ├── babel-existing-react-namespace-import.js │ │ │ │ │ │ │ ├── babel-existing-react-runtime-import.expect.md │ │ │ │ │ │ │ ├── babel-existing-react-runtime-import.js │ │ │ │ │ │ │ ├── babel-repro-compact-negative-number.expect.md │ │ │ │ │ │ │ ├── babel-repro-compact-negative-number.js │ │ │ │ │ │ │ ├── block-scoping-switch-dead-code.expect.md │ │ │ │ │ │ │ ├── block-scoping-switch-dead-code.js │ │ │ │ │ │ │ ├── block-scoping-switch-variable-scoping.expect.md │ │ │ │ │ │ │ ├── block-scoping-switch-variable-scoping.js │ │ │ │ │ │ │ ├── bug-capturing-func-maybealias-captured-mutate.expect.md │ │ │ │ │ │ │ ├── bug-capturing-func-maybealias-captured-mutate.ts │ │ │ │ │ │ │ ├── bug-ref-prefix-postfix-operator.expect.md │ │ │ │ │ │ │ ├── bug-ref-prefix-postfix-operator.js │ │ │ │ │ │ │ ├── bug-separate-memoization-due-to-callback-capturing.expect.md │ │ │ │ │ │ │ ├── bug-separate-memoization-due-to-callback-capturing.js │ │ │ │ │ │ │ ├── bug-type-inference-control-flow.expect.md │ │ │ │ │ │ │ ├── bug-type-inference-control-flow.ts │ │ │ │ │ │ │ ├── builtin-jsx-tag-lowered-between-mutations.expect.md │ │ │ │ │ │ │ ├── builtin-jsx-tag-lowered-between-mutations.js │ │ │ │ │ │ │ ├── call-args-assignment.expect.md │ │ │ │ │ │ │ ├── call-args-assignment.js │ │ │ │ │ │ │ ├── call-args-destructuring-assignment.expect.md │ │ │ │ │ │ │ ├── call-args-destructuring-assignment.js │ │ │ │ │ │ │ ├── call-spread-argument-mutable-iterator.expect.md │ │ │ │ │ │ │ ├── call-spread-argument-mutable-iterator.js │ │ │ │ │ │ │ ├── call-spread.expect.md │ │ │ │ │ │ │ ├── call-spread.js │ │ │ │ │ │ │ ├── call-with-independently-memoizable-arg.expect.md │ │ │ │ │ │ │ ├── call-with-independently-memoizable-arg.js │ │ │ │ │ │ │ ├── call.expect.md │ │ │ │ │ │ │ ├── call.js │ │ │ │ │ │ │ ├── capture-indirect-mutate-alias-iife.expect.md │ │ │ │ │ │ │ ├── capture-indirect-mutate-alias-iife.js │ │ │ │ │ │ │ ├── capture-indirect-mutate-alias.expect.md │ │ │ │ │ │ │ ├── capture-indirect-mutate-alias.js │ │ │ │ │ │ │ ├── capture-param-mutate.expect.md │ │ │ │ │ │ │ ├── capture-param-mutate.js │ │ │ │ │ │ │ ├── capture-ref-for-later-mutation.expect.md │ │ │ │ │ │ │ ├── capture-ref-for-later-mutation.tsx │ │ │ │ │ │ │ ├── capture_mutate-across-fns-iife.expect.md │ │ │ │ │ │ │ ├── capture_mutate-across-fns-iife.js │ │ │ │ │ │ │ ├── capture_mutate-across-fns.expect.md │ │ │ │ │ │ │ ├── capture_mutate-across-fns.js │ │ │ │ │ │ │ ├── capturing-arrow-function-1.expect.md │ │ │ │ │ │ │ ├── capturing-arrow-function-1.js │ │ │ │ │ │ │ ├── capturing-fun-alias-captured-mutate-2-iife.expect.md │ │ │ │ │ │ │ ├── capturing-fun-alias-captured-mutate-2-iife.js │ │ │ │ │ │ │ ├── capturing-fun-alias-captured-mutate-2.expect.md │ │ │ │ │ │ │ ├── capturing-fun-alias-captured-mutate-2.js │ │ │ │ │ │ │ ├── capturing-fun-alias-captured-mutate-arr-2-iife.expect.md │ │ │ │ │ │ │ ├── capturing-fun-alias-captured-mutate-arr-2-iife.js │ │ │ │ │ │ │ ├── capturing-fun-alias-captured-mutate-arr-2.expect.md │ │ │ │ │ │ │ ├── capturing-fun-alias-captured-mutate-arr-2.js │ │ │ │ │ │ │ ├── capturing-func-alias-captured-mutate-arr-iife.expect.md │ │ │ │ │ │ │ ├── capturing-func-alias-captured-mutate-arr-iife.js │ │ │ │ │ │ │ ├── capturing-func-alias-captured-mutate-arr.expect.md │ │ │ │ │ │ │ ├── capturing-func-alias-captured-mutate-arr.js │ │ │ │ │ │ │ ├── capturing-func-alias-captured-mutate-iife.expect.md │ │ │ │ │ │ │ ├── capturing-func-alias-captured-mutate-iife.js │ │ │ │ │ │ │ ├── capturing-func-alias-captured-mutate.expect.md │ │ │ │ │ │ │ ├── capturing-func-alias-captured-mutate.js │ │ │ │ │ │ │ ├── capturing-func-alias-computed-mutate-iife.expect.md │ │ │ │ │ │ │ ├── capturing-func-alias-computed-mutate-iife.js │ │ │ │ │ │ │ ├── capturing-func-alias-computed-mutate.expect.md │ │ │ │ │ │ │ ├── capturing-func-alias-computed-mutate.js │ │ │ │ │ │ │ ├── capturing-func-alias-mutate-iife.expect.md │ │ │ │ │ │ │ ├── capturing-func-alias-mutate-iife.js │ │ │ │ │ │ │ ├── capturing-func-alias-mutate.expect.md │ │ │ │ │ │ │ ├── capturing-func-alias-mutate.js │ │ │ │ │ │ │ ├── capturing-func-alias-receiver-computed-mutate-iife.expect.md │ │ │ │ │ │ │ ├── capturing-func-alias-receiver-computed-mutate-iife.js │ │ │ │ │ │ │ ├── capturing-func-alias-receiver-computed-mutate.expect.md │ │ │ │ │ │ │ ├── capturing-func-alias-receiver-computed-mutate.js │ │ │ │ │ │ │ ├── capturing-func-alias-receiver-mutate-iife.expect.md │ │ │ │ │ │ │ ├── capturing-func-alias-receiver-mutate-iife.js │ │ │ │ │ │ │ ├── capturing-func-alias-receiver-mutate.expect.md │ │ │ │ │ │ │ ├── capturing-func-alias-receiver-mutate.js │ │ │ │ │ │ │ ├── capturing-func-mutate-2.expect.md │ │ │ │ │ │ │ ├── capturing-func-mutate-2.js │ │ │ │ │ │ │ ├── capturing-func-mutate-3.expect.md │ │ │ │ │ │ │ ├── capturing-func-mutate-3.js │ │ │ │ │ │ │ ├── capturing-func-mutate-nested.expect.md │ │ │ │ │ │ │ ├── capturing-func-mutate-nested.js │ │ │ │ │ │ │ ├── capturing-func-mutate.expect.md │ │ │ │ │ │ │ ├── capturing-func-mutate.js │ │ │ │ │ │ │ ├── capturing-func-no-mutate.expect.md │ │ │ │ │ │ │ ├── capturing-func-no-mutate.js │ │ │ │ │ │ │ ├── capturing-func-simple-alias-iife.expect.md │ │ │ │ │ │ │ ├── capturing-func-simple-alias-iife.js │ │ │ │ │ │ │ ├── capturing-func-simple-alias.expect.md │ │ │ │ │ │ │ ├── capturing-func-simple-alias.js │ │ │ │ │ │ │ ├── capturing-function-1.expect.md │ │ │ │ │ │ │ ├── capturing-function-1.js │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-2-iife.expect.md │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-2-iife.js │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-2.expect.md │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-2.js │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-3-iife.expect.md │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-3-iife.js │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-3.expect.md │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-3.js │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-4-iife.expect.md │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-4-iife.js │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-4.expect.md │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-4.js │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-iife.expect.md │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-iife.js │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load.expect.md │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load.js │ │ │ │ │ │ │ ├── capturing-function-capture-ref-before-rename.expect.md │ │ │ │ │ │ │ ├── capturing-function-capture-ref-before-rename.js │ │ │ │ │ │ │ ├── capturing-function-conditional-capture-mutate.expect.md │ │ │ │ │ │ │ ├── capturing-function-conditional-capture-mutate.js │ │ │ │ │ │ │ ├── capturing-function-decl.expect.md │ │ │ │ │ │ │ ├── capturing-function-decl.js │ │ │ │ │ │ │ ├── capturing-function-member-expr-arguments.expect.md │ │ │ │ │ │ │ ├── capturing-function-member-expr-arguments.js │ │ │ │ │ │ │ ├── capturing-function-member-expr-call.expect.md │ │ │ │ │ │ │ ├── capturing-function-member-expr-call.js │ │ │ │ │ │ │ ├── capturing-function-renamed-ref.expect.md │ │ │ │ │ │ │ ├── capturing-function-renamed-ref.js │ │ │ │ │ │ │ ├── capturing-function-runs-inference.expect.md │ │ │ │ │ │ │ ├── capturing-function-runs-inference.js │ │ │ │ │ │ │ ├── capturing-function-shadow-captured.expect.md │ │ │ │ │ │ │ ├── capturing-function-shadow-captured.js │ │ │ │ │ │ │ ├── capturing-function-skip-computed-path.expect.md │ │ │ │ │ │ │ ├── capturing-function-skip-computed-path.js │ │ │ │ │ │ │ ├── capturing-function-within-block.expect.md │ │ │ │ │ │ │ ├── capturing-function-within-block.js │ │ │ │ │ │ │ ├── capturing-member-expr.expect.md │ │ │ │ │ │ │ ├── capturing-member-expr.js │ │ │ │ │ │ │ ├── capturing-nested-member-call.expect.md │ │ │ │ │ │ │ ├── capturing-nested-member-call.js │ │ │ │ │ │ │ ├── capturing-nested-member-expr-in-nested-func.expect.md │ │ │ │ │ │ │ ├── capturing-nested-member-expr-in-nested-func.js │ │ │ │ │ │ │ ├── capturing-nested-member-expr.expect.md │ │ │ │ │ │ │ ├── capturing-nested-member-expr.js │ │ │ │ │ │ │ ├── capturing-reference-changes-type.expect.md │ │ │ │ │ │ │ ├── capturing-reference-changes-type.js │ │ │ │ │ │ │ ├── capturing-variable-in-nested-block.expect.md │ │ │ │ │ │ │ ├── capturing-variable-in-nested-block.js │ │ │ │ │ │ │ ├── capturing-variable-in-nested-function.expect.md │ │ │ │ │ │ │ ├── capturing-variable-in-nested-function.js │ │ │ │ │ │ │ ├── chained-assignment-context-variable.expect.md │ │ │ │ │ │ │ ├── chained-assignment-context-variable.js │ │ │ │ │ │ │ ├── chained-assignment-expressions.expect.md │ │ │ │ │ │ │ ├── chained-assignment-expressions.js │ │ │ │ │ │ │ ├── class-component-with-render-helper.expect.md │ │ │ │ │ │ │ ├── class-component-with-render-helper.js │ │ │ │ │ │ │ ├── codegen-inline-iife-reassign.expect.md │ │ │ │ │ │ │ ├── codegen-inline-iife-reassign.ts │ │ │ │ │ │ │ ├── codegen-inline-iife-storeprop.expect.md │ │ │ │ │ │ │ ├── codegen-inline-iife-storeprop.ts │ │ │ │ │ │ │ ├── codegen-inline-iife.expect.md │ │ │ │ │ │ │ ├── codegen-inline-iife.ts │ │ │ │ │ │ │ ├── codegen-instrument-forget-test.expect.md │ │ │ │ │ │ │ ├── codegen-instrument-forget-test.js │ │ │ │ │ │ │ ├── complex-while.expect.md │ │ │ │ │ │ │ ├── complex-while.js │ │ │ │ │ │ │ ├── component-declaration-basic.flow.expect.md │ │ │ │ │ │ │ ├── component-declaration-basic.flow.js │ │ │ │ │ │ │ ├── component-inner-function-with-many-args.expect.md │ │ │ │ │ │ │ ├── component-inner-function-with-many-args.tsx │ │ │ │ │ │ │ ├── component.expect.md │ │ │ │ │ │ │ ├── component.js │ │ │ │ │ │ │ ├── computed-call-evaluation-order.expect.md │ │ │ │ │ │ │ ├── computed-call-evaluation-order.js │ │ │ │ │ │ │ ├── computed-call-spread.expect.md │ │ │ │ │ │ │ ├── computed-call-spread.js │ │ │ │ │ │ │ ├── computed-load-primitive-as-dependency.expect.md │ │ │ │ │ │ │ ├── computed-load-primitive-as-dependency.js │ │ │ │ │ │ │ ├── computed-store-alias.expect.md │ │ │ │ │ │ │ ├── computed-store-alias.js │ │ │ │ │ │ │ ├── concise-arrow-expr.expect.md │ │ │ │ │ │ │ ├── concise-arrow-expr.js │ │ │ │ │ │ │ ├── conditional-break-labeled.expect.md │ │ │ │ │ │ │ ├── conditional-break-labeled.js │ │ │ │ │ │ │ ├── conditional-early-return.expect.md │ │ │ │ │ │ │ ├── conditional-early-return.js │ │ │ │ │ │ │ ├── conditional-on-mutable.expect.md │ │ │ │ │ │ │ ├── conditional-on-mutable.js │ │ │ │ │ │ │ ├── conditional-set-state-in-render.expect.md │ │ │ │ │ │ │ ├── conditional-set-state-in-render.js │ │ │ │ │ │ │ ├── conflict-codegen-instrument-forget.expect.md │ │ │ │ │ │ │ ├── conflict-codegen-instrument-forget.js │ │ │ │ │ │ │ ├── conflicting-dollar-sign-variable.expect.md │ │ │ │ │ │ │ ├── conflicting-dollar-sign-variable.js │ │ │ │ │ │ │ ├── consecutive-use-memo.expect.md │ │ │ │ │ │ │ ├── consecutive-use-memo.ts │ │ │ │ │ │ │ ├── console-readonly.expect.md │ │ │ │ │ │ │ ├── console-readonly.js │ │ │ │ │ │ │ ├── const-propagation-into-function-expression-global.expect.md │ │ │ │ │ │ │ ├── const-propagation-into-function-expression-global.js │ │ │ │ │ │ │ ├── const-propagation-into-function-expression-primitive.expect.md │ │ │ │ │ │ │ ├── const-propagation-into-function-expression-primitive.js │ │ │ │ │ │ │ ├── const-propagation-phi-nodes.expect.md │ │ │ │ │ │ │ ├── const-propagation-phi-nodes.ts │ │ │ │ │ │ │ ├── constant-computed.expect.md │ │ │ │ │ │ │ ├── constant-computed.js │ │ │ │ │ │ │ ├── constant-prop-across-objectmethod-def.expect.md │ │ │ │ │ │ │ ├── constant-prop-across-objectmethod-def.js │ │ │ │ │ │ │ ├── constant-prop-colliding-identifier.expect.md │ │ │ │ │ │ │ ├── constant-prop-colliding-identifier.js │ │ │ │ │ │ │ ├── constant-prop-to-object-method.expect.md │ │ │ │ │ │ │ ├── constant-prop-to-object-method.js │ │ │ │ │ │ │ ├── constant-propagate-global-phis-constant.expect.md │ │ │ │ │ │ │ ├── constant-propagate-global-phis-constant.js │ │ │ │ │ │ │ ├── constant-propagate-global-phis.expect.md │ │ │ │ │ │ │ ├── constant-propagate-global-phis.js │ │ │ │ │ │ │ ├── constant-propagation-bit-ops.expect.md │ │ │ │ │ │ │ ├── constant-propagation-bit-ops.js │ │ │ │ │ │ │ ├── constant-propagation-for.expect.md │ │ │ │ │ │ │ ├── constant-propagation-for.js │ │ │ │ │ │ │ ├── constant-propagation-into-function-expressions.expect.md │ │ │ │ │ │ │ ├── constant-propagation-into-function-expressions.js │ │ │ │ │ │ │ ├── constant-propagation-phi.expect.md │ │ │ │ │ │ │ ├── constant-propagation-phi.js │ │ │ │ │ │ │ ├── constant-propagation-string-concat.expect.md │ │ │ │ │ │ │ ├── constant-propagation-string-concat.js │ │ │ │ │ │ │ ├── constant-propagation-template-literal.expect.md │ │ │ │ │ │ │ ├── constant-propagation-template-literal.js │ │ │ │ │ │ │ ├── constant-propagation-unary-number.expect.md │ │ │ │ │ │ │ ├── constant-propagation-unary-number.js │ │ │ │ │ │ │ ├── constant-propagation-unary.expect.md │ │ │ │ │ │ │ ├── constant-propagation-unary.js │ │ │ │ │ │ │ ├── constant-propagation-while.expect.md │ │ │ │ │ │ │ ├── constant-propagation-while.js │ │ │ │ │ │ │ ├── constant-propagation.expect.md │ │ │ │ │ │ │ ├── constant-propagation.js │ │ │ │ │ │ │ ├── constructor.expect.md │ │ │ │ │ │ │ ├── constructor.js │ │ │ │ │ │ │ ├── context-variable-as-jsx-element-tag.expect.md │ │ │ │ │ │ │ ├── context-variable-as-jsx-element-tag.js │ │ │ │ │ │ │ ├── context-variable-reactive-explicit-control-flow.expect.md │ │ │ │ │ │ │ ├── context-variable-reactive-explicit-control-flow.js │ │ │ │ │ │ │ ├── context-variable-reactive-implicit-control-flow.expect.md │ │ │ │ │ │ │ ├── context-variable-reactive-implicit-control-flow.js │ │ │ │ │ │ │ ├── context-variable-reassigned-objectmethod.expect.md │ │ │ │ │ │ │ ├── context-variable-reassigned-objectmethod.js │ │ │ │ │ │ │ ├── context-variable-reassigned-outside-of-lambda.expect.md │ │ │ │ │ │ │ ├── context-variable-reassigned-outside-of-lambda.js │ │ │ │ │ │ │ ├── context-variable-reassigned-reactive-capture.expect.md │ │ │ │ │ │ │ ├── context-variable-reassigned-reactive-capture.js │ │ │ │ │ │ │ ├── context-variable-reassigned-two-lambdas.expect.md │ │ │ │ │ │ │ ├── context-variable-reassigned-two-lambdas.js │ │ │ │ │ │ │ ├── controlled-input.expect.md │ │ │ │ │ │ │ ├── controlled-input.js │ │ │ │ │ │ │ ├── createElement-freeze.expect.md │ │ │ │ │ │ │ ├── createElement-freeze.js │ │ │ │ │ │ │ ├── custom-opt-out-directive.expect.md │ │ │ │ │ │ │ ├── custom-opt-out-directive.tsx │ │ │ │ │ │ │ ├── dce-loop.expect.md │ │ │ │ │ │ │ ├── dce-loop.js │ │ │ │ │ │ │ ├── dce-unused-const.expect.md │ │ │ │ │ │ │ ├── dce-unused-const.js │ │ │ │ │ │ │ ├── dce-unused-postfix-update.expect.md │ │ │ │ │ │ │ ├── dce-unused-postfix-update.js │ │ │ │ │ │ │ ├── dce-unused-prefix-update.expect.md │ │ │ │ │ │ │ ├── dce-unused-prefix-update.js │ │ │ │ │ │ │ ├── debugger-memoized.expect.md │ │ │ │ │ │ │ ├── debugger-memoized.js │ │ │ │ │ │ │ ├── debugger.expect.md │ │ │ │ │ │ │ ├── debugger.js │ │ │ │ │ │ │ ├── declare-reassign-variable-in-closure.expect.md │ │ │ │ │ │ │ ├── declare-reassign-variable-in-closure.js │ │ │ │ │ │ │ ├── deeply-nested-function-expressions-with-params.expect.md │ │ │ │ │ │ │ ├── deeply-nested-function-expressions-with-params.js │ │ │ │ │ │ │ ├── default-param-array-with-unary.expect.md │ │ │ │ │ │ │ ├── default-param-array-with-unary.js │ │ │ │ │ │ │ ├── default-param-calls-global-function.expect.md │ │ │ │ │ │ │ ├── default-param-calls-global-function.js │ │ │ │ │ │ │ ├── default-param-with-empty-callback.expect.md │ │ │ │ │ │ │ ├── default-param-with-empty-callback.js │ │ │ │ │ │ │ ├── default-param-with-reorderable-callback.expect.md │ │ │ │ │ │ │ ├── default-param-with-reorderable-callback.js │ │ │ │ │ │ │ ├── delete-computed-property.expect.md │ │ │ │ │ │ │ ├── delete-computed-property.js │ │ │ │ │ │ │ ├── delete-property.expect.md │ │ │ │ │ │ │ ├── delete-property.js │ │ │ │ │ │ │ ├── dependencies-outputs.expect.md │ │ │ │ │ │ │ ├── dependencies-outputs.js │ │ │ │ │ │ │ ├── dependencies.expect.md │ │ │ │ │ │ │ ├── dependencies.js │ │ │ │ │ │ │ ├── destructure-array-assignment-to-context-var.expect.md │ │ │ │ │ │ │ ├── destructure-array-assignment-to-context-var.js │ │ │ │ │ │ │ ├── destructure-array-declaration-to-context-var.expect.md │ │ │ │ │ │ │ ├── destructure-array-declaration-to-context-var.js │ │ │ │ │ │ │ ├── destructure-capture-global.expect.md │ │ │ │ │ │ │ ├── destructure-capture-global.js │ │ │ │ │ │ │ ├── destructure-default-array-with-unary.expect.md │ │ │ │ │ │ │ ├── destructure-default-array-with-unary.js │ │ │ │ │ │ │ ├── destructure-direct-reassignment.expect.md │ │ │ │ │ │ │ ├── destructure-direct-reassignment.js │ │ │ │ │ │ │ ├── destructure-in-branch-ssa.expect.md │ │ │ │ │ │ │ ├── destructure-in-branch-ssa.ts │ │ │ │ │ │ │ ├── destructure-mixed-property-key-types.expect.md │ │ │ │ │ │ │ ├── destructure-mixed-property-key-types.js │ │ │ │ │ │ │ ├── destructure-object-assignment-to-context-var.expect.md │ │ │ │ │ │ │ ├── destructure-object-assignment-to-context-var.js │ │ │ │ │ │ │ ├── destructure-object-declaration-to-context-var.expect.md │ │ │ │ │ │ │ ├── destructure-object-declaration-to-context-var.js │ │ │ │ │ │ │ ├── destructure-param-string-literal-key-invalid-identifier.expect.md │ │ │ │ │ │ │ ├── destructure-param-string-literal-key-invalid-identifier.js │ │ │ │ │ │ │ ├── destructure-param-string-literal-key.expect.md │ │ │ │ │ │ │ ├── destructure-param-string-literal-key.js │ │ │ │ │ │ │ ├── destructure-string-literal-invalid-identifier-property-key.expect.md │ │ │ │ │ │ │ ├── destructure-string-literal-invalid-identifier-property-key.js │ │ │ │ │ │ │ ├── destructure-string-literal-property-key.expect.md │ │ │ │ │ │ │ ├── destructure-string-literal-property-key.js │ │ │ │ │ │ │ ├── destructuring-array-default.expect.md │ │ │ │ │ │ │ ├── destructuring-array-default.js │ │ │ │ │ │ │ ├── destructuring-array-param-default.expect.md │ │ │ │ │ │ │ ├── destructuring-array-param-default.js │ │ │ │ │ │ │ ├── destructuring-assignment-array-default.expect.md │ │ │ │ │ │ │ ├── destructuring-assignment-array-default.js │ │ │ │ │ │ │ ├── destructuring-assignment.expect.md │ │ │ │ │ │ │ ├── destructuring-assignment.js │ │ │ │ │ │ │ ├── destructuring-default-at-array-hole.expect.md │ │ │ │ │ │ │ ├── destructuring-default-at-array-hole.js │ │ │ │ │ │ │ ├── destructuring-default-at-explicit-null.expect.md │ │ │ │ │ │ │ ├── destructuring-default-at-explicit-null.js │ │ │ │ │ │ │ ├── destructuring-default-at-explicit-undefined.expect.md │ │ │ │ │ │ │ ├── destructuring-default-at-explicit-undefined.js │ │ │ │ │ │ │ ├── destructuring-default-past-end-of-array.expect.md │ │ │ │ │ │ │ ├── destructuring-default-past-end-of-array.js │ │ │ │ │ │ │ ├── destructuring-mixed-scope-and-local-variables-with-default.expect.md │ │ │ │ │ │ │ ├── destructuring-mixed-scope-and-local-variables-with-default.js │ │ │ │ │ │ │ ├── destructuring-mixed-scope-declarations-and-locals.expect.md │ │ │ │ │ │ │ ├── destructuring-mixed-scope-declarations-and-locals.js │ │ │ │ │ │ │ ├── destructuring-object-default.expect.md │ │ │ │ │ │ │ ├── destructuring-object-default.js │ │ │ │ │ │ │ ├── destructuring-object-param-default.expect.md │ │ │ │ │ │ │ ├── destructuring-object-param-default.js │ │ │ │ │ │ │ ├── destructuring-object-pattern-within-rest.expect.md │ │ │ │ │ │ │ ├── destructuring-object-pattern-within-rest.js │ │ │ │ │ │ │ ├── destructuring-property-inference.expect.md │ │ │ │ │ │ │ ├── destructuring-property-inference.js │ │ │ │ │ │ │ ├── destructuring-same-property-identifier-names.expect.md │ │ │ │ │ │ │ ├── destructuring-same-property-identifier-names.js │ │ │ │ │ │ │ ├── destructuring-with-conditional-as-default-value.expect.md │ │ │ │ │ │ │ ├── destructuring-with-conditional-as-default-value.js │ │ │ │ │ │ │ ├── destructuring-with-typecast-as-default-value.flow.expect.md │ │ │ │ │ │ │ ├── destructuring-with-typecast-as-default-value.flow.js │ │ │ │ │ │ │ ├── destructuring.expect.md │ │ │ │ │ │ │ ├── destructuring.js │ │ │ │ │ │ │ ├── do-while-break.expect.md │ │ │ │ │ │ │ ├── do-while-break.js │ │ │ │ │ │ │ ├── do-while-compound-test.expect.md │ │ │ │ │ │ │ ├── do-while-compound-test.js │ │ │ │ │ │ │ ├── do-while-conditional-break.expect.md │ │ │ │ │ │ │ ├── do-while-conditional-break.js │ │ │ │ │ │ │ ├── do-while-continue.expect.md │ │ │ │ │ │ │ ├── do-while-continue.js │ │ │ │ │ │ │ ├── do-while-early-unconditional-break.expect.md │ │ │ │ │ │ │ ├── do-while-early-unconditional-break.js │ │ │ │ │ │ │ ├── do-while-simple.expect.md │ │ │ │ │ │ │ ├── do-while-simple.js │ │ │ │ │ │ │ ├── dominator.expect.md │ │ │ │ │ │ │ ├── dominator.js │ │ │ │ │ │ │ ├── dont-memoize-primitive-function-call-non-escaping-useMemo.expect.md │ │ │ │ │ │ │ ├── dont-memoize-primitive-function-call-non-escaping-useMemo.js │ │ │ │ │ │ │ ├── dont-memoize-primitive-function-call-non-escaping.expect.md │ │ │ │ │ │ │ ├── dont-memoize-primitive-function-call-non-escaping.js │ │ │ │ │ │ │ ├── dont-merge-if-dep-is-inner-declaration-of-previous-scope.expect.md │ │ │ │ │ │ │ ├── dont-merge-if-dep-is-inner-declaration-of-previous-scope.js │ │ │ │ │ │ │ ├── dont-merge-overlapping-scopes-store-const-used-later.expect.md │ │ │ │ │ │ │ ├── dont-merge-overlapping-scopes-store-const-used-later.js │ │ │ │ │ │ │ ├── dont-merge-overlapping-scopes-with-intermediate-reassignment.expect.md │ │ │ │ │ │ │ ├── dont-merge-overlapping-scopes-with-intermediate-reassignment.js │ │ │ │ │ │ │ ├── drop-methodcall-usecallback.expect.md │ │ │ │ │ │ │ ├── drop-methodcall-usecallback.js │ │ │ │ │ │ │ ├── drop-methodcall-usememo.expect.md │ │ │ │ │ │ │ ├── drop-methodcall-usememo.js │ │ │ │ │ │ │ ├── early-return-nested-early-return-within-reactive-scope.expect.md │ │ │ │ │ │ │ ├── early-return-nested-early-return-within-reactive-scope.js │ │ │ │ │ │ │ ├── early-return-no-declarations-reassignments-dependencies.expect.md │ │ │ │ │ │ │ ├── early-return-no-declarations-reassignments-dependencies.js │ │ │ │ │ │ │ ├── early-return-within-reactive-scope.expect.md │ │ │ │ │ │ │ ├── early-return-within-reactive-scope.js │ │ │ │ │ │ │ ├── early-return.expect.md │ │ │ │ │ │ │ ├── early-return.js │ │ │ │ │ │ │ ├── ecma/ │ │ │ │ │ │ │ │ ├── error.reserved-words.expect.md │ │ │ │ │ │ │ │ └── error.reserved-words.ts │ │ │ │ │ │ │ ├── effect-derived-computations/ │ │ │ │ │ │ │ │ ├── derived-state-conditionally-in-effect.expect.md │ │ │ │ │ │ │ │ ├── derived-state-conditionally-in-effect.js │ │ │ │ │ │ │ │ ├── derived-state-from-default-props.expect.md │ │ │ │ │ │ │ │ ├── derived-state-from-default-props.js │ │ │ │ │ │ │ │ ├── derived-state-from-local-state-in-effect.expect.md │ │ │ │ │ │ │ │ ├── derived-state-from-local-state-in-effect.js │ │ │ │ │ │ │ │ ├── derived-state-from-prop-local-state-and-component-scope.expect.md │ │ │ │ │ │ │ │ ├── derived-state-from-prop-local-state-and-component-scope.js │ │ │ │ │ │ │ │ ├── derived-state-from-prop-setter-call-outside-effect-no-error.expect.md │ │ │ │ │ │ │ │ ├── derived-state-from-prop-setter-call-outside-effect-no-error.js │ │ │ │ │ │ │ │ ├── derived-state-from-prop-setter-ternary.expect.md │ │ │ │ │ │ │ │ ├── derived-state-from-prop-setter-ternary.js │ │ │ │ │ │ │ │ ├── derived-state-from-prop-setter-used-outside-effect-no-error.expect.md │ │ │ │ │ │ │ │ ├── derived-state-from-prop-setter-used-outside-effect-no-error.js │ │ │ │ │ │ │ │ ├── derived-state-from-prop-with-side-effect.expect.md │ │ │ │ │ │ │ │ ├── derived-state-from-prop-with-side-effect.js │ │ │ │ │ │ │ │ ├── derived-state-from-ref-and-state-no-error.expect.md │ │ │ │ │ │ │ │ ├── derived-state-from-ref-and-state-no-error.js │ │ │ │ │ │ │ │ ├── effect-contains-local-function-call.expect.md │ │ │ │ │ │ │ │ ├── effect-contains-local-function-call.js │ │ │ │ │ │ │ │ ├── effect-contains-prop-function-call-no-error.expect.md │ │ │ │ │ │ │ │ ├── effect-contains-prop-function-call-no-error.js │ │ │ │ │ │ │ │ ├── effect-used-in-dep-array-still-errors.expect.md │ │ │ │ │ │ │ │ ├── effect-used-in-dep-array-still-errors.js │ │ │ │ │ │ │ │ ├── effect-with-cleanup-function-depending-on-derived-computation-value.expect.md │ │ │ │ │ │ │ │ ├── effect-with-cleanup-function-depending-on-derived-computation-value.js │ │ │ │ │ │ │ │ ├── effect-with-global-function-call-no-error.expect.md │ │ │ │ │ │ │ │ ├── effect-with-global-function-call-no-error.js │ │ │ │ │ │ │ │ ├── from-props-setstate-in-effect-no-error.expect.md │ │ │ │ │ │ │ │ ├── from-props-setstate-in-effect-no-error.js │ │ │ │ │ │ │ │ ├── function-expression-mutation-edge-case.expect.md │ │ │ │ │ │ │ │ ├── function-expression-mutation-edge-case.js │ │ │ │ │ │ │ │ ├── invalid-derived-computation-in-effect.expect.md │ │ │ │ │ │ │ │ ├── invalid-derived-computation-in-effect.js │ │ │ │ │ │ │ │ ├── invalid-derived-state-from-computed-props.expect.md │ │ │ │ │ │ │ │ ├── invalid-derived-state-from-computed-props.js │ │ │ │ │ │ │ │ ├── invalid-derived-state-from-destructured-props.expect.md │ │ │ │ │ │ │ │ ├── invalid-derived-state-from-destructured-props.js │ │ │ │ │ │ │ │ ├── ref-conditional-in-effect-no-error.expect.md │ │ │ │ │ │ │ │ ├── ref-conditional-in-effect-no-error.js │ │ │ │ │ │ │ │ ├── usestate-derived-from-prop-no-show-in-data-flow-tree.expect.md │ │ │ │ │ │ │ │ └── usestate-derived-from-prop-no-show-in-data-flow-tree.js │ │ │ │ │ │ │ ├── empty-catch-statement.expect.md │ │ │ │ │ │ │ ├── empty-catch-statement.ts │ │ │ │ │ │ │ ├── empty-eslint-suppressions-config.expect.md │ │ │ │ │ │ │ ├── empty-eslint-suppressions-config.js │ │ │ │ │ │ │ ├── error._todo.computed-lval-in-destructure.expect.md │ │ │ │ │ │ │ ├── error._todo.computed-lval-in-destructure.js │ │ │ │ │ │ │ ├── error.assign-global-in-component-tag-function.expect.md │ │ │ │ │ │ │ ├── error.assign-global-in-component-tag-function.js │ │ │ │ │ │ │ ├── error.assign-global-in-jsx-children.expect.md │ │ │ │ │ │ │ ├── error.assign-global-in-jsx-children.js │ │ │ │ │ │ │ ├── error.assign-ref-in-effect-hint.expect.md │ │ │ │ │ │ │ ├── error.assign-ref-in-effect-hint.js │ │ │ │ │ │ │ ├── error.bailout-on-flow-suppression.expect.md │ │ │ │ │ │ │ ├── error.bailout-on-flow-suppression.js │ │ │ │ │ │ │ ├── error.bailout-on-suppression-of-custom-rule.expect.md │ │ │ │ │ │ │ ├── error.bailout-on-suppression-of-custom-rule.js │ │ │ │ │ │ │ ├── error.bug-infer-mutation-aliasing-effects.expect.md │ │ │ │ │ │ │ ├── error.bug-infer-mutation-aliasing-effects.js │ │ │ │ │ │ │ ├── error.bug-invariant-codegen-methodcall.expect.md │ │ │ │ │ │ │ ├── error.bug-invariant-codegen-methodcall.js │ │ │ │ │ │ │ ├── error.bug-invariant-couldnt-find-binding-for-decl.expect.md │ │ │ │ │ │ │ ├── error.bug-invariant-couldnt-find-binding-for-decl.js │ │ │ │ │ │ │ ├── error.bug-invariant-expected-consistent-destructuring.expect.md │ │ │ │ │ │ │ ├── error.bug-invariant-expected-consistent-destructuring.js │ │ │ │ │ │ │ ├── error.bug-invariant-local-or-context-references.expect.md │ │ │ │ │ │ │ ├── error.bug-invariant-local-or-context-references.js │ │ │ │ │ │ │ ├── error.bug-invariant-unnamed-temporary.expect.md │ │ │ │ │ │ │ ├── error.bug-invariant-unnamed-temporary.js │ │ │ │ │ │ │ ├── error.call-args-destructuring-asignment-complex.expect.md │ │ │ │ │ │ │ ├── error.call-args-destructuring-asignment-complex.js │ │ │ │ │ │ │ ├── error.capitalized-function-call-aliased.expect.md │ │ │ │ │ │ │ ├── error.capitalized-function-call-aliased.js │ │ │ │ │ │ │ ├── error.capitalized-function-call.expect.md │ │ │ │ │ │ │ ├── error.capitalized-function-call.js │ │ │ │ │ │ │ ├── error.capitalized-method-call.expect.md │ │ │ │ │ │ │ ├── error.capitalized-method-call.js │ │ │ │ │ │ │ ├── error.capture-ref-for-mutation.expect.md │ │ │ │ │ │ │ ├── error.capture-ref-for-mutation.tsx │ │ │ │ │ │ │ ├── error.conditional-hook-unknown-hook-react-namespace.expect.md │ │ │ │ │ │ │ ├── error.conditional-hook-unknown-hook-react-namespace.js │ │ │ │ │ │ │ ├── error.conditional-hooks-as-method-call.expect.md │ │ │ │ │ │ │ ├── error.conditional-hooks-as-method-call.js │ │ │ │ │ │ │ ├── error.context-variable-only-chained-assign.expect.md │ │ │ │ │ │ │ ├── error.context-variable-only-chained-assign.js │ │ │ │ │ │ │ ├── error.declare-reassign-variable-in-function-declaration.expect.md │ │ │ │ │ │ │ ├── error.declare-reassign-variable-in-function-declaration.js │ │ │ │ │ │ │ ├── error.default-param-accesses-local.expect.md │ │ │ │ │ │ │ ├── error.default-param-accesses-local.js │ │ │ │ │ │ │ ├── error.dont-hoist-inline-reference.expect.md │ │ │ │ │ │ │ ├── error.dont-hoist-inline-reference.js │ │ │ │ │ │ │ ├── error.fault-tolerance-reports-multiple-errors.expect.md │ │ │ │ │ │ │ ├── error.fault-tolerance-reports-multiple-errors.js │ │ │ │ │ │ │ ├── error.function-expression-references-variable-its-assigned-to.expect.md │ │ │ │ │ │ │ ├── error.function-expression-references-variable-its-assigned-to.js │ │ │ │ │ │ │ ├── error.handle-unexpected-exception-pipeline.expect.md │ │ │ │ │ │ │ ├── error.handle-unexpected-exception-pipeline.ts │ │ │ │ │ │ │ ├── error.hoist-optional-member-expression-with-conditional-optional.expect.md │ │ │ │ │ │ │ ├── error.hoist-optional-member-expression-with-conditional-optional.js │ │ │ │ │ │ │ ├── error.hoist-optional-member-expression-with-conditional.expect.md │ │ │ │ │ │ │ ├── error.hoist-optional-member-expression-with-conditional.js │ │ │ │ │ │ │ ├── error.hoisting-simple-function-declaration.expect.md │ │ │ │ │ │ │ ├── error.hoisting-simple-function-declaration.js │ │ │ │ │ │ │ ├── error.hook-call-freezes-captured-identifier.expect.md │ │ │ │ │ │ │ ├── error.hook-call-freezes-captured-identifier.tsx │ │ │ │ │ │ │ ├── error.hook-call-freezes-captured-memberexpr.expect.md │ │ │ │ │ │ │ ├── error.hook-call-freezes-captured-memberexpr.jsx │ │ │ │ │ │ │ ├── error.hook-property-load-local-hook.expect.md │ │ │ │ │ │ │ ├── error.hook-property-load-local-hook.js │ │ │ │ │ │ │ ├── error.hook-ref-value.expect.md │ │ │ │ │ │ │ ├── error.hook-ref-value.js │ │ │ │ │ │ │ ├── error.invalid-ReactUseMemo-async-callback.expect.md │ │ │ │ │ │ │ ├── error.invalid-ReactUseMemo-async-callback.js │ │ │ │ │ │ │ ├── error.invalid-access-ref-during-render.expect.md │ │ │ │ │ │ │ ├── error.invalid-access-ref-during-render.js │ │ │ │ │ │ │ ├── error.invalid-access-ref-in-reducer-init.expect.md │ │ │ │ │ │ │ ├── error.invalid-access-ref-in-reducer-init.js │ │ │ │ │ │ │ ├── error.invalid-access-ref-in-reducer.expect.md │ │ │ │ │ │ │ ├── error.invalid-access-ref-in-reducer.js │ │ │ │ │ │ │ ├── error.invalid-access-ref-in-render-mutate-object-with-ref-function.expect.md │ │ │ │ │ │ │ ├── error.invalid-access-ref-in-render-mutate-object-with-ref-function.js │ │ │ │ │ │ │ ├── error.invalid-access-ref-in-state-initializer.expect.md │ │ │ │ │ │ │ ├── error.invalid-access-ref-in-state-initializer.js │ │ │ │ │ │ │ ├── error.invalid-aliased-ref-in-callback-invoked-during-render-.expect.md │ │ │ │ │ │ │ ├── error.invalid-aliased-ref-in-callback-invoked-during-render-.js │ │ │ │ │ │ │ ├── error.invalid-array-push-frozen.expect.md │ │ │ │ │ │ │ ├── error.invalid-array-push-frozen.js │ │ │ │ │ │ │ ├── error.invalid-assign-current-inferred-ref-during-render.expect.md │ │ │ │ │ │ │ ├── error.invalid-assign-current-inferred-ref-during-render.js │ │ │ │ │ │ │ ├── error.invalid-assign-hook-to-local.expect.md │ │ │ │ │ │ │ ├── error.invalid-assign-hook-to-local.js │ │ │ │ │ │ │ ├── error.invalid-assing-to-ref-current-in-render.expect.md │ │ │ │ │ │ │ ├── error.invalid-assing-to-ref-current-in-render.js │ │ │ │ │ │ │ ├── error.invalid-computed-store-to-frozen-value.expect.md │ │ │ │ │ │ │ ├── error.invalid-computed-store-to-frozen-value.js │ │ │ │ │ │ │ ├── error.invalid-conditional-call-aliased-hook-import.expect.md │ │ │ │ │ │ │ ├── error.invalid-conditional-call-aliased-hook-import.js │ │ │ │ │ │ │ ├── error.invalid-conditional-call-aliased-react-hook.expect.md │ │ │ │ │ │ │ ├── error.invalid-conditional-call-aliased-react-hook.js │ │ │ │ │ │ │ ├── error.invalid-conditional-call-non-hook-imported-as-hook.expect.md │ │ │ │ │ │ │ ├── error.invalid-conditional-call-non-hook-imported-as-hook.js │ │ │ │ │ │ │ ├── error.invalid-conditional-setState-in-useMemo.expect.md │ │ │ │ │ │ │ ├── error.invalid-conditional-setState-in-useMemo.js │ │ │ │ │ │ │ ├── error.invalid-delete-computed-property-of-frozen-value.expect.md │ │ │ │ │ │ │ ├── error.invalid-delete-computed-property-of-frozen-value.js │ │ │ │ │ │ │ ├── error.invalid-delete-property-of-frozen-value.expect.md │ │ │ │ │ │ │ ├── error.invalid-delete-property-of-frozen-value.js │ │ │ │ │ │ │ ├── error.invalid-derived-computation-in-effect.expect.md │ │ │ │ │ │ │ ├── error.invalid-derived-computation-in-effect.js │ │ │ │ │ │ │ ├── error.invalid-destructure-assignment-to-global.expect.md │ │ │ │ │ │ │ ├── error.invalid-destructure-assignment-to-global.js │ │ │ │ │ │ │ ├── error.invalid-destructure-to-local-global-variables.expect.md │ │ │ │ │ │ │ ├── error.invalid-destructure-to-local-global-variables.js │ │ │ │ │ │ │ ├── error.invalid-disallow-mutating-ref-in-render.expect.md │ │ │ │ │ │ │ ├── error.invalid-disallow-mutating-ref-in-render.js │ │ │ │ │ │ │ ├── error.invalid-disallow-mutating-refs-in-render-transitive.expect.md │ │ │ │ │ │ │ ├── error.invalid-disallow-mutating-refs-in-render-transitive.js │ │ │ │ │ │ │ ├── error.invalid-eval-unsupported.expect.md │ │ │ │ │ │ │ ├── error.invalid-eval-unsupported.js │ │ │ │ │ │ │ ├── error.invalid-function-expression-mutates-immutable-value.expect.md │ │ │ │ │ │ │ ├── error.invalid-function-expression-mutates-immutable-value.js │ │ │ │ │ │ │ ├── error.invalid-global-reassignment-indirect.expect.md │ │ │ │ │ │ │ ├── error.invalid-global-reassignment-indirect.js │ │ │ │ │ │ │ ├── error.invalid-hoisting-setstate.expect.md │ │ │ │ │ │ │ ├── error.invalid-hoisting-setstate.js │ │ │ │ │ │ │ ├── error.invalid-hook-function-argument-mutates-local-variable.expect.md │ │ │ │ │ │ │ ├── error.invalid-hook-function-argument-mutates-local-variable.js │ │ │ │ │ │ │ ├── error.invalid-impure-functions-in-render.expect.md │ │ │ │ │ │ │ ├── error.invalid-impure-functions-in-render.js │ │ │ │ │ │ │ ├── error.invalid-jsx-captures-context-variable.expect.md │ │ │ │ │ │ │ ├── error.invalid-jsx-captures-context-variable.js │ │ │ │ │ │ │ ├── error.invalid-known-incompatible-function.expect.md │ │ │ │ │ │ │ ├── error.invalid-known-incompatible-function.js │ │ │ │ │ │ │ ├── error.invalid-known-incompatible-hook-return-property.expect.md │ │ │ │ │ │ │ ├── error.invalid-known-incompatible-hook-return-property.js │ │ │ │ │ │ │ ├── error.invalid-known-incompatible-hook.expect.md │ │ │ │ │ │ │ ├── error.invalid-known-incompatible-hook.js │ │ │ │ │ │ │ ├── error.invalid-mutate-after-aliased-freeze.expect.md │ │ │ │ │ │ │ ├── error.invalid-mutate-after-aliased-freeze.js │ │ │ │ │ │ │ ├── error.invalid-mutate-after-freeze.expect.md │ │ │ │ │ │ │ ├── error.invalid-mutate-after-freeze.js │ │ │ │ │ │ │ ├── error.invalid-mutate-context-in-callback.expect.md │ │ │ │ │ │ │ ├── error.invalid-mutate-context-in-callback.js │ │ │ │ │ │ │ ├── error.invalid-mutate-context.expect.md │ │ │ │ │ │ │ ├── error.invalid-mutate-context.js │ │ │ │ │ │ │ ├── error.invalid-mutate-global-in-render-helper-phi-return-prop.expect.md │ │ │ │ │ │ │ ├── error.invalid-mutate-global-in-render-helper-phi-return-prop.js │ │ │ │ │ │ │ ├── error.invalid-mutate-global-in-render-helper-prop.expect.md │ │ │ │ │ │ │ ├── error.invalid-mutate-global-in-render-helper-prop.js │ │ │ │ │ │ │ ├── error.invalid-mutate-phi-which-could-be-frozen.expect.md │ │ │ │ │ │ │ ├── error.invalid-mutate-phi-which-could-be-frozen.js │ │ │ │ │ │ │ ├── error.invalid-mutate-props-in-effect-fixpoint.expect.md │ │ │ │ │ │ │ ├── error.invalid-mutate-props-in-effect-fixpoint.js │ │ │ │ │ │ │ ├── error.invalid-mutate-props-via-for-of-iterator.expect.md │ │ │ │ │ │ │ ├── error.invalid-mutate-props-via-for-of-iterator.js │ │ │ │ │ │ │ ├── error.invalid-mutation-in-closure.expect.md │ │ │ │ │ │ │ ├── error.invalid-mutation-in-closure.js │ │ │ │ │ │ │ ├── error.invalid-mutation-of-possible-props-phi-indirect.expect.md │ │ │ │ │ │ │ ├── error.invalid-mutation-of-possible-props-phi-indirect.js │ │ │ │ │ │ │ ├── error.invalid-nested-function-reassign-local-variable-in-effect.expect.md │ │ │ │ │ │ │ ├── error.invalid-nested-function-reassign-local-variable-in-effect.js │ │ │ │ │ │ │ ├── error.invalid-non-imported-reanimated-shared-value-writes.expect.md │ │ │ │ │ │ │ ├── error.invalid-non-imported-reanimated-shared-value-writes.jsx │ │ │ │ │ │ │ ├── error.invalid-optional-member-expression-as-memo-dep-non-optional-in-body.expect.md │ │ │ │ │ │ │ ├── error.invalid-optional-member-expression-as-memo-dep-non-optional-in-body.js │ │ │ │ │ │ │ ├── error.invalid-pass-hook-as-call-arg.expect.md │ │ │ │ │ │ │ ├── error.invalid-pass-hook-as-call-arg.js │ │ │ │ │ │ │ ├── error.invalid-pass-hook-as-prop.expect.md │ │ │ │ │ │ │ ├── error.invalid-pass-hook-as-prop.js │ │ │ │ │ │ │ ├── error.invalid-pass-mutable-function-as-prop.expect.md │ │ │ │ │ │ │ ├── error.invalid-pass-mutable-function-as-prop.js │ │ │ │ │ │ │ ├── error.invalid-pass-ref-to-function.expect.md │ │ │ │ │ │ │ ├── error.invalid-pass-ref-to-function.js │ │ │ │ │ │ │ ├── error.invalid-prop-mutation-indirect.expect.md │ │ │ │ │ │ │ ├── error.invalid-prop-mutation-indirect.js │ │ │ │ │ │ │ ├── error.invalid-property-store-to-frozen-value.expect.md │ │ │ │ │ │ │ ├── error.invalid-property-store-to-frozen-value.js │ │ │ │ │ │ │ ├── error.invalid-props-mutation-in-effect-indirect.expect.md │ │ │ │ │ │ │ ├── error.invalid-props-mutation-in-effect-indirect.js │ │ │ │ │ │ │ ├── error.invalid-read-ref-prop-in-render-destructure.expect.md │ │ │ │ │ │ │ ├── error.invalid-read-ref-prop-in-render-destructure.js │ │ │ │ │ │ │ ├── error.invalid-read-ref-prop-in-render-property-load.expect.md │ │ │ │ │ │ │ ├── error.invalid-read-ref-prop-in-render-property-load.js │ │ │ │ │ │ │ ├── error.invalid-reassign-const.expect.md │ │ │ │ │ │ │ ├── error.invalid-reassign-const.js │ │ │ │ │ │ │ ├── error.invalid-reassign-local-in-hook-return-value.expect.md │ │ │ │ │ │ │ ├── error.invalid-reassign-local-in-hook-return-value.js │ │ │ │ │ │ │ ├── error.invalid-reassign-local-variable-in-async-callback.expect.md │ │ │ │ │ │ │ ├── error.invalid-reassign-local-variable-in-async-callback.js │ │ │ │ │ │ │ ├── error.invalid-reassign-local-variable-in-effect.expect.md │ │ │ │ │ │ │ ├── error.invalid-reassign-local-variable-in-effect.js │ │ │ │ │ │ │ ├── error.invalid-reassign-local-variable-in-hook-argument.expect.md │ │ │ │ │ │ │ ├── error.invalid-reassign-local-variable-in-hook-argument.js │ │ │ │ │ │ │ ├── error.invalid-reassign-local-variable-in-jsx-callback.expect.md │ │ │ │ │ │ │ ├── error.invalid-reassign-local-variable-in-jsx-callback.js │ │ │ │ │ │ │ ├── error.invalid-reassign-variable-in-usememo.expect.md │ │ │ │ │ │ │ ├── error.invalid-reassign-variable-in-usememo.js │ │ │ │ │ │ │ ├── error.invalid-ref-access-render-unary.expect.md │ │ │ │ │ │ │ ├── error.invalid-ref-access-render-unary.js │ │ │ │ │ │ │ ├── error.invalid-ref-in-callback-invoked-during-render.expect.md │ │ │ │ │ │ │ ├── error.invalid-ref-in-callback-invoked-during-render.js │ │ │ │ │ │ │ ├── error.invalid-ref-initialization-unary-not.expect.md │ │ │ │ │ │ │ ├── error.invalid-ref-initialization-unary-not.js │ │ │ │ │ │ │ ├── error.invalid-ref-value-as-props.expect.md │ │ │ │ │ │ │ ├── error.invalid-ref-value-as-props.js │ │ │ │ │ │ │ ├── error.invalid-return-mutable-function-from-hook.expect.md │ │ │ │ │ │ │ ├── error.invalid-return-mutable-function-from-hook.js │ │ │ │ │ │ │ ├── error.invalid-set-and-read-ref-during-render.expect.md │ │ │ │ │ │ │ ├── error.invalid-set-and-read-ref-during-render.js │ │ │ │ │ │ │ ├── error.invalid-set-and-read-ref-nested-property-during-render.expect.md │ │ │ │ │ │ │ ├── error.invalid-set-and-read-ref-nested-property-during-render.js │ │ │ │ │ │ │ ├── error.invalid-setState-in-render-unbound-state.expect.md │ │ │ │ │ │ │ ├── error.invalid-setState-in-render-unbound-state.js │ │ │ │ │ │ │ ├── error.invalid-setState-in-useMemo-indirect-useCallback.expect.md │ │ │ │ │ │ │ ├── error.invalid-setState-in-useMemo-indirect-useCallback.js │ │ │ │ │ │ │ ├── error.invalid-setState-in-useMemo.expect.md │ │ │ │ │ │ │ ├── error.invalid-setState-in-useMemo.js │ │ │ │ │ │ │ ├── error.invalid-setstate-unconditional-with-keyed-state.expect.md │ │ │ │ │ │ │ ├── error.invalid-setstate-unconditional-with-keyed-state.js │ │ │ │ │ │ │ ├── error.invalid-sketchy-code-use-forget.expect.md │ │ │ │ │ │ │ ├── error.invalid-sketchy-code-use-forget.js │ │ │ │ │ │ │ ├── error.invalid-ternary-with-hook-values.expect.md │ │ │ │ │ │ │ ├── error.invalid-ternary-with-hook-values.js │ │ │ │ │ │ │ ├── error.invalid-type-provider-hook-name-not-typed-as-hook-namespace.expect.md │ │ │ │ │ │ │ ├── error.invalid-type-provider-hook-name-not-typed-as-hook-namespace.js │ │ │ │ │ │ │ ├── error.invalid-type-provider-hook-name-not-typed-as-hook.expect.md │ │ │ │ │ │ │ ├── error.invalid-type-provider-hook-name-not-typed-as-hook.js │ │ │ │ │ │ │ ├── error.invalid-type-provider-hooklike-module-default-not-hook.expect.md │ │ │ │ │ │ │ ├── error.invalid-type-provider-hooklike-module-default-not-hook.js │ │ │ │ │ │ │ ├── error.invalid-type-provider-nonhook-name-typed-as-hook.expect.md │ │ │ │ │ │ │ ├── error.invalid-type-provider-nonhook-name-typed-as-hook.js │ │ │ │ │ │ │ ├── error.invalid-uncalled-function-capturing-mutable-values-memoizes-with-captures-values.expect.md │ │ │ │ │ │ │ ├── error.invalid-uncalled-function-capturing-mutable-values-memoizes-with-captures-values.js │ │ │ │ │ │ │ ├── error.invalid-unclosed-eslint-suppression.expect.md │ │ │ │ │ │ │ ├── error.invalid-unclosed-eslint-suppression.js │ │ │ │ │ │ │ ├── error.invalid-unconditional-set-state-hook-return-in-render.expect.md │ │ │ │ │ │ │ ├── error.invalid-unconditional-set-state-hook-return-in-render.js │ │ │ │ │ │ │ ├── error.invalid-unconditional-set-state-in-render.expect.md │ │ │ │ │ │ │ ├── error.invalid-unconditional-set-state-in-render.js │ │ │ │ │ │ │ ├── error.invalid-unconditional-set-state-prop-in-render.expect.md │ │ │ │ │ │ │ ├── error.invalid-unconditional-set-state-prop-in-render.js │ │ │ │ │ │ │ ├── error.invalid-use-ref-added-to-dep-without-type-info.expect.md │ │ │ │ │ │ │ ├── error.invalid-use-ref-added-to-dep-without-type-info.js │ │ │ │ │ │ │ ├── error.invalid-useMemo-async-callback.expect.md │ │ │ │ │ │ │ ├── error.invalid-useMemo-async-callback.js │ │ │ │ │ │ │ ├── error.invalid-useMemo-callback-args.expect.md │ │ │ │ │ │ │ ├── error.invalid-useMemo-callback-args.js │ │ │ │ │ │ │ ├── error.invalid-write-but-dont-read-ref-in-render.expect.md │ │ │ │ │ │ │ ├── error.invalid-write-but-dont-read-ref-in-render.js │ │ │ │ │ │ │ ├── error.invalid-write-ref-prop-in-render.expect.md │ │ │ │ │ │ │ ├── error.invalid-write-ref-prop-in-render.js │ │ │ │ │ │ │ ├── error.modify-state-2.expect.md │ │ │ │ │ │ │ ├── error.modify-state-2.js │ │ │ │ │ │ │ ├── error.modify-state.expect.md │ │ │ │ │ │ │ ├── error.modify-state.js │ │ │ │ │ │ │ ├── error.modify-useReducer-state.expect.md │ │ │ │ │ │ │ ├── error.modify-useReducer-state.js │ │ │ │ │ │ │ ├── error.mutable-range-shared-inner-outer-function.expect.md │ │ │ │ │ │ │ ├── error.mutable-range-shared-inner-outer-function.js │ │ │ │ │ │ │ ├── error.mutate-function-property.expect.md │ │ │ │ │ │ │ ├── error.mutate-function-property.js │ │ │ │ │ │ │ ├── error.mutate-global-increment-op-invalid-react.expect.md │ │ │ │ │ │ │ ├── error.mutate-global-increment-op-invalid-react.js │ │ │ │ │ │ │ ├── error.mutate-hook-argument.expect.md │ │ │ │ │ │ │ ├── error.mutate-hook-argument.js │ │ │ │ │ │ │ ├── error.mutate-property-from-global.expect.md │ │ │ │ │ │ │ ├── error.mutate-property-from-global.js │ │ │ │ │ │ │ ├── error.mutate-props.expect.md │ │ │ │ │ │ │ ├── error.mutate-props.js │ │ │ │ │ │ │ ├── error.not-useEffect-external-mutate.expect.md │ │ │ │ │ │ │ ├── error.not-useEffect-external-mutate.js │ │ │ │ │ │ │ ├── error.propertyload-hook.expect.md │ │ │ │ │ │ │ ├── error.propertyload-hook.js │ │ │ │ │ │ │ ├── error.reassign-global-fn-arg.expect.md │ │ │ │ │ │ │ ├── error.reassign-global-fn-arg.js │ │ │ │ │ │ │ ├── error.reassignment-to-global-indirect.expect.md │ │ │ │ │ │ │ ├── error.reassignment-to-global-indirect.js │ │ │ │ │ │ │ ├── error.reassignment-to-global.expect.md │ │ │ │ │ │ │ ├── error.reassignment-to-global.js │ │ │ │ │ │ │ ├── error.ref-initialization-arbitrary.expect.md │ │ │ │ │ │ │ ├── error.ref-initialization-arbitrary.js │ │ │ │ │ │ │ ├── error.ref-initialization-call-2.expect.md │ │ │ │ │ │ │ ├── error.ref-initialization-call-2.js │ │ │ │ │ │ │ ├── error.ref-initialization-call.expect.md │ │ │ │ │ │ │ ├── error.ref-initialization-call.js │ │ │ │ │ │ │ ├── error.ref-initialization-linear.expect.md │ │ │ │ │ │ │ ├── error.ref-initialization-linear.js │ │ │ │ │ │ │ ├── error.ref-initialization-nonif.expect.md │ │ │ │ │ │ │ ├── error.ref-initialization-nonif.js │ │ │ │ │ │ │ ├── error.ref-initialization-other.expect.md │ │ │ │ │ │ │ ├── error.ref-initialization-other.js │ │ │ │ │ │ │ ├── error.ref-initialization-post-access-2.expect.md │ │ │ │ │ │ │ ├── error.ref-initialization-post-access-2.js │ │ │ │ │ │ │ ├── error.ref-initialization-post-access.expect.md │ │ │ │ │ │ │ ├── error.ref-initialization-post-access.js │ │ │ │ │ │ │ ├── error.ref-like-name-not-Ref.expect.md │ │ │ │ │ │ │ ├── error.ref-like-name-not-Ref.js │ │ │ │ │ │ │ ├── error.ref-like-name-not-a-ref.expect.md │ │ │ │ │ │ │ ├── error.ref-like-name-not-a-ref.js │ │ │ │ │ │ │ ├── error.ref-optional.expect.md │ │ │ │ │ │ │ ├── error.ref-optional.js │ │ │ │ │ │ │ ├── error.repro-preserve-memoization-inner-destructured-value-mistaken-as-dependency-later-mutation.expect.md │ │ │ │ │ │ │ ├── error.repro-preserve-memoization-inner-destructured-value-mistaken-as-dependency-later-mutation.js │ │ │ │ │ │ │ ├── error.repro-preserve-memoization-inner-destructured-value-mistaken-as-dependency-mutated-dep.expect.md │ │ │ │ │ │ │ ├── error.repro-preserve-memoization-inner-destructured-value-mistaken-as-dependency-mutated-dep.js │ │ │ │ │ │ │ ├── error.sketchy-code-rules-of-hooks.expect.md │ │ │ │ │ │ │ ├── error.sketchy-code-rules-of-hooks.js │ │ │ │ │ │ │ ├── error.store-property-in-global.expect.md │ │ │ │ │ │ │ ├── error.store-property-in-global.js │ │ │ │ │ │ │ ├── error.todo-allow-assigning-to-inferred-ref-prop-in-callback.expect.md │ │ │ │ │ │ │ ├── error.todo-allow-assigning-to-inferred-ref-prop-in-callback.js │ │ │ │ │ │ │ ├── error.todo-for-await-loops.expect.md │ │ │ │ │ │ │ ├── error.todo-for-await-loops.js │ │ │ │ │ │ │ ├── error.todo-for-in-loop-with-context-variable-iterator.expect.md │ │ │ │ │ │ │ ├── error.todo-for-in-loop-with-context-variable-iterator.js │ │ │ │ │ │ │ ├── error.todo-for-loop-with-context-variable-iterator.expect.md │ │ │ │ │ │ │ ├── error.todo-for-loop-with-context-variable-iterator.js │ │ │ │ │ │ │ ├── error.todo-for-of-loop-with-context-variable-iterator.expect.md │ │ │ │ │ │ │ ├── error.todo-for-of-loop-with-context-variable-iterator.js │ │ │ │ │ │ │ ├── error.todo-function-expression-references-later-variable-declaration.expect.md │ │ │ │ │ │ │ ├── error.todo-function-expression-references-later-variable-declaration.js │ │ │ │ │ │ │ ├── error.todo-functiondecl-hoisting.expect.md │ │ │ │ │ │ │ ├── error.todo-functiondecl-hoisting.tsx │ │ │ │ │ │ │ ├── error.todo-handle-update-context-identifiers.expect.md │ │ │ │ │ │ │ ├── error.todo-handle-update-context-identifiers.js │ │ │ │ │ │ │ ├── error.todo-hoist-function-decls.expect.md │ │ │ │ │ │ │ ├── error.todo-hoist-function-decls.js │ │ │ │ │ │ │ ├── error.todo-hoisted-function-in-unreachable-code.expect.md │ │ │ │ │ │ │ ├── error.todo-hoisted-function-in-unreachable-code.js │ │ │ │ │ │ │ ├── error.todo-hoisting-simple-var-declaration.expect.md │ │ │ │ │ │ │ ├── error.todo-hoisting-simple-var-declaration.js │ │ │ │ │ │ │ ├── error.todo-hook-call-spreads-mutable-iterator.expect.md │ │ │ │ │ │ │ ├── error.todo-hook-call-spreads-mutable-iterator.js │ │ │ │ │ │ │ ├── error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.expect.md │ │ │ │ │ │ │ ├── error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.js │ │ │ │ │ │ │ ├── error.todo-invalid-jsx-in-try-with-finally.expect.md │ │ │ │ │ │ │ ├── error.todo-invalid-jsx-in-try-with-finally.js │ │ │ │ │ │ │ ├── error.todo-kitchensink.expect.md │ │ │ │ │ │ │ ├── error.todo-kitchensink.js │ │ │ │ │ │ │ ├── error.todo-missing-source-locations.expect.md │ │ │ │ │ │ │ ├── error.todo-missing-source-locations.js │ │ │ │ │ │ │ ├── error.todo-nested-method-calls-lower-property-load-into-temporary.expect.md │ │ │ │ │ │ │ ├── error.todo-nested-method-calls-lower-property-load-into-temporary.js │ │ │ │ │ │ │ ├── error.todo-new-target-meta-property.expect.md │ │ │ │ │ │ │ ├── error.todo-new-target-meta-property.js │ │ │ │ │ │ │ ├── error.todo-object-expression-get-syntax.expect.md │ │ │ │ │ │ │ ├── error.todo-object-expression-get-syntax.js │ │ │ │ │ │ │ ├── error.todo-object-expression-set-syntax.expect.md │ │ │ │ │ │ │ ├── error.todo-object-expression-set-syntax.js │ │ │ │ │ │ │ ├── error.todo-preserve-memo-deps-mixed-optional-nonoptional-property-chain.expect.md │ │ │ │ │ │ │ ├── error.todo-preserve-memo-deps-mixed-optional-nonoptional-property-chain.js │ │ │ │ │ │ │ ├── error.todo-reassign-const.expect.md │ │ │ │ │ │ │ ├── error.todo-reassign-const.js │ │ │ │ │ │ │ ├── error.todo-repro-missed-memoization-from-capture-in-invoked-function-inferred-as-mutation.expect.md │ │ │ │ │ │ │ ├── error.todo-repro-missed-memoization-from-capture-in-invoked-function-inferred-as-mutation.js │ │ │ │ │ │ │ ├── error.todo-repro-missed-memoization-from-inferred-mutation-in-logger.expect.md │ │ │ │ │ │ │ ├── error.todo-repro-missed-memoization-from-inferred-mutation-in-logger.js │ │ │ │ │ │ │ ├── error.todo-repro-named-function-with-shadowed-local-same-name.expect.md │ │ │ │ │ │ │ ├── error.todo-repro-named-function-with-shadowed-local-same-name.js │ │ │ │ │ │ │ ├── error.todo-repro-unmemoized-callback-captured-in-context-variable.expect.md │ │ │ │ │ │ │ ├── error.todo-repro-unmemoized-callback-captured-in-context-variable.tsx │ │ │ │ │ │ │ ├── error.todo-useCallback-set-ref-nested-property-ref-modified-later-preserve-memoization.expect.md │ │ │ │ │ │ │ ├── error.todo-useCallback-set-ref-nested-property-ref-modified-later-preserve-memoization.js │ │ │ │ │ │ │ ├── error.todo-valid-functiondecl-hoisting.expect.md │ │ │ │ │ │ │ ├── error.todo-valid-functiondecl-hoisting.tsx │ │ │ │ │ │ │ ├── error.todo.try-catch-with-throw.expect.md │ │ │ │ │ │ │ ├── error.todo.try-catch-with-throw.js │ │ │ │ │ │ │ ├── error.unconditional-set-state-in-render-after-loop-break.expect.md │ │ │ │ │ │ │ ├── error.unconditional-set-state-in-render-after-loop-break.js │ │ │ │ │ │ │ ├── error.unconditional-set-state-in-render-after-loop.expect.md │ │ │ │ │ │ │ ├── error.unconditional-set-state-in-render-after-loop.js │ │ │ │ │ │ │ ├── error.unconditional-set-state-in-render-with-loop-throw.expect.md │ │ │ │ │ │ │ ├── error.unconditional-set-state-in-render-with-loop-throw.js │ │ │ │ │ │ │ ├── error.unconditional-set-state-lambda.expect.md │ │ │ │ │ │ │ ├── error.unconditional-set-state-lambda.js │ │ │ │ │ │ │ ├── error.unconditional-set-state-nested-function-expressions.expect.md │ │ │ │ │ │ │ ├── error.unconditional-set-state-nested-function-expressions.js │ │ │ │ │ │ │ ├── error.update-global-should-bailout.expect.md │ │ │ │ │ │ │ ├── error.update-global-should-bailout.tsx │ │ │ │ │ │ │ ├── error.useCallback-accesses-ref-mutated-later-via-function-preserve-memoization.expect.md │ │ │ │ │ │ │ ├── error.useCallback-accesses-ref-mutated-later-via-function-preserve-memoization.js │ │ │ │ │ │ │ ├── error.useCallback-set-ref-nested-property-dont-preserve-memoization.expect.md │ │ │ │ │ │ │ ├── error.useCallback-set-ref-nested-property-dont-preserve-memoization.js │ │ │ │ │ │ │ ├── error.useMemo-callback-generator.expect.md │ │ │ │ │ │ │ ├── error.useMemo-callback-generator.js │ │ │ │ │ │ │ ├── error.useMemo-non-literal-depslist.expect.md │ │ │ │ │ │ │ ├── error.useMemo-non-literal-depslist.ts │ │ │ │ │ │ │ ├── error.validate-blocklisted-imports.expect.md │ │ │ │ │ │ │ ├── error.validate-blocklisted-imports.ts │ │ │ │ │ │ │ ├── error.validate-mutate-ref-arg-in-render.expect.md │ │ │ │ │ │ │ ├── error.validate-mutate-ref-arg-in-render.js │ │ │ │ │ │ │ ├── error.validate-object-entries-mutation.expect.md │ │ │ │ │ │ │ ├── error.validate-object-entries-mutation.js │ │ │ │ │ │ │ ├── error.validate-object-values-mutation.expect.md │ │ │ │ │ │ │ ├── error.validate-object-values-mutation.js │ │ │ │ │ │ │ ├── escape-analysis-destructured-rest-element.expect.md │ │ │ │ │ │ │ ├── escape-analysis-destructured-rest-element.js │ │ │ │ │ │ │ ├── escape-analysis-jsx-child.expect.md │ │ │ │ │ │ │ ├── escape-analysis-jsx-child.js │ │ │ │ │ │ │ ├── escape-analysis-logical.expect.md │ │ │ │ │ │ │ ├── escape-analysis-logical.js │ │ │ │ │ │ │ ├── escape-analysis-non-escaping-interleaved-allocating-dependency.expect.md │ │ │ │ │ │ │ ├── escape-analysis-non-escaping-interleaved-allocating-dependency.js │ │ │ │ │ │ │ ├── escape-analysis-non-escaping-interleaved-allocating-nested-dependency.expect.md │ │ │ │ │ │ │ ├── escape-analysis-non-escaping-interleaved-allocating-nested-dependency.js │ │ │ │ │ │ │ ├── escape-analysis-non-escaping-interleaved-primitive-dependency.expect.md │ │ │ │ │ │ │ ├── escape-analysis-non-escaping-interleaved-primitive-dependency.js │ │ │ │ │ │ │ ├── escape-analysis-not-conditional-test.expect.md │ │ │ │ │ │ │ ├── escape-analysis-not-conditional-test.js │ │ │ │ │ │ │ ├── escape-analysis-not-if-test.expect.md │ │ │ │ │ │ │ ├── escape-analysis-not-if-test.js │ │ │ │ │ │ │ ├── escape-analysis-not-switch-case.expect.md │ │ │ │ │ │ │ ├── escape-analysis-not-switch-case.js │ │ │ │ │ │ │ ├── escape-analysis-not-switch-test.expect.md │ │ │ │ │ │ │ ├── escape-analysis-not-switch-test.js │ │ │ │ │ │ │ ├── evaluation-order-mutate-call-after-dependency-load.expect.md │ │ │ │ │ │ │ ├── evaluation-order-mutate-call-after-dependency-load.ts │ │ │ │ │ │ │ ├── evaluation-order-mutate-store-after-dependency-load.expect.md │ │ │ │ │ │ │ ├── evaluation-order-mutate-store-after-dependency-load.ts │ │ │ │ │ │ │ ├── exhaustive-deps/ │ │ │ │ │ │ │ │ ├── compile-files-with-exhaustive-deps-violation-in-effects.expect.md │ │ │ │ │ │ │ │ ├── compile-files-with-exhaustive-deps-violation-in-effects.js │ │ │ │ │ │ │ │ ├── error.exhaustive-deps-effect-events.expect.md │ │ │ │ │ │ │ │ ├── error.exhaustive-deps-effect-events.js │ │ │ │ │ │ │ │ ├── error.invalid-dep-on-ref-current-value.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-dep-on-ref-current-value.js │ │ │ │ │ │ │ │ ├── error.invalid-exhaustive-deps-disallow-unused-stable-types.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-exhaustive-deps-disallow-unused-stable-types.js │ │ │ │ │ │ │ │ ├── error.invalid-exhaustive-deps.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-exhaustive-deps.js │ │ │ │ │ │ │ │ ├── error.invalid-exhaustive-effect-deps-extra-only.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-exhaustive-effect-deps-extra-only.js │ │ │ │ │ │ │ │ ├── error.invalid-exhaustive-effect-deps-missing-only.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-exhaustive-effect-deps-missing-only.js │ │ │ │ │ │ │ │ ├── error.invalid-exhaustive-effect-deps.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-exhaustive-effect-deps.js │ │ │ │ │ │ │ │ ├── error.invalid-missing-nonreactive-dep-inner-function.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-missing-nonreactive-dep-inner-function.js │ │ │ │ │ │ │ │ ├── error.invalid-missing-nonreactive-dep-unmemoized.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-missing-nonreactive-dep-unmemoized.js │ │ │ │ │ │ │ │ ├── error.invalid-missing-nonreactive-dep.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-missing-nonreactive-dep.js │ │ │ │ │ │ │ │ ├── error.sketchy-code-exhaustive-deps.expect.md │ │ │ │ │ │ │ │ ├── error.sketchy-code-exhaustive-deps.js │ │ │ │ │ │ │ │ ├── exhaustive-deps-allow-constant-folded-values.expect.md │ │ │ │ │ │ │ │ ├── exhaustive-deps-allow-constant-folded-values.js │ │ │ │ │ │ │ │ ├── exhaustive-deps-allow-nonreactive-stable-types-as-extra-deps.expect.md │ │ │ │ │ │ │ │ ├── exhaustive-deps-allow-nonreactive-stable-types-as-extra-deps.js │ │ │ │ │ │ │ │ ├── exhaustive-deps-effect-events.expect.md │ │ │ │ │ │ │ │ ├── exhaustive-deps-effect-events.js │ │ │ │ │ │ │ │ ├── exhaustive-deps.expect.md │ │ │ │ │ │ │ │ └── exhaustive-deps.js │ │ │ │ │ │ │ ├── existing-variables-with-c-name.expect.md │ │ │ │ │ │ │ ├── existing-variables-with-c-name.js │ │ │ │ │ │ │ ├── expression-with-assignment-dynamic.expect.md │ │ │ │ │ │ │ ├── expression-with-assignment-dynamic.js │ │ │ │ │ │ │ ├── expression-with-assignment.expect.md │ │ │ │ │ │ │ ├── expression-with-assignment.js │ │ │ │ │ │ │ ├── extend-scopes-if.expect.md │ │ │ │ │ │ │ ├── extend-scopes-if.js │ │ │ │ │ │ │ ├── fast-refresh-dont-refresh-const-changes-prod.expect.md │ │ │ │ │ │ │ ├── fast-refresh-dont-refresh-const-changes-prod.js │ │ │ │ │ │ │ ├── fast-refresh-refresh-on-const-changes-dev.expect.md │ │ │ │ │ │ │ ├── fast-refresh-refresh-on-const-changes-dev.js │ │ │ │ │ │ │ ├── fast-refresh-reloading.expect.md │ │ │ │ │ │ │ ├── fast-refresh-reloading.js │ │ │ │ │ │ │ ├── fault-tolerance/ │ │ │ │ │ │ │ │ ├── error.try-finally-and-mutation-of-props.expect.md │ │ │ │ │ │ │ │ ├── error.try-finally-and-mutation-of-props.js │ │ │ │ │ │ │ │ ├── error.try-finally-and-ref-access.expect.md │ │ │ │ │ │ │ │ ├── error.try-finally-and-ref-access.js │ │ │ │ │ │ │ │ ├── error.try-finally-ref-access-and-mutation.expect.md │ │ │ │ │ │ │ │ ├── error.try-finally-ref-access-and-mutation.js │ │ │ │ │ │ │ │ ├── error.var-declaration-and-mutation-of-props.expect.md │ │ │ │ │ │ │ │ ├── error.var-declaration-and-mutation-of-props.js │ │ │ │ │ │ │ │ ├── error.var-declaration-and-ref-access.expect.md │ │ │ │ │ │ │ │ └── error.var-declaration-and-ref-access.js │ │ │ │ │ │ │ ├── fbt/ │ │ │ │ │ │ │ │ ├── bug-fbt-plural-multiple-function-calls.expect.md │ │ │ │ │ │ │ │ ├── bug-fbt-plural-multiple-function-calls.ts │ │ │ │ │ │ │ │ ├── bug-fbt-plural-multiple-mixed-call-tag.expect.md │ │ │ │ │ │ │ │ ├── bug-fbt-plural-multiple-mixed-call-tag.tsx │ │ │ │ │ │ │ │ ├── error.todo-fbt-as-local.expect.md │ │ │ │ │ │ │ │ ├── error.todo-fbt-as-local.js │ │ │ │ │ │ │ │ ├── error.todo-fbt-unknown-enum-value.expect.md │ │ │ │ │ │ │ │ ├── error.todo-fbt-unknown-enum-value.js │ │ │ │ │ │ │ │ ├── error.todo-locally-require-fbt.expect.md │ │ │ │ │ │ │ │ ├── error.todo-locally-require-fbt.js │ │ │ │ │ │ │ │ ├── error.todo-multiple-fbt-plural.expect.md │ │ │ │ │ │ │ │ ├── error.todo-multiple-fbt-plural.tsx │ │ │ │ │ │ │ │ ├── fbs-params.expect.md │ │ │ │ │ │ │ │ ├── fbs-params.js │ │ │ │ │ │ │ │ ├── fbt-call-complex-param-value.expect.md │ │ │ │ │ │ │ │ ├── fbt-call-complex-param-value.js │ │ │ │ │ │ │ │ ├── fbt-call.expect.md │ │ │ │ │ │ │ │ ├── fbt-call.js │ │ │ │ │ │ │ │ ├── fbt-no-whitespace-btw-text-and-param.expect.md │ │ │ │ │ │ │ │ ├── fbt-no-whitespace-btw-text-and-param.tsx │ │ │ │ │ │ │ │ ├── fbt-param-with-leading-whitespace.expect.md │ │ │ │ │ │ │ │ ├── fbt-param-with-leading-whitespace.js │ │ │ │ │ │ │ │ ├── fbt-param-with-newline.expect.md │ │ │ │ │ │ │ │ ├── fbt-param-with-newline.js │ │ │ │ │ │ │ │ ├── fbt-param-with-quotes.expect.md │ │ │ │ │ │ │ │ ├── fbt-param-with-quotes.js │ │ │ │ │ │ │ │ ├── fbt-param-with-trailing-whitespace.expect.md │ │ │ │ │ │ │ │ ├── fbt-param-with-trailing-whitespace.js │ │ │ │ │ │ │ │ ├── fbt-param-with-unicode.expect.md │ │ │ │ │ │ │ │ ├── fbt-param-with-unicode.js │ │ │ │ │ │ │ │ ├── fbt-params-complex-param-value.expect.md │ │ │ │ │ │ │ │ ├── fbt-params-complex-param-value.js │ │ │ │ │ │ │ │ ├── fbt-params.expect.md │ │ │ │ │ │ │ │ ├── fbt-params.js │ │ │ │ │ │ │ │ ├── fbt-preserve-jsxtext.expect.md │ │ │ │ │ │ │ │ ├── fbt-preserve-jsxtext.js │ │ │ │ │ │ │ │ ├── fbt-preserve-whitespace-subtree.expect.md │ │ │ │ │ │ │ │ ├── fbt-preserve-whitespace-subtree.tsx │ │ │ │ │ │ │ │ ├── fbt-preserve-whitespace-two-subtrees.expect.md │ │ │ │ │ │ │ │ ├── fbt-preserve-whitespace-two-subtrees.tsx │ │ │ │ │ │ │ │ ├── fbt-preserve-whitespace.expect.md │ │ │ │ │ │ │ │ ├── fbt-preserve-whitespace.tsx │ │ │ │ │ │ │ │ ├── fbt-repro-invalid-mutable-range-destructured-prop.expect.md │ │ │ │ │ │ │ │ ├── fbt-repro-invalid-mutable-range-destructured-prop.js │ │ │ │ │ │ │ │ ├── fbt-single-space-btw-param-and-text.expect.md │ │ │ │ │ │ │ │ ├── fbt-single-space-btw-param-and-text.tsx │ │ │ │ │ │ │ │ ├── fbt-template-string-same-scope.expect.md │ │ │ │ │ │ │ │ ├── fbt-template-string-same-scope.js │ │ │ │ │ │ │ │ ├── fbt-to-string.expect.md │ │ │ │ │ │ │ │ ├── fbt-to-string.js │ │ │ │ │ │ │ │ ├── fbt-whitespace-around-param-value.expect.md │ │ │ │ │ │ │ │ ├── fbt-whitespace-around-param-value.tsx │ │ │ │ │ │ │ │ ├── fbt-whitespace-within-text.expect.md │ │ │ │ │ │ │ │ ├── fbt-whitespace-within-text.tsx │ │ │ │ │ │ │ │ ├── fbtparam-text-must-use-expression-container.expect.md │ │ │ │ │ │ │ │ ├── fbtparam-text-must-use-expression-container.js │ │ │ │ │ │ │ │ ├── fbtparam-with-jsx-element-content.expect.md │ │ │ │ │ │ │ │ ├── fbtparam-with-jsx-element-content.js │ │ │ │ │ │ │ │ ├── fbtparam-with-jsx-fragment-value.expect.md │ │ │ │ │ │ │ │ ├── fbtparam-with-jsx-fragment-value.js │ │ │ │ │ │ │ │ ├── lambda-with-fbt.expect.md │ │ │ │ │ │ │ │ ├── lambda-with-fbt.js │ │ │ │ │ │ │ │ ├── recursively-merge-scopes-jsx.expect.md │ │ │ │ │ │ │ │ ├── recursively-merge-scopes-jsx.js │ │ │ │ │ │ │ │ ├── repro-fbt-param-nested-fbt-jsx.expect.md │ │ │ │ │ │ │ │ ├── repro-fbt-param-nested-fbt-jsx.js │ │ │ │ │ │ │ │ ├── repro-fbt-param-nested-fbt.expect.md │ │ │ │ │ │ │ │ ├── repro-fbt-param-nested-fbt.js │ │ │ │ │ │ │ │ ├── repro-macro-property-not-handled.expect.md │ │ │ │ │ │ │ │ ├── repro-macro-property-not-handled.tsx │ │ │ │ │ │ │ │ ├── repro-separately-memoized-fbt-param.expect.md │ │ │ │ │ │ │ │ └── repro-separately-memoized-fbt-param.js │ │ │ │ │ │ │ ├── flag-enable-emit-hook-guards.expect.md │ │ │ │ │ │ │ ├── flag-enable-emit-hook-guards.ts │ │ │ │ │ │ │ ├── flatten-scopes-with-methodcall-hook.expect.md │ │ │ │ │ │ │ ├── flatten-scopes-with-methodcall-hook.js │ │ │ │ │ │ │ ├── flow-enum-inline.expect.md │ │ │ │ │ │ │ ├── flow-enum-inline.js │ │ │ │ │ │ │ ├── for-empty-update-with-continue.expect.md │ │ │ │ │ │ │ ├── for-empty-update-with-continue.js │ │ │ │ │ │ │ ├── for-empty-update.expect.md │ │ │ │ │ │ │ ├── for-empty-update.js │ │ │ │ │ │ │ ├── for-in-statement-body-always-returns.expect.md │ │ │ │ │ │ │ ├── for-in-statement-body-always-returns.js │ │ │ │ │ │ │ ├── for-in-statement-break.expect.md │ │ │ │ │ │ │ ├── for-in-statement-break.js │ │ │ │ │ │ │ ├── for-in-statement-continue.expect.md │ │ │ │ │ │ │ ├── for-in-statement-continue.js │ │ │ │ │ │ │ ├── for-in-statement-empty-body.expect.md │ │ │ │ │ │ │ ├── for-in-statement-empty-body.js │ │ │ │ │ │ │ ├── for-in-statement-type-inference.expect.md │ │ │ │ │ │ │ ├── for-in-statement-type-inference.js │ │ │ │ │ │ │ ├── for-in-statement.expect.md │ │ │ │ │ │ │ ├── for-in-statement.js │ │ │ │ │ │ │ ├── for-logical.expect.md │ │ │ │ │ │ │ ├── for-logical.js │ │ │ │ │ │ │ ├── for-loop-let-undefined-decl.expect.md │ │ │ │ │ │ │ ├── for-loop-let-undefined-decl.js │ │ │ │ │ │ │ ├── for-loop-with-value-block-initializer.expect.md │ │ │ │ │ │ │ ├── for-loop-with-value-block-initializer.js │ │ │ │ │ │ │ ├── for-multiple-variable-declarations-in-initializer.expect.md │ │ │ │ │ │ │ ├── for-multiple-variable-declarations-in-initializer.js │ │ │ │ │ │ │ ├── for-of-break.expect.md │ │ │ │ │ │ │ ├── for-of-break.js │ │ │ │ │ │ │ ├── for-of-capture-item-of-local-collection-mutate-later-value-initially-null.expect.md │ │ │ │ │ │ │ ├── for-of-capture-item-of-local-collection-mutate-later-value-initially-null.js │ │ │ │ │ │ │ ├── for-of-capture-item-of-local-collection-mutate-later.expect.md │ │ │ │ │ │ │ ├── for-of-capture-item-of-local-collection-mutate-later.js │ │ │ │ │ │ │ ├── for-of-conditional-break.expect.md │ │ │ │ │ │ │ ├── for-of-conditional-break.js │ │ │ │ │ │ │ ├── for-of-continue.expect.md │ │ │ │ │ │ │ ├── for-of-continue.js │ │ │ │ │ │ │ ├── for-of-destructure.expect.md │ │ │ │ │ │ │ ├── for-of-destructure.js │ │ │ │ │ │ │ ├── for-of-immutable-collection.expect.md │ │ │ │ │ │ │ ├── for-of-immutable-collection.js │ │ │ │ │ │ │ ├── for-of-iterator-of-immutable-collection.expect.md │ │ │ │ │ │ │ ├── for-of-iterator-of-immutable-collection.js │ │ │ │ │ │ │ ├── for-of-mutate-item-of-local-collection.expect.md │ │ │ │ │ │ │ ├── for-of-mutate-item-of-local-collection.js │ │ │ │ │ │ │ ├── for-of-mutate.expect.md │ │ │ │ │ │ │ ├── for-of-mutate.tsx │ │ │ │ │ │ │ ├── for-of-nonmutating-loop-local-collection.expect.md │ │ │ │ │ │ │ ├── for-of-nonmutating-loop-local-collection.js │ │ │ │ │ │ │ ├── for-of-simple.expect.md │ │ │ │ │ │ │ ├── for-of-simple.js │ │ │ │ │ │ │ ├── for-return.expect.md │ │ │ │ │ │ │ ├── for-return.js │ │ │ │ │ │ │ ├── for-with-assignment-as-update.expect.md │ │ │ │ │ │ │ ├── for-with-assignment-as-update.js │ │ │ │ │ │ │ ├── frozen-after-alias.expect.md │ │ │ │ │ │ │ ├── frozen-after-alias.js │ │ │ │ │ │ │ ├── function-declaration-reassign.expect.md │ │ │ │ │ │ │ ├── function-declaration-reassign.js │ │ │ │ │ │ │ ├── function-declaration-redeclare.expect.md │ │ │ │ │ │ │ ├── function-declaration-redeclare.js │ │ │ │ │ │ │ ├── function-declaration-simple.expect.md │ │ │ │ │ │ │ ├── function-declaration-simple.js │ │ │ │ │ │ │ ├── function-expr-directive.expect.md │ │ │ │ │ │ │ ├── function-expr-directive.js │ │ │ │ │ │ │ ├── function-expression-captures-value-later-frozen-jsx.expect.md │ │ │ │ │ │ │ ├── function-expression-captures-value-later-frozen-jsx.js │ │ │ │ │ │ │ ├── function-expression-maybe-mutates-hook-return-value.expect.md │ │ │ │ │ │ │ ├── function-expression-maybe-mutates-hook-return-value.js │ │ │ │ │ │ │ ├── function-expression-prototype-call-mutating.expect.md │ │ │ │ │ │ │ ├── function-expression-prototype-call-mutating.js │ │ │ │ │ │ │ ├── function-expression-prototype-call.expect.md │ │ │ │ │ │ │ ├── function-expression-prototype-call.js │ │ │ │ │ │ │ ├── function-expression-with-store-to-parameter.expect.md │ │ │ │ │ │ │ ├── function-expression-with-store-to-parameter.js │ │ │ │ │ │ │ ├── function-param-assignment-pattern.expect.md │ │ │ │ │ │ │ ├── function-param-assignment-pattern.js │ │ │ │ │ │ │ ├── gating/ │ │ │ │ │ │ │ │ ├── arrow-function-expr-gating-test.expect.md │ │ │ │ │ │ │ │ ├── arrow-function-expr-gating-test.js │ │ │ │ │ │ │ │ ├── codegen-instrument-forget-gating-test.expect.md │ │ │ │ │ │ │ │ ├── codegen-instrument-forget-gating-test.js │ │ │ │ │ │ │ │ ├── component-syntax-ref-gating.flow.expect.md │ │ │ │ │ │ │ │ ├── component-syntax-ref-gating.flow.js │ │ │ │ │ │ │ │ ├── conflicting-gating-fn.expect.md │ │ │ │ │ │ │ │ ├── conflicting-gating-fn.js │ │ │ │ │ │ │ │ ├── dynamic-gating-annotation.expect.md │ │ │ │ │ │ │ │ ├── dynamic-gating-annotation.js │ │ │ │ │ │ │ │ ├── dynamic-gating-bailout-nopanic.expect.md │ │ │ │ │ │ │ │ ├── dynamic-gating-bailout-nopanic.js │ │ │ │ │ │ │ │ ├── dynamic-gating-disabled.expect.md │ │ │ │ │ │ │ │ ├── dynamic-gating-disabled.js │ │ │ │ │ │ │ │ ├── dynamic-gating-enabled.expect.md │ │ │ │ │ │ │ │ ├── dynamic-gating-enabled.js │ │ │ │ │ │ │ │ ├── dynamic-gating-invalid-identifier-nopanic.expect.md │ │ │ │ │ │ │ │ ├── dynamic-gating-invalid-identifier-nopanic.js │ │ │ │ │ │ │ │ ├── dynamic-gating-invalid-multiple.expect.md │ │ │ │ │ │ │ │ ├── dynamic-gating-invalid-multiple.js │ │ │ │ │ │ │ │ ├── dynamic-gating-noemit.expect.md │ │ │ │ │ │ │ │ ├── dynamic-gating-noemit.js │ │ │ │ │ │ │ │ ├── error.dynamic-gating-invalid-identifier.expect.md │ │ │ │ │ │ │ │ ├── error.dynamic-gating-invalid-identifier.js │ │ │ │ │ │ │ │ ├── gating-access-function-name-in-component.expect.md │ │ │ │ │ │ │ │ ├── gating-access-function-name-in-component.js │ │ │ │ │ │ │ │ ├── gating-nonreferenced-identifier-collision.expect.md │ │ │ │ │ │ │ │ ├── gating-nonreferenced-identifier-collision.js │ │ │ │ │ │ │ │ ├── gating-preserves-function-properties.expect.md │ │ │ │ │ │ │ │ ├── gating-preserves-function-properties.tsx │ │ │ │ │ │ │ │ ├── gating-test-export-default-function.expect.md │ │ │ │ │ │ │ │ ├── gating-test-export-default-function.js │ │ │ │ │ │ │ │ ├── gating-test-export-function-and-default.expect.md │ │ │ │ │ │ │ │ ├── gating-test-export-function-and-default.js │ │ │ │ │ │ │ │ ├── gating-test-export-function.expect.md │ │ │ │ │ │ │ │ ├── gating-test-export-function.js │ │ │ │ │ │ │ │ ├── gating-test.expect.md │ │ │ │ │ │ │ │ ├── gating-test.js │ │ │ │ │ │ │ │ ├── gating-use-before-decl-ref.expect.md │ │ │ │ │ │ │ │ ├── gating-use-before-decl-ref.js │ │ │ │ │ │ │ │ ├── gating-use-before-decl.expect.md │ │ │ │ │ │ │ │ ├── gating-use-before-decl.js │ │ │ │ │ │ │ │ ├── gating-with-hoisted-type-reference.flow.expect.md │ │ │ │ │ │ │ │ ├── gating-with-hoisted-type-reference.flow.js │ │ │ │ │ │ │ │ ├── infer-function-expression-React-memo-gating.expect.md │ │ │ │ │ │ │ │ ├── infer-function-expression-React-memo-gating.js │ │ │ │ │ │ │ │ ├── invalid-fnexpr-reference.expect.md │ │ │ │ │ │ │ │ ├── invalid-fnexpr-reference.js │ │ │ │ │ │ │ │ ├── multi-arrow-expr-export-default-gating-test.expect.md │ │ │ │ │ │ │ │ ├── multi-arrow-expr-export-default-gating-test.js │ │ │ │ │ │ │ │ ├── multi-arrow-expr-export-gating-test.expect.md │ │ │ │ │ │ │ │ ├── multi-arrow-expr-export-gating-test.js │ │ │ │ │ │ │ │ ├── multi-arrow-expr-gating-test.expect.md │ │ │ │ │ │ │ │ ├── multi-arrow-expr-gating-test.js │ │ │ │ │ │ │ │ ├── reassigned-fnexpr-variable.expect.md │ │ │ │ │ │ │ │ ├── reassigned-fnexpr-variable.js │ │ │ │ │ │ │ │ ├── repro-no-gating-import-without-compiled-functions.expect.md │ │ │ │ │ │ │ │ └── repro-no-gating-import-without-compiled-functions.js │ │ │ │ │ │ │ ├── global-jsx-tag-lowered-between-mutations.expect.md │ │ │ │ │ │ │ ├── global-jsx-tag-lowered-between-mutations.js │ │ │ │ │ │ │ ├── global-types/ │ │ │ │ │ │ │ │ ├── call-spread-argument-set.expect.md │ │ │ │ │ │ │ │ ├── call-spread-argument-set.ts │ │ │ │ │ │ │ │ ├── map-constructor.expect.md │ │ │ │ │ │ │ │ ├── map-constructor.ts │ │ │ │ │ │ │ │ ├── repro-array-filter-capture-mutate-bug.expect.md │ │ │ │ │ │ │ │ ├── repro-array-filter-capture-mutate-bug.tsx │ │ │ │ │ │ │ │ ├── repro-array-filter-known-nonmutate-Boolean.expect.md │ │ │ │ │ │ │ │ ├── repro-array-filter-known-nonmutate-Boolean.tsx │ │ │ │ │ │ │ │ ├── repro-array-map-capture-mutate-bug.expect.md │ │ │ │ │ │ │ │ ├── repro-array-map-capture-mutate-bug.tsx │ │ │ │ │ │ │ │ ├── repro-array-map-known-mutate-shape.expect.md │ │ │ │ │ │ │ │ ├── repro-array-map-known-mutate-shape.tsx │ │ │ │ │ │ │ │ ├── set-add-mutate.expect.md │ │ │ │ │ │ │ │ ├── set-add-mutate.ts │ │ │ │ │ │ │ │ ├── set-constructor-arg.expect.md │ │ │ │ │ │ │ │ ├── set-constructor-arg.ts │ │ │ │ │ │ │ │ ├── set-constructor.expect.md │ │ │ │ │ │ │ │ ├── set-constructor.ts │ │ │ │ │ │ │ │ ├── set-copy-constructor-mutate.expect.md │ │ │ │ │ │ │ │ ├── set-copy-constructor-mutate.ts │ │ │ │ │ │ │ │ ├── set-for-of-iterate-values.expect.md │ │ │ │ │ │ │ │ ├── set-for-of-iterate-values.ts │ │ │ │ │ │ │ │ ├── set-foreach-mutate.expect.md │ │ │ │ │ │ │ │ └── set-foreach-mutate.tsx │ │ │ │ │ │ │ ├── globals-Boolean.expect.md │ │ │ │ │ │ │ ├── globals-Boolean.js │ │ │ │ │ │ │ ├── globals-Number.expect.md │ │ │ │ │ │ │ ├── globals-Number.js │ │ │ │ │ │ │ ├── globals-String.expect.md │ │ │ │ │ │ │ ├── globals-String.js │ │ │ │ │ │ │ ├── globals-dont-resolve-local-useState.expect.md │ │ │ │ │ │ │ ├── globals-dont-resolve-local-useState.js │ │ │ │ │ │ │ ├── hoist-destruct.expect.md │ │ │ │ │ │ │ ├── hoist-destruct.js │ │ │ │ │ │ │ ├── hoisted-context-variable-in-outlined-fn.expect.md │ │ │ │ │ │ │ ├── hoisted-context-variable-in-outlined-fn.js │ │ │ │ │ │ │ ├── hoisted-declaration-with-scope.expect.md │ │ │ │ │ │ │ ├── hoisted-declaration-with-scope.tsx │ │ │ │ │ │ │ ├── hoisted-function-declaration.expect.md │ │ │ │ │ │ │ ├── hoisted-function-declaration.js │ │ │ │ │ │ │ ├── hoisting-computed-member-expression.expect.md │ │ │ │ │ │ │ ├── hoisting-computed-member-expression.js │ │ │ │ │ │ │ ├── hoisting-functionexpr-conditional-dep.expect.md │ │ │ │ │ │ │ ├── hoisting-functionexpr-conditional-dep.tsx │ │ │ │ │ │ │ ├── hoisting-invalid-tdz-let.expect.md │ │ │ │ │ │ │ ├── hoisting-invalid-tdz-let.js │ │ │ │ │ │ │ ├── hoisting-let-declaration-without-initialization.expect.md │ │ │ │ │ │ │ ├── hoisting-let-declaration-without-initialization.js │ │ │ │ │ │ │ ├── hoisting-member-expression.expect.md │ │ │ │ │ │ │ ├── hoisting-member-expression.js │ │ │ │ │ │ │ ├── hoisting-nested-block-statements.expect.md │ │ │ │ │ │ │ ├── hoisting-nested-block-statements.js │ │ │ │ │ │ │ ├── hoisting-nested-const-declaration-2.expect.md │ │ │ │ │ │ │ ├── hoisting-nested-const-declaration-2.js │ │ │ │ │ │ │ ├── hoisting-nested-const-declaration.expect.md │ │ │ │ │ │ │ ├── hoisting-nested-const-declaration.js │ │ │ │ │ │ │ ├── hoisting-nested-let-declaration-2.expect.md │ │ │ │ │ │ │ ├── hoisting-nested-let-declaration-2.js │ │ │ │ │ │ │ ├── hoisting-nested-let-declaration.expect.md │ │ │ │ │ │ │ ├── hoisting-nested-let-declaration.js │ │ │ │ │ │ │ ├── hoisting-object-method.expect.md │ │ │ │ │ │ │ ├── hoisting-object-method.js │ │ │ │ │ │ │ ├── hoisting-reassigned-let-declaration.expect.md │ │ │ │ │ │ │ ├── hoisting-reassigned-let-declaration.js │ │ │ │ │ │ │ ├── hoisting-reassigned-twice-let-declaration.expect.md │ │ │ │ │ │ │ ├── hoisting-reassigned-twice-let-declaration.js │ │ │ │ │ │ │ ├── hoisting-recursive-call-within-lambda.expect.md │ │ │ │ │ │ │ ├── hoisting-recursive-call-within-lambda.js │ │ │ │ │ │ │ ├── hoisting-recursive-call.expect.md │ │ │ │ │ │ │ ├── hoisting-recursive-call.ts │ │ │ │ │ │ │ ├── hoisting-repro-variable-used-in-assignment.expect.md │ │ │ │ │ │ │ ├── hoisting-repro-variable-used-in-assignment.js │ │ │ │ │ │ │ ├── hoisting-setstate-captured-indirectly-jsx.expect.md │ │ │ │ │ │ │ ├── hoisting-setstate-captured-indirectly-jsx.js │ │ │ │ │ │ │ ├── hoisting-simple-const-declaration.expect.md │ │ │ │ │ │ │ ├── hoisting-simple-const-declaration.js │ │ │ │ │ │ │ ├── hoisting-simple-function-expression.expect.md │ │ │ │ │ │ │ ├── hoisting-simple-function-expression.js │ │ │ │ │ │ │ ├── hoisting-simple-let-declaration.expect.md │ │ │ │ │ │ │ ├── hoisting-simple-let-declaration.js │ │ │ │ │ │ │ ├── hoisting-within-lambda.expect.md │ │ │ │ │ │ │ ├── hoisting-within-lambda.js │ │ │ │ │ │ │ ├── holey-array-expr.expect.md │ │ │ │ │ │ │ ├── holey-array-expr.js │ │ │ │ │ │ │ ├── holey-array-pattern-dce-2.expect.md │ │ │ │ │ │ │ ├── holey-array-pattern-dce-2.js │ │ │ │ │ │ │ ├── holey-array-pattern-dce.expect.md │ │ │ │ │ │ │ ├── holey-array-pattern-dce.js │ │ │ │ │ │ │ ├── hook-call-freezes-captured-memberexpr.expect.md │ │ │ │ │ │ │ ├── hook-call-freezes-captured-memberexpr.tsx │ │ │ │ │ │ │ ├── hook-call.expect.md │ │ │ │ │ │ │ ├── hook-call.js │ │ │ │ │ │ │ ├── hook-declaration-basic.flow.expect.md │ │ │ │ │ │ │ ├── hook-declaration-basic.flow.js │ │ │ │ │ │ │ ├── hook-inside-logical-expression.expect.md │ │ │ │ │ │ │ ├── hook-inside-logical-expression.js │ │ │ │ │ │ │ ├── hook-noAlias.expect.md │ │ │ │ │ │ │ ├── hook-noAlias.js │ │ │ │ │ │ │ ├── hook-property-load-local.expect.md │ │ │ │ │ │ │ ├── hook-property-load-local.js │ │ │ │ │ │ │ ├── hook-ref-callback.expect.md │ │ │ │ │ │ │ ├── hook-ref-callback.js │ │ │ │ │ │ │ ├── hooks-freeze-arguments.expect.md │ │ │ │ │ │ │ ├── hooks-freeze-arguments.js │ │ │ │ │ │ │ ├── hooks-freeze-possibly-mutable-arguments.expect.md │ │ │ │ │ │ │ ├── hooks-freeze-possibly-mutable-arguments.js │ │ │ │ │ │ │ ├── hooks-with-React-namespace.expect.md │ │ │ │ │ │ │ ├── hooks-with-React-namespace.js │ │ │ │ │ │ │ ├── idx-method-no-outlining-wildcard.expect.md │ │ │ │ │ │ │ ├── idx-method-no-outlining-wildcard.js │ │ │ │ │ │ │ ├── idx-method-no-outlining.expect.md │ │ │ │ │ │ │ ├── idx-method-no-outlining.js │ │ │ │ │ │ │ ├── idx-no-outlining.expect.md │ │ │ │ │ │ │ ├── idx-no-outlining.js │ │ │ │ │ │ │ ├── ignore-inner-interface-types.expect.md │ │ │ │ │ │ │ ├── ignore-inner-interface-types.ts │ │ │ │ │ │ │ ├── ignore-use-no-forget.expect.md │ │ │ │ │ │ │ ├── ignore-use-no-forget.js │ │ │ │ │ │ │ ├── iife-inline-ternary.expect.md │ │ │ │ │ │ │ ├── iife-inline-ternary.js │ │ │ │ │ │ │ ├── iife-return-modified-later-phi.expect.md │ │ │ │ │ │ │ ├── iife-return-modified-later-phi.js │ │ │ │ │ │ │ ├── iife-return-modified-later.expect.md │ │ │ │ │ │ │ ├── iife-return-modified-later.js │ │ │ │ │ │ │ ├── immutable-hooks.expect.md │ │ │ │ │ │ │ ├── immutable-hooks.js │ │ │ │ │ │ │ ├── import-as-local.expect.md │ │ │ │ │ │ │ ├── import-as-local.tsx │ │ │ │ │ │ │ ├── inadvertent-mutability-readonly-class.expect.md │ │ │ │ │ │ │ ├── inadvertent-mutability-readonly-class.js │ │ │ │ │ │ │ ├── inadvertent-mutability-readonly-lambda.expect.md │ │ │ │ │ │ │ ├── inadvertent-mutability-readonly-lambda.js │ │ │ │ │ │ │ ├── incompatible-destructuring-kinds.expect.md │ │ │ │ │ │ │ ├── incompatible-destructuring-kinds.js │ │ │ │ │ │ │ ├── independent-across-if.expect.md │ │ │ │ │ │ │ ├── independent-across-if.js │ │ │ │ │ │ │ ├── independent.expect.md │ │ │ │ │ │ │ ├── independent.js │ │ │ │ │ │ │ ├── independently-memoize-object-property.expect.md │ │ │ │ │ │ │ ├── independently-memoize-object-property.js │ │ │ │ │ │ │ ├── infer-compile-hooks-with-multiple-params.expect.md │ │ │ │ │ │ │ ├── infer-compile-hooks-with-multiple-params.js │ │ │ │ │ │ │ ├── infer-computed-delete.expect.md │ │ │ │ │ │ │ ├── infer-computed-delete.js │ │ │ │ │ │ │ ├── infer-dont-compile-components-with-multiple-params.expect.md │ │ │ │ │ │ │ ├── infer-dont-compile-components-with-multiple-params.js │ │ │ │ │ │ │ ├── infer-function-React-memo.expect.md │ │ │ │ │ │ │ ├── infer-function-React-memo.js │ │ │ │ │ │ │ ├── infer-function-assignment.expect.md │ │ │ │ │ │ │ ├── infer-function-assignment.js │ │ │ │ │ │ │ ├── infer-function-expression-component.expect.md │ │ │ │ │ │ │ ├── infer-function-expression-component.js │ │ │ │ │ │ │ ├── infer-function-forwardRef.expect.md │ │ │ │ │ │ │ ├── infer-function-forwardRef.js │ │ │ │ │ │ │ ├── infer-functions-component-with-hook-call.expect.md │ │ │ │ │ │ │ ├── infer-functions-component-with-hook-call.js │ │ │ │ │ │ │ ├── infer-functions-component-with-jsx.expect.md │ │ │ │ │ │ │ ├── infer-functions-component-with-jsx.js │ │ │ │ │ │ │ ├── infer-functions-component-with-ref-arg.expect.md │ │ │ │ │ │ │ ├── infer-functions-component-with-ref-arg.js │ │ │ │ │ │ │ ├── infer-functions-hook-with-hook-call.expect.md │ │ │ │ │ │ │ ├── infer-functions-hook-with-hook-call.js │ │ │ │ │ │ │ ├── infer-functions-hook-with-jsx.expect.md │ │ │ │ │ │ │ ├── infer-functions-hook-with-jsx.js │ │ │ │ │ │ │ ├── infer-global-object.expect.md │ │ │ │ │ │ │ ├── infer-global-object.js │ │ │ │ │ │ │ ├── infer-nested-object-method.expect.md │ │ │ │ │ │ │ ├── infer-nested-object-method.jsx │ │ │ │ │ │ │ ├── infer-no-component-annot.expect.md │ │ │ │ │ │ │ ├── infer-no-component-annot.ts │ │ │ │ │ │ │ ├── infer-no-component-nested-jsx.expect.md │ │ │ │ │ │ │ ├── infer-no-component-nested-jsx.js │ │ │ │ │ │ │ ├── infer-no-component-obj-return.expect.md │ │ │ │ │ │ │ ├── infer-no-component-obj-return.js │ │ │ │ │ │ │ ├── infer-phi-primitive.expect.md │ │ │ │ │ │ │ ├── infer-phi-primitive.js │ │ │ │ │ │ │ ├── infer-property-delete.expect.md │ │ │ │ │ │ │ ├── infer-property-delete.js │ │ │ │ │ │ │ ├── infer-sequential-optional-chain-nonnull.expect.md │ │ │ │ │ │ │ ├── infer-sequential-optional-chain-nonnull.ts │ │ │ │ │ │ │ ├── infer-skip-components-without-hooks-or-jsx.expect.md │ │ │ │ │ │ │ ├── infer-skip-components-without-hooks-or-jsx.js │ │ │ │ │ │ │ ├── infer-types-through-type-cast.flow.expect.md │ │ │ │ │ │ │ ├── infer-types-through-type-cast.flow.js │ │ │ │ │ │ │ ├── inner-function/ │ │ │ │ │ │ │ │ └── nullable-objects/ │ │ │ │ │ │ │ │ ├── array-map-named-callback-cross-context.expect.md │ │ │ │ │ │ │ │ ├── array-map-named-callback-cross-context.js │ │ │ │ │ │ │ │ ├── array-map-named-callback.expect.md │ │ │ │ │ │ │ │ ├── array-map-named-callback.js │ │ │ │ │ │ │ │ ├── array-map-named-chained-callbacks.expect.md │ │ │ │ │ │ │ │ ├── array-map-named-chained-callbacks.js │ │ │ │ │ │ │ │ ├── array-map-simple.expect.md │ │ │ │ │ │ │ │ ├── array-map-simple.js │ │ │ │ │ │ │ │ ├── assume-invoked/ │ │ │ │ │ │ │ │ │ ├── conditional-call-chain.expect.md │ │ │ │ │ │ │ │ │ ├── conditional-call-chain.tsx │ │ │ │ │ │ │ │ │ ├── conditional-call.expect.md │ │ │ │ │ │ │ │ │ ├── conditional-call.ts │ │ │ │ │ │ │ │ │ ├── conditionally-return-fn.expect.md │ │ │ │ │ │ │ │ │ ├── conditionally-return-fn.ts │ │ │ │ │ │ │ │ │ ├── direct-call.expect.md │ │ │ │ │ │ │ │ │ ├── direct-call.ts │ │ │ │ │ │ │ │ │ ├── function-with-conditional-callsite-in-another-function.expect.md │ │ │ │ │ │ │ │ │ ├── function-with-conditional-callsite-in-another-function.ts │ │ │ │ │ │ │ │ │ ├── hook-call.expect.md │ │ │ │ │ │ │ │ │ ├── hook-call.ts │ │ │ │ │ │ │ │ │ ├── jsx-and-passed.expect.md │ │ │ │ │ │ │ │ │ ├── jsx-and-passed.ts │ │ │ │ │ │ │ │ │ ├── jsx-function.expect.md │ │ │ │ │ │ │ │ │ ├── jsx-function.tsx │ │ │ │ │ │ │ │ │ ├── return-function.expect.md │ │ │ │ │ │ │ │ │ ├── return-function.ts │ │ │ │ │ │ │ │ │ ├── use-memo-returned.expect.md │ │ │ │ │ │ │ │ │ └── use-memo-returned.ts │ │ │ │ │ │ │ │ ├── bug-invalid-array-map-manual.expect.md │ │ │ │ │ │ │ │ ├── bug-invalid-array-map-manual.js │ │ │ │ │ │ │ │ ├── return-object-of-functions.expect.md │ │ │ │ │ │ │ │ └── return-object-of-functions.js │ │ │ │ │ │ │ ├── inner-memo-value-not-promoted-to-outer-scope-dynamic.expect.md │ │ │ │ │ │ │ ├── inner-memo-value-not-promoted-to-outer-scope-dynamic.js │ │ │ │ │ │ │ ├── inner-memo-value-not-promoted-to-outer-scope-static.expect.md │ │ │ │ │ │ │ ├── inner-memo-value-not-promoted-to-outer-scope-static.js │ │ │ │ │ │ │ ├── interdependent-across-if.expect.md │ │ │ │ │ │ │ ├── interdependent-across-if.js │ │ │ │ │ │ │ ├── interdependent.expect.md │ │ │ │ │ │ │ ├── interdependent.js │ │ │ │ │ │ │ ├── invalid-jsx-in-catch-in-outer-try-with-catch.expect.md │ │ │ │ │ │ │ ├── invalid-jsx-in-catch-in-outer-try-with-catch.js │ │ │ │ │ │ │ ├── invalid-jsx-in-try-with-catch.expect.md │ │ │ │ │ │ │ ├── invalid-jsx-in-try-with-catch.js │ │ │ │ │ │ │ ├── invalid-jsx-lowercase-localvar.expect.md │ │ │ │ │ │ │ ├── invalid-jsx-lowercase-localvar.jsx │ │ │ │ │ │ │ ├── invalid-set-state-in-effect-verbose-derived-event.expect.md │ │ │ │ │ │ │ ├── invalid-set-state-in-effect-verbose-derived-event.js │ │ │ │ │ │ │ ├── invalid-set-state-in-effect-verbose-force-update.expect.md │ │ │ │ │ │ │ ├── invalid-set-state-in-effect-verbose-force-update.js │ │ │ │ │ │ │ ├── invalid-set-state-in-effect-verbose-non-local-derived.expect.md │ │ │ │ │ │ │ ├── invalid-set-state-in-effect-verbose-non-local-derived.js │ │ │ │ │ │ │ ├── invalid-setState-in-useEffect-namespace.expect.md │ │ │ │ │ │ │ ├── invalid-setState-in-useEffect-namespace.js │ │ │ │ │ │ │ ├── invalid-setState-in-useEffect-transitive.expect.md │ │ │ │ │ │ │ ├── invalid-setState-in-useEffect-transitive.js │ │ │ │ │ │ │ ├── invalid-setState-in-useEffect-via-useEffectEvent.expect.md │ │ │ │ │ │ │ ├── invalid-setState-in-useEffect-via-useEffectEvent.js │ │ │ │ │ │ │ ├── invalid-setState-in-useEffect.expect.md │ │ │ │ │ │ │ ├── invalid-setState-in-useEffect.js │ │ │ │ │ │ │ ├── invalid-unused-usememo.expect.md │ │ │ │ │ │ │ ├── invalid-unused-usememo.js │ │ │ │ │ │ │ ├── invalid-useMemo-no-return-value.expect.md │ │ │ │ │ │ │ ├── invalid-useMemo-no-return-value.js │ │ │ │ │ │ │ ├── invalid-useMemo-return-empty.expect.md │ │ │ │ │ │ │ ├── invalid-useMemo-return-empty.js │ │ │ │ │ │ │ ├── inverted-if-else.expect.md │ │ │ │ │ │ │ ├── inverted-if-else.js │ │ │ │ │ │ │ ├── inverted-if.expect.md │ │ │ │ │ │ │ ├── inverted-if.js │ │ │ │ │ │ │ ├── issue852.expect.md │ │ │ │ │ │ │ ├── issue852.js │ │ │ │ │ │ │ ├── issue933-disjoint-set-infinite-loop.expect.md │ │ │ │ │ │ │ ├── issue933-disjoint-set-infinite-loop.js │ │ │ │ │ │ │ ├── jsx-attribute-default-to-true.expect.md │ │ │ │ │ │ │ ├── jsx-attribute-default-to-true.tsx │ │ │ │ │ │ │ ├── jsx-attribute-with-jsx-element-value.expect.md │ │ │ │ │ │ │ ├── jsx-attribute-with-jsx-element-value.js │ │ │ │ │ │ │ ├── jsx-attribute-with-jsx-fragment-value.flow.expect.md │ │ │ │ │ │ │ ├── jsx-attribute-with-jsx-fragment-value.flow.js │ │ │ │ │ │ │ ├── jsx-bracket-in-text.expect.md │ │ │ │ │ │ │ ├── jsx-bracket-in-text.jsx │ │ │ │ │ │ │ ├── jsx-empty-expression.expect.md │ │ │ │ │ │ │ ├── jsx-empty-expression.js │ │ │ │ │ │ │ ├── jsx-fragment.expect.md │ │ │ │ │ │ │ ├── jsx-fragment.js │ │ │ │ │ │ │ ├── jsx-freeze.expect.md │ │ │ │ │ │ │ ├── jsx-freeze.js │ │ │ │ │ │ │ ├── jsx-html-entity.expect.md │ │ │ │ │ │ │ ├── jsx-html-entity.js │ │ │ │ │ │ │ ├── jsx-local-memberexpr-tag-conditional.expect.md │ │ │ │ │ │ │ ├── jsx-local-memberexpr-tag-conditional.js │ │ │ │ │ │ │ ├── jsx-local-memberexpr-tag.expect.md │ │ │ │ │ │ │ ├── jsx-local-memberexpr-tag.js │ │ │ │ │ │ │ ├── jsx-local-tag-in-lambda.expect.md │ │ │ │ │ │ │ ├── jsx-local-tag-in-lambda.js │ │ │ │ │ │ │ ├── jsx-lowercase-localvar-memberexpr-in-lambda.expect.md │ │ │ │ │ │ │ ├── jsx-lowercase-localvar-memberexpr-in-lambda.jsx │ │ │ │ │ │ │ ├── jsx-lowercase-localvar-memberexpr.expect.md │ │ │ │ │ │ │ ├── jsx-lowercase-localvar-memberexpr.jsx │ │ │ │ │ │ │ ├── jsx-lowercase-memberexpr.expect.md │ │ │ │ │ │ │ ├── jsx-lowercase-memberexpr.jsx │ │ │ │ │ │ │ ├── jsx-member-expression-tag-grouping.expect.md │ │ │ │ │ │ │ ├── jsx-member-expression-tag-grouping.js │ │ │ │ │ │ │ ├── jsx-member-expression.expect.md │ │ │ │ │ │ │ ├── jsx-member-expression.js │ │ │ │ │ │ │ ├── jsx-memberexpr-tag-in-lambda.expect.md │ │ │ │ │ │ │ ├── jsx-memberexpr-tag-in-lambda.js │ │ │ │ │ │ │ ├── jsx-namespaced-name.expect.md │ │ │ │ │ │ │ ├── jsx-namespaced-name.js │ │ │ │ │ │ │ ├── jsx-outlining-child-stored-in-id.expect.md │ │ │ │ │ │ │ ├── jsx-outlining-child-stored-in-id.js │ │ │ │ │ │ │ ├── jsx-outlining-dup-key-diff-value.expect.md │ │ │ │ │ │ │ ├── jsx-outlining-dup-key-diff-value.js │ │ │ │ │ │ │ ├── jsx-outlining-dupe-attr-after-rename.expect.md │ │ │ │ │ │ │ ├── jsx-outlining-dupe-attr-after-rename.js │ │ │ │ │ │ │ ├── jsx-outlining-dupe-key-dupe-component.expect.md │ │ │ │ │ │ │ ├── jsx-outlining-dupe-key-dupe-component.js │ │ │ │ │ │ │ ├── jsx-outlining-duplicate-prop.expect.md │ │ │ │ │ │ │ ├── jsx-outlining-duplicate-prop.js │ │ │ │ │ │ │ ├── jsx-outlining-jsx-stored-in-id.expect.md │ │ │ │ │ │ │ ├── jsx-outlining-jsx-stored-in-id.js │ │ │ │ │ │ │ ├── jsx-outlining-separate-nested.expect.md │ │ │ │ │ │ │ ├── jsx-outlining-separate-nested.js │ │ │ │ │ │ │ ├── jsx-outlining-simple.expect.md │ │ │ │ │ │ │ ├── jsx-outlining-simple.js │ │ │ │ │ │ │ ├── jsx-outlining-with-non-jsx-children.expect.md │ │ │ │ │ │ │ ├── jsx-outlining-with-non-jsx-children.js │ │ │ │ │ │ │ ├── jsx-preserve-escape-character.expect.md │ │ │ │ │ │ │ ├── jsx-preserve-escape-character.js │ │ │ │ │ │ │ ├── jsx-preserve-whitespace.expect.md │ │ │ │ │ │ │ ├── jsx-preserve-whitespace.tsx │ │ │ │ │ │ │ ├── jsx-reactive-local-variable-member-expr.expect.md │ │ │ │ │ │ │ ├── jsx-reactive-local-variable-member-expr.tsx │ │ │ │ │ │ │ ├── jsx-spread.expect.md │ │ │ │ │ │ │ ├── jsx-spread.js │ │ │ │ │ │ │ ├── jsx-string-attribute-expression-container.expect.md │ │ │ │ │ │ │ ├── jsx-string-attribute-expression-container.js │ │ │ │ │ │ │ ├── jsx-string-attribute-non-ascii.expect.md │ │ │ │ │ │ │ ├── jsx-string-attribute-non-ascii.js │ │ │ │ │ │ │ ├── jsx-tag-evaluation-order-non-global.expect.md │ │ │ │ │ │ │ ├── jsx-tag-evaluation-order-non-global.js │ │ │ │ │ │ │ ├── jsx-tag-evaluation-order.expect.md │ │ │ │ │ │ │ ├── jsx-tag-evaluation-order.tsx │ │ │ │ │ │ │ ├── jsx-ternary-local-variable.expect.md │ │ │ │ │ │ │ ├── jsx-ternary-local-variable.tsx │ │ │ │ │ │ │ ├── labeled-break-within-label-loop.expect.md │ │ │ │ │ │ │ ├── labeled-break-within-label-loop.ts │ │ │ │ │ │ │ ├── labeled-break-within-label-switch.expect.md │ │ │ │ │ │ │ ├── labeled-break-within-label-switch.ts │ │ │ │ │ │ │ ├── lambda-array-access-member-expr-captured.expect.md │ │ │ │ │ │ │ ├── lambda-array-access-member-expr-captured.ts │ │ │ │ │ │ │ ├── lambda-array-access-member-expr-param.expect.md │ │ │ │ │ │ │ ├── lambda-array-access-member-expr-param.ts │ │ │ │ │ │ │ ├── lambda-capture-returned-alias.expect.md │ │ │ │ │ │ │ ├── lambda-capture-returned-alias.js │ │ │ │ │ │ │ ├── lambda-mutate-shadowed-object.expect.md │ │ │ │ │ │ │ ├── lambda-mutate-shadowed-object.js │ │ │ │ │ │ │ ├── lambda-mutated-non-reactive-to-reactive.expect.md │ │ │ │ │ │ │ ├── lambda-mutated-non-reactive-to-reactive.js │ │ │ │ │ │ │ ├── lambda-mutated-ref-non-reactive.expect.md │ │ │ │ │ │ │ ├── lambda-mutated-ref-non-reactive.js │ │ │ │ │ │ │ ├── lambda-reassign-primitive.expect.md │ │ │ │ │ │ │ ├── lambda-reassign-primitive.js │ │ │ │ │ │ │ ├── lambda-reassign-shadowed-primitive.expect.md │ │ │ │ │ │ │ ├── lambda-reassign-shadowed-primitive.js │ │ │ │ │ │ │ ├── lambda-return-expression.expect.md │ │ │ │ │ │ │ ├── lambda-return-expression.ts │ │ │ │ │ │ │ ├── log-pruned-memoization.expect.md │ │ │ │ │ │ │ ├── log-pruned-memoization.js │ │ │ │ │ │ │ ├── logical-expression-object.expect.md │ │ │ │ │ │ │ ├── logical-expression-object.js │ │ │ │ │ │ │ ├── logical-expression.expect.md │ │ │ │ │ │ │ ├── logical-expression.js │ │ │ │ │ │ │ ├── logical-reorder.flow.expect.md │ │ │ │ │ │ │ ├── logical-reorder.flow.js │ │ │ │ │ │ │ ├── loop-unused-let.expect.md │ │ │ │ │ │ │ ├── loop-unused-let.js │ │ │ │ │ │ │ ├── maybe-mutate-object-in-callback.expect.md │ │ │ │ │ │ │ ├── maybe-mutate-object-in-callback.js │ │ │ │ │ │ │ ├── mege-consecutive-scopes-dont-merge-with-different-deps.expect.md │ │ │ │ │ │ │ ├── mege-consecutive-scopes-dont-merge-with-different-deps.js │ │ │ │ │ │ │ ├── member-inc.expect.md │ │ │ │ │ │ │ ├── member-inc.js │ │ │ │ │ │ │ ├── memoize-primitive-function-calls.expect.md │ │ │ │ │ │ │ ├── memoize-primitive-function-calls.js │ │ │ │ │ │ │ ├── memoize-value-block-value-conditional.expect.md │ │ │ │ │ │ │ ├── memoize-value-block-value-conditional.js │ │ │ │ │ │ │ ├── memoize-value-block-value-logical-no-sequence.expect.md │ │ │ │ │ │ │ ├── memoize-value-block-value-logical-no-sequence.js │ │ │ │ │ │ │ ├── memoize-value-block-value-logical.expect.md │ │ │ │ │ │ │ ├── memoize-value-block-value-logical.js │ │ │ │ │ │ │ ├── memoize-value-block-value-sequence.expect.md │ │ │ │ │ │ │ ├── memoize-value-block-value-sequence.js │ │ │ │ │ │ │ ├── merge-consecutive-nested-scopes.expect.md │ │ │ │ │ │ │ ├── merge-consecutive-nested-scopes.js │ │ │ │ │ │ │ ├── merge-consecutive-scopes-deps-subset-of-decls.expect.md │ │ │ │ │ │ │ ├── merge-consecutive-scopes-deps-subset-of-decls.js │ │ │ │ │ │ │ ├── merge-consecutive-scopes-no-deps.expect.md │ │ │ │ │ │ │ ├── merge-consecutive-scopes-no-deps.js │ │ │ │ │ │ │ ├── merge-consecutive-scopes-objects.expect.md │ │ │ │ │ │ │ ├── merge-consecutive-scopes-objects.js │ │ │ │ │ │ │ ├── merge-consecutive-scopes.expect.md │ │ │ │ │ │ │ ├── merge-consecutive-scopes.js │ │ │ │ │ │ │ ├── merge-nested-scopes-with-same-inputs.expect.md │ │ │ │ │ │ │ ├── merge-nested-scopes-with-same-inputs.js │ │ │ │ │ │ │ ├── meta-isms/ │ │ │ │ │ │ │ │ ├── repro-cx-assigned-to-temporary.expect.md │ │ │ │ │ │ │ │ ├── repro-cx-assigned-to-temporary.js │ │ │ │ │ │ │ │ ├── repro-cx-namespace-assigned-to-temporary.expect.md │ │ │ │ │ │ │ │ ├── repro-cx-namespace-assigned-to-temporary.js │ │ │ │ │ │ │ │ ├── repro-cx-namespace-nesting.expect.md │ │ │ │ │ │ │ │ └── repro-cx-namespace-nesting.js │ │ │ │ │ │ │ ├── meta-property.expect.md │ │ │ │ │ │ │ ├── meta-property.mjs │ │ │ │ │ │ │ ├── method-call-computed.expect.md │ │ │ │ │ │ │ ├── method-call-computed.js │ │ │ │ │ │ │ ├── method-call-fn-call.expect.md │ │ │ │ │ │ │ ├── method-call-fn-call.js │ │ │ │ │ │ │ ├── method-call.expect.md │ │ │ │ │ │ │ ├── method-call.js │ │ │ │ │ │ │ ├── mixedreadonly-mutating-map.expect.md │ │ │ │ │ │ │ ├── mixedreadonly-mutating-map.js │ │ │ │ │ │ │ ├── module-scoped-bindings.expect.md │ │ │ │ │ │ │ ├── module-scoped-bindings.js │ │ │ │ │ │ │ ├── multi-directive.expect.md │ │ │ │ │ │ │ ├── multi-directive.js │ │ │ │ │ │ │ ├── multiple-calls-to-hoisted-callback-from-other-callback.expect.md │ │ │ │ │ │ │ ├── multiple-calls-to-hoisted-callback-from-other-callback.js │ │ │ │ │ │ │ ├── multiple-components-first-is-invalid.expect.md │ │ │ │ │ │ │ ├── multiple-components-first-is-invalid.js │ │ │ │ │ │ │ ├── mutable-lifetime-loops.expect.md │ │ │ │ │ │ │ ├── mutable-lifetime-loops.js │ │ │ │ │ │ │ ├── mutable-lifetime-with-aliasing.expect.md │ │ │ │ │ │ │ ├── mutable-lifetime-with-aliasing.js │ │ │ │ │ │ │ ├── mutable-liverange-loop.expect.md │ │ │ │ │ │ │ ├── mutable-liverange-loop.js │ │ │ │ │ │ │ ├── mutate-captured-arg-separately.expect.md │ │ │ │ │ │ │ ├── mutate-captured-arg-separately.js │ │ │ │ │ │ │ ├── mutate-outer-scope-within-value-block.expect.md │ │ │ │ │ │ │ ├── mutate-outer-scope-within-value-block.ts │ │ │ │ │ │ │ ├── mutation-during-jsx-construction.expect.md │ │ │ │ │ │ │ ├── mutation-during-jsx-construction.js │ │ │ │ │ │ │ ├── mutation-within-capture-and-mutablerange.expect.md │ │ │ │ │ │ │ ├── mutation-within-capture-and-mutablerange.tsx │ │ │ │ │ │ │ ├── mutation-within-jsx-and-break.expect.md │ │ │ │ │ │ │ ├── mutation-within-jsx-and-break.tsx │ │ │ │ │ │ │ ├── mutation-within-jsx.expect.md │ │ │ │ │ │ │ ├── mutation-within-jsx.tsx │ │ │ │ │ │ │ ├── name-anonymous-functions-outline.expect.md │ │ │ │ │ │ │ ├── name-anonymous-functions-outline.js │ │ │ │ │ │ │ ├── name-anonymous-functions.expect.md │ │ │ │ │ │ │ ├── name-anonymous-functions.js │ │ │ │ │ │ │ ├── nested-function-shadowed-identifiers.expect.md │ │ │ │ │ │ │ ├── nested-function-shadowed-identifiers.js │ │ │ │ │ │ │ ├── nested-function-with-param-as-captured-dep.expect.md │ │ │ │ │ │ │ ├── nested-function-with-param-as-captured-dep.ts │ │ │ │ │ │ │ ├── nested-optional-chains.expect.md │ │ │ │ │ │ │ ├── nested-optional-chains.ts │ │ │ │ │ │ │ ├── nested-optional-member-expr.expect.md │ │ │ │ │ │ │ ├── nested-optional-member-expr.js │ │ │ │ │ │ │ ├── nested-scopes-begin-same-instr-valueblock.expect.md │ │ │ │ │ │ │ ├── nested-scopes-begin-same-instr-valueblock.ts │ │ │ │ │ │ │ ├── nested-scopes-hook-call.expect.md │ │ │ │ │ │ │ ├── nested-scopes-hook-call.js │ │ │ │ │ │ │ ├── new-does-not-mutate-class.expect.md │ │ │ │ │ │ │ ├── new-does-not-mutate-class.ts │ │ │ │ │ │ │ ├── new-mutability/ │ │ │ │ │ │ │ │ ├── aliased-nested-scope-truncated-dep.expect.md │ │ │ │ │ │ │ │ ├── aliased-nested-scope-truncated-dep.tsx │ │ │ │ │ │ │ │ ├── array-filter.expect.md │ │ │ │ │ │ │ │ ├── array-filter.js │ │ │ │ │ │ │ │ ├── array-map-captures-receiver-noAlias.expect.md │ │ │ │ │ │ │ │ ├── array-map-captures-receiver-noAlias.js │ │ │ │ │ │ │ │ ├── array-map-named-callback-cross-context.expect.md │ │ │ │ │ │ │ │ ├── array-map-named-callback-cross-context.js │ │ │ │ │ │ │ │ ├── array-push.expect.md │ │ │ │ │ │ │ │ ├── array-push.js │ │ │ │ │ │ │ │ ├── basic-mutation-via-function-expression.expect.md │ │ │ │ │ │ │ │ ├── basic-mutation-via-function-expression.js │ │ │ │ │ │ │ │ ├── basic-mutation.expect.md │ │ │ │ │ │ │ │ ├── basic-mutation.js │ │ │ │ │ │ │ │ ├── capture-backedge-phi-with-later-mutation.expect.md │ │ │ │ │ │ │ │ ├── capture-backedge-phi-with-later-mutation.js │ │ │ │ │ │ │ │ ├── capture-in-function-expression-indirect.expect.md │ │ │ │ │ │ │ │ ├── capture-in-function-expression-indirect.js │ │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-2-iife.expect.md │ │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-2-iife.js │ │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-3-iife.expect.md │ │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-3-iife.js │ │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-4-iife.expect.md │ │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-4-iife.js │ │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-iife.expect.md │ │ │ │ │ │ │ │ ├── capturing-function-alias-computed-load-iife.js │ │ │ │ │ │ │ │ ├── error.invalid-impure-functions-in-render.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-impure-functions-in-render.js │ │ │ │ │ │ │ │ ├── error.invalid-reassign-local-variable-in-jsx-callback.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-reassign-local-variable-in-jsx-callback.js │ │ │ │ │ │ │ │ ├── error.invalid-referencing-frozen-hoisted-storecontext-const.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-referencing-frozen-hoisted-storecontext-const.js │ │ │ │ │ │ │ │ ├── error.invalid-useCallback-captures-reassigned-context.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-useCallback-captures-reassigned-context.js │ │ │ │ │ │ │ │ ├── error.mutate-frozen-value.expect.md │ │ │ │ │ │ │ │ ├── error.mutate-frozen-value.js │ │ │ │ │ │ │ │ ├── error.mutate-hook-argument.expect.md │ │ │ │ │ │ │ │ ├── error.mutate-hook-argument.js │ │ │ │ │ │ │ │ ├── error.not-useEffect-external-mutate.expect.md │ │ │ │ │ │ │ │ ├── error.not-useEffect-external-mutate.js │ │ │ │ │ │ │ │ ├── error.reassignment-to-global-indirect.expect.md │ │ │ │ │ │ │ │ ├── error.reassignment-to-global-indirect.js │ │ │ │ │ │ │ │ ├── error.reassignment-to-global.expect.md │ │ │ │ │ │ │ │ ├── error.reassignment-to-global.js │ │ │ │ │ │ │ │ ├── error.todo-repro-named-function-with-shadowed-local-same-name.expect.md │ │ │ │ │ │ │ │ ├── error.todo-repro-named-function-with-shadowed-local-same-name.js │ │ │ │ │ │ │ │ ├── iife-return-modified-later-phi.expect.md │ │ │ │ │ │ │ │ ├── iife-return-modified-later-phi.js │ │ │ │ │ │ │ │ ├── mutate-through-boxing-unboxing-function-call-indirections-2.expect.md │ │ │ │ │ │ │ │ ├── mutate-through-boxing-unboxing-function-call-indirections-2.js │ │ │ │ │ │ │ │ ├── mutate-through-boxing-unboxing-function-call-indirections.expect.md │ │ │ │ │ │ │ │ ├── mutate-through-boxing-unboxing-function-call-indirections.js │ │ │ │ │ │ │ │ ├── mutate-through-boxing-unboxing-indirections.expect.md │ │ │ │ │ │ │ │ ├── mutate-through-boxing-unboxing-indirections.js │ │ │ │ │ │ │ │ ├── mutate-through-identity-function-expression.expect.md │ │ │ │ │ │ │ │ ├── mutate-through-identity-function-expression.js │ │ │ │ │ │ │ │ ├── mutate-through-identity.expect.md │ │ │ │ │ │ │ │ ├── mutate-through-identity.js │ │ │ │ │ │ │ │ ├── mutate-through-propertyload.expect.md │ │ │ │ │ │ │ │ ├── mutate-through-propertyload.js │ │ │ │ │ │ │ │ ├── nullable-objects-assume-invoked-direct-call.expect.md │ │ │ │ │ │ │ │ ├── nullable-objects-assume-invoked-direct-call.js │ │ │ │ │ │ │ │ ├── object-expression-computed-key-object-mutated-later.expect.md │ │ │ │ │ │ │ │ ├── object-expression-computed-key-object-mutated-later.js │ │ │ │ │ │ │ │ ├── object-expression-computed-member.expect.md │ │ │ │ │ │ │ │ ├── object-expression-computed-member.js │ │ │ │ │ │ │ │ ├── potential-mutation-in-function-expression.expect.md │ │ │ │ │ │ │ │ ├── potential-mutation-in-function-expression.js │ │ │ │ │ │ │ │ ├── reactive-ref.expect.md │ │ │ │ │ │ │ │ ├── reactive-ref.js │ │ │ │ │ │ │ │ ├── repro-compiler-infinite-loop.expect.md │ │ │ │ │ │ │ │ ├── repro-compiler-infinite-loop.js │ │ │ │ │ │ │ │ ├── repro-destructure-from-prop-with-default-value.expect.md │ │ │ │ │ │ │ │ ├── repro-destructure-from-prop-with-default-value.js │ │ │ │ │ │ │ │ ├── repro-function-expression-effects-stack-overflow.expect.md │ │ │ │ │ │ │ │ ├── repro-function-expression-effects-stack-overflow.js │ │ │ │ │ │ │ │ ├── repro-internal-compiler-shared-mutablerange-bug.expect.md │ │ │ │ │ │ │ │ ├── repro-internal-compiler-shared-mutablerange-bug.js │ │ │ │ │ │ │ │ ├── repro-invalid-function-expression-effects-phi.expect.md │ │ │ │ │ │ │ │ ├── repro-invalid-function-expression-effects-phi.js │ │ │ │ │ │ │ │ ├── repro-jsx-captures-value-mutated-later.expect.md │ │ │ │ │ │ │ │ ├── repro-jsx-captures-value-mutated-later.js │ │ │ │ │ │ │ │ ├── repro-mutate-new-set-of-frozen-items-in-callback.expect.md │ │ │ │ │ │ │ │ ├── repro-mutate-new-set-of-frozen-items-in-callback.js │ │ │ │ │ │ │ │ ├── set-add-mutate.expect.md │ │ │ │ │ │ │ │ ├── set-add-mutate.js │ │ │ │ │ │ │ │ ├── ssa-renaming-ternary-destruction.expect.md │ │ │ │ │ │ │ │ ├── ssa-renaming-ternary-destruction.js │ │ │ │ │ │ │ │ ├── todo-control-flow-sensitive-mutation.expect.md │ │ │ │ │ │ │ │ ├── todo-control-flow-sensitive-mutation.tsx │ │ │ │ │ │ │ │ ├── todo-transitivity-createfrom-capture-lambda.expect.md │ │ │ │ │ │ │ │ ├── todo-transitivity-createfrom-capture-lambda.tsx │ │ │ │ │ │ │ │ ├── transitive-mutation-before-capturing-value-created-earlier.expect.md │ │ │ │ │ │ │ │ ├── transitive-mutation-before-capturing-value-created-earlier.js │ │ │ │ │ │ │ │ ├── transitivity-add-captured-array-to-itself.expect.md │ │ │ │ │ │ │ │ ├── transitivity-add-captured-array-to-itself.tsx │ │ │ │ │ │ │ │ ├── transitivity-capture-createfrom-lambda.expect.md │ │ │ │ │ │ │ │ ├── transitivity-capture-createfrom-lambda.tsx │ │ │ │ │ │ │ │ ├── transitivity-capture-createfrom.expect.md │ │ │ │ │ │ │ │ ├── transitivity-capture-createfrom.tsx │ │ │ │ │ │ │ │ ├── transitivity-createfrom-capture.expect.md │ │ │ │ │ │ │ │ ├── transitivity-createfrom-capture.tsx │ │ │ │ │ │ │ │ ├── transitivity-phi-assign-or-capture.expect.md │ │ │ │ │ │ │ │ ├── transitivity-phi-assign-or-capture.tsx │ │ │ │ │ │ │ │ ├── typed-identity-function-frozen-input.expect.md │ │ │ │ │ │ │ │ ├── typed-identity-function-frozen-input.js │ │ │ │ │ │ │ │ ├── typed-identity-function-mutable-input.expect.md │ │ │ │ │ │ │ │ ├── typed-identity-function-mutable-input.js │ │ │ │ │ │ │ │ ├── useCallback-reordering-deplist-controlflow.expect.md │ │ │ │ │ │ │ │ ├── useCallback-reordering-deplist-controlflow.tsx │ │ │ │ │ │ │ │ ├── useCallback-reordering-depslist-assignment.expect.md │ │ │ │ │ │ │ │ ├── useCallback-reordering-depslist-assignment.tsx │ │ │ │ │ │ │ │ ├── useMemo-reordering-depslist-assignment.expect.md │ │ │ │ │ │ │ │ └── useMemo-reordering-depslist-assignment.ts │ │ │ │ │ │ │ ├── new-spread.expect.md │ │ │ │ │ │ │ ├── new-spread.js │ │ │ │ │ │ │ ├── no-flow-bailout-unrelated.expect.md │ │ │ │ │ │ │ ├── no-flow-bailout-unrelated.js │ │ │ │ │ │ │ ├── noAlias-filter-on-array-prop.expect.md │ │ │ │ │ │ │ ├── noAlias-filter-on-array-prop.js │ │ │ │ │ │ │ ├── non-null-assertion.expect.md │ │ │ │ │ │ │ ├── non-null-assertion.ts │ │ │ │ │ │ │ ├── nonmutated-spread-hook-return.expect.md │ │ │ │ │ │ │ ├── nonmutated-spread-hook-return.js │ │ │ │ │ │ │ ├── nonmutated-spread-props-jsx.expect.md │ │ │ │ │ │ │ ├── nonmutated-spread-props-jsx.js │ │ │ │ │ │ │ ├── nonmutated-spread-props-local-indirection.expect.md │ │ │ │ │ │ │ ├── nonmutated-spread-props-local-indirection.js │ │ │ │ │ │ │ ├── nonmutated-spread-props.expect.md │ │ │ │ │ │ │ ├── nonmutated-spread-props.js │ │ │ │ │ │ │ ├── nonmutating-capture-in-unsplittable-memo-block.expect.md │ │ │ │ │ │ │ ├── nonmutating-capture-in-unsplittable-memo-block.ts │ │ │ │ │ │ │ ├── nonoptional-load-from-optional-memberexpr.expect.md │ │ │ │ │ │ │ ├── nonoptional-load-from-optional-memberexpr.js │ │ │ │ │ │ │ ├── nonreactive-noescaping-dependency-can-inline-into-consuming-scope.expect.md │ │ │ │ │ │ │ ├── nonreactive-noescaping-dependency-can-inline-into-consuming-scope.js │ │ │ │ │ │ │ ├── numeric-literal-as-object-property-key.expect.md │ │ │ │ │ │ │ ├── numeric-literal-as-object-property-key.js │ │ │ │ │ │ │ ├── obj-literal-cached-in-if-else.expect.md │ │ │ │ │ │ │ ├── obj-literal-cached-in-if-else.js │ │ │ │ │ │ │ ├── obj-literal-mutated-after-if-else.expect.md │ │ │ │ │ │ │ ├── obj-literal-mutated-after-if-else.js │ │ │ │ │ │ │ ├── obj-mutated-after-if-else-with-alias.expect.md │ │ │ │ │ │ │ ├── obj-mutated-after-if-else-with-alias.js │ │ │ │ │ │ │ ├── obj-mutated-after-if-else.expect.md │ │ │ │ │ │ │ ├── obj-mutated-after-if-else.js │ │ │ │ │ │ │ ├── obj-mutated-after-nested-if-else-with-alias.expect.md │ │ │ │ │ │ │ ├── obj-mutated-after-nested-if-else-with-alias.js │ │ │ │ │ │ │ ├── object-access-assignment.expect.md │ │ │ │ │ │ │ ├── object-access-assignment.js │ │ │ │ │ │ │ ├── object-computed-access-assignment.expect.md │ │ │ │ │ │ │ ├── object-computed-access-assignment.js │ │ │ │ │ │ │ ├── object-entries-mutation.expect.md │ │ │ │ │ │ │ ├── object-entries-mutation.js │ │ │ │ │ │ │ ├── object-expression-captures-function-with-global-mutation.expect.md │ │ │ │ │ │ │ ├── object-expression-captures-function-with-global-mutation.js │ │ │ │ │ │ │ ├── object-expression-computed-key-constant-number.expect.md │ │ │ │ │ │ │ ├── object-expression-computed-key-constant-number.js │ │ │ │ │ │ │ ├── object-expression-computed-key-constant-string.expect.md │ │ │ │ │ │ │ ├── object-expression-computed-key-constant-string.js │ │ │ │ │ │ │ ├── object-expression-computed-key-modified-during-after-construction-sequence-expr.expect.md │ │ │ │ │ │ │ ├── object-expression-computed-key-modified-during-after-construction-sequence-expr.js │ │ │ │ │ │ │ ├── object-expression-computed-key-modified-during-after-construction.expect.md │ │ │ │ │ │ │ ├── object-expression-computed-key-modified-during-after-construction.js │ │ │ │ │ │ │ ├── object-expression-computed-key-mutate-key-while-constructing-object.expect.md │ │ │ │ │ │ │ ├── object-expression-computed-key-mutate-key-while-constructing-object.js │ │ │ │ │ │ │ ├── object-expression-computed-key-non-reactive.expect.md │ │ │ │ │ │ │ ├── object-expression-computed-key-non-reactive.js │ │ │ │ │ │ │ ├── object-expression-computed-key-object-mutated-later.expect.md │ │ │ │ │ │ │ ├── object-expression-computed-key-object-mutated-later.js │ │ │ │ │ │ │ ├── object-expression-computed-key.expect.md │ │ │ │ │ │ │ ├── object-expression-computed-key.js │ │ │ │ │ │ │ ├── object-expression-computed-member.expect.md │ │ │ │ │ │ │ ├── object-expression-computed-member.js │ │ │ │ │ │ │ ├── object-expression-member-expr-call.expect.md │ │ │ │ │ │ │ ├── object-expression-member-expr-call.js │ │ │ │ │ │ │ ├── object-expression-string-literal-key.expect.md │ │ │ │ │ │ │ ├── object-expression-string-literal-key.js │ │ │ │ │ │ │ ├── object-keys.expect.md │ │ │ │ │ │ │ ├── object-keys.js │ │ │ │ │ │ │ ├── object-literal-method-call-in-ternary-test.expect.md │ │ │ │ │ │ │ ├── object-literal-method-call-in-ternary-test.js │ │ │ │ │ │ │ ├── object-literal-method-derived-in-ternary-consequent.expect.md │ │ │ │ │ │ │ ├── object-literal-method-derived-in-ternary-consequent.js │ │ │ │ │ │ │ ├── object-literal-method-in-ternary-consequent.expect.md │ │ │ │ │ │ │ ├── object-literal-method-in-ternary-consequent.js │ │ │ │ │ │ │ ├── object-literal-method-in-ternary-test.expect.md │ │ │ │ │ │ │ ├── object-literal-method-in-ternary-test.js │ │ │ │ │ │ │ ├── object-literal-spread-element.expect.md │ │ │ │ │ │ │ ├── object-literal-spread-element.js │ │ │ │ │ │ │ ├── object-method-maybe-alias.expect.md │ │ │ │ │ │ │ ├── object-method-maybe-alias.js │ │ │ │ │ │ │ ├── object-method-shorthand-3.expect.md │ │ │ │ │ │ │ ├── object-method-shorthand-3.js │ │ │ │ │ │ │ ├── object-method-shorthand-aliased-mutate-after.expect.md │ │ │ │ │ │ │ ├── object-method-shorthand-aliased-mutate-after.js │ │ │ │ │ │ │ ├── object-method-shorthand-derived-value.expect.md │ │ │ │ │ │ │ ├── object-method-shorthand-derived-value.js │ │ │ │ │ │ │ ├── object-method-shorthand-hook-dep.expect.md │ │ │ │ │ │ │ ├── object-method-shorthand-hook-dep.js │ │ │ │ │ │ │ ├── object-method-shorthand-mutated-after.expect.md │ │ │ │ │ │ │ ├── object-method-shorthand-mutated-after.js │ │ │ │ │ │ │ ├── object-method-shorthand.expect.md │ │ │ │ │ │ │ ├── object-method-shorthand.js │ │ │ │ │ │ │ ├── object-mutated-in-consequent-alternate-both-return.expect.md │ │ │ │ │ │ │ ├── object-mutated-in-consequent-alternate-both-return.js │ │ │ │ │ │ │ ├── object-pattern-params.expect.md │ │ │ │ │ │ │ ├── object-pattern-params.js │ │ │ │ │ │ │ ├── object-properties.expect.md │ │ │ │ │ │ │ ├── object-properties.js │ │ │ │ │ │ │ ├── object-shorthand-method-1.expect.md │ │ │ │ │ │ │ ├── object-shorthand-method-1.js │ │ │ │ │ │ │ ├── object-shorthand-method-2.expect.md │ │ │ │ │ │ │ ├── object-shorthand-method-2.js │ │ │ │ │ │ │ ├── object-shorthand-method-nested.expect.md │ │ │ │ │ │ │ ├── object-shorthand-method-nested.js │ │ │ │ │ │ │ ├── object-values-mutation.expect.md │ │ │ │ │ │ │ ├── object-values-mutation.js │ │ │ │ │ │ │ ├── object-values.expect.md │ │ │ │ │ │ │ ├── object-values.js │ │ │ │ │ │ │ ├── optional-call-chain-in-logical-expr.expect.md │ │ │ │ │ │ │ ├── optional-call-chain-in-logical-expr.ts │ │ │ │ │ │ │ ├── optional-call-chain-in-ternary.expect.md │ │ │ │ │ │ │ ├── optional-call-chain-in-ternary.ts │ │ │ │ │ │ │ ├── optional-call-chained.expect.md │ │ │ │ │ │ │ ├── optional-call-chained.js │ │ │ │ │ │ │ ├── optional-call-logical.expect.md │ │ │ │ │ │ │ ├── optional-call-logical.js │ │ │ │ │ │ │ ├── optional-call-simple.expect.md │ │ │ │ │ │ │ ├── optional-call-simple.js │ │ │ │ │ │ │ ├── optional-call-with-independently-memoizable-arg.expect.md │ │ │ │ │ │ │ ├── optional-call-with-independently-memoizable-arg.js │ │ │ │ │ │ │ ├── optional-call-with-optional-property-load.expect.md │ │ │ │ │ │ │ ├── optional-call-with-optional-property-load.js │ │ │ │ │ │ │ ├── optional-call.expect.md │ │ │ │ │ │ │ ├── optional-call.js │ │ │ │ │ │ │ ├── optional-computed-load-static.expect.md │ │ │ │ │ │ │ ├── optional-computed-load-static.js │ │ │ │ │ │ │ ├── optional-computed-member-expression.expect.md │ │ │ │ │ │ │ ├── optional-computed-member-expression.js │ │ │ │ │ │ │ ├── optional-member-expression-as-memo-dep.expect.md │ │ │ │ │ │ │ ├── optional-member-expression-as-memo-dep.js │ │ │ │ │ │ │ ├── optional-member-expression-call-as-property.expect.md │ │ │ │ │ │ │ ├── optional-member-expression-call-as-property.js │ │ │ │ │ │ │ ├── optional-member-expression-chain.expect.md │ │ │ │ │ │ │ ├── optional-member-expression-chain.js │ │ │ │ │ │ │ ├── optional-member-expression-inverted-optionals-parallel-paths.expect.md │ │ │ │ │ │ │ ├── optional-member-expression-inverted-optionals-parallel-paths.js │ │ │ │ │ │ │ ├── optional-member-expression-single-with-unconditional.expect.md │ │ │ │ │ │ │ ├── optional-member-expression-single-with-unconditional.js │ │ │ │ │ │ │ ├── optional-member-expression-single.expect.md │ │ │ │ │ │ │ ├── optional-member-expression-single.js │ │ │ │ │ │ │ ├── optional-member-expression-with-optional-member-expr-as-property.expect.md │ │ │ │ │ │ │ ├── optional-member-expression-with-optional-member-expr-as-property.js │ │ │ │ │ │ │ ├── optional-member-expression.expect.md │ │ │ │ │ │ │ ├── optional-member-expression.js │ │ │ │ │ │ │ ├── optional-method-call.expect.md │ │ │ │ │ │ │ ├── optional-method-call.js │ │ │ │ │ │ │ ├── optional-receiver-method-call.expect.md │ │ │ │ │ │ │ ├── optional-receiver-method-call.js │ │ │ │ │ │ │ ├── optional-receiver-optional-method.expect.md │ │ │ │ │ │ │ ├── optional-receiver-optional-method.js │ │ │ │ │ │ │ ├── original-reactive-scopes-fork/ │ │ │ │ │ │ │ │ ├── capture-ref-for-later-mutation.expect.md │ │ │ │ │ │ │ │ └── capture-ref-for-later-mutation.tsx │ │ │ │ │ │ │ ├── outlined-destructured-params.expect.md │ │ │ │ │ │ │ ├── outlined-destructured-params.js │ │ │ │ │ │ │ ├── outlined-helper.expect.md │ │ │ │ │ │ │ ├── outlined-helper.js │ │ │ │ │ │ │ ├── outlining-in-func-expr.expect.md │ │ │ │ │ │ │ ├── outlining-in-func-expr.js │ │ │ │ │ │ │ ├── outlining-in-react-memo.expect.md │ │ │ │ │ │ │ ├── outlining-in-react-memo.js │ │ │ │ │ │ │ ├── overlapping-scopes-interleaved-by-terminal.expect.md │ │ │ │ │ │ │ ├── overlapping-scopes-interleaved-by-terminal.js │ │ │ │ │ │ │ ├── overlapping-scopes-interleaved.expect.md │ │ │ │ │ │ │ ├── overlapping-scopes-interleaved.js │ │ │ │ │ │ │ ├── overlapping-scopes-shadowed.expect.md │ │ │ │ │ │ │ ├── overlapping-scopes-shadowed.js │ │ │ │ │ │ │ ├── overlapping-scopes-shadowing-within-block.expect.md │ │ │ │ │ │ │ ├── overlapping-scopes-shadowing-within-block.js │ │ │ │ │ │ │ ├── overlapping-scopes-while.expect.md │ │ │ │ │ │ │ ├── overlapping-scopes-while.js │ │ │ │ │ │ │ ├── overlapping-scopes-within-block.expect.md │ │ │ │ │ │ │ ├── overlapping-scopes-within-block.js │ │ │ │ │ │ │ ├── panresponder-ref-in-callback.expect.md │ │ │ │ │ │ │ ├── panresponder-ref-in-callback.js │ │ │ │ │ │ │ ├── partial-early-return-within-reactive-scope.expect.md │ │ │ │ │ │ │ ├── partial-early-return-within-reactive-scope.js │ │ │ │ │ │ │ ├── phi-reference-effects.expect.md │ │ │ │ │ │ │ ├── phi-reference-effects.ts │ │ │ │ │ │ │ ├── phi-type-inference-array-push-consecutive-phis.expect.md │ │ │ │ │ │ │ ├── phi-type-inference-array-push-consecutive-phis.js │ │ │ │ │ │ │ ├── phi-type-inference-array-push.expect.md │ │ │ │ │ │ │ ├── phi-type-inference-array-push.js │ │ │ │ │ │ │ ├── phi-type-inference-property-store.expect.md │ │ │ │ │ │ │ ├── phi-type-inference-property-store.js │ │ │ │ │ │ │ ├── preserve-existing-memoization-guarantees/ │ │ │ │ │ │ │ │ ├── lambda-with-fbt-preserve-memoization.expect.md │ │ │ │ │ │ │ │ └── lambda-with-fbt-preserve-memoization.js │ │ │ │ │ │ │ ├── preserve-jsxtext-stringliteral-distinction.expect.md │ │ │ │ │ │ │ ├── preserve-jsxtext-stringliteral-distinction.js │ │ │ │ │ │ │ ├── preserve-memo-deps-conditional-property-chain-less-precise-deps.expect.md │ │ │ │ │ │ │ ├── preserve-memo-deps-conditional-property-chain-less-precise-deps.js │ │ │ │ │ │ │ ├── preserve-memo-deps-conditional-property-chain.expect.md │ │ │ │ │ │ │ ├── preserve-memo-deps-conditional-property-chain.js │ │ │ │ │ │ │ ├── preserve-memo-deps-optional-property-chain.expect.md │ │ │ │ │ │ │ ├── preserve-memo-deps-optional-property-chain.js │ │ │ │ │ │ │ ├── preserve-memo-validation/ │ │ │ │ │ │ │ │ ├── error.false-positive-useMemo-dropped-infer-always-invalidating.expect.md │ │ │ │ │ │ │ │ ├── error.false-positive-useMemo-dropped-infer-always-invalidating.ts │ │ │ │ │ │ │ │ ├── error.false-positive-useMemo-infer-mutate-deps.expect.md │ │ │ │ │ │ │ │ ├── error.false-positive-useMemo-infer-mutate-deps.ts │ │ │ │ │ │ │ │ ├── error.false-positive-useMemo-overlap-scopes.expect.md │ │ │ │ │ │ │ │ ├── error.false-positive-useMemo-overlap-scopes.ts │ │ │ │ │ │ │ │ ├── error.hoist-useCallback-conditional-access-own-scope.expect.md │ │ │ │ │ │ │ │ ├── error.hoist-useCallback-conditional-access-own-scope.ts │ │ │ │ │ │ │ │ ├── error.hoist-useCallback-infer-conditional-value-block.expect.md │ │ │ │ │ │ │ │ ├── error.hoist-useCallback-infer-conditional-value-block.ts │ │ │ │ │ │ │ │ ├── error.invalid-useCallback-captures-reassigned-context.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-useCallback-captures-reassigned-context.ts │ │ │ │ │ │ │ │ ├── error.maybe-mutable-ref-not-preserved.expect.md │ │ │ │ │ │ │ │ ├── error.maybe-mutable-ref-not-preserved.ts │ │ │ │ │ │ │ │ ├── error.preserve-use-memo-ref-missing-reactive.expect.md │ │ │ │ │ │ │ │ ├── error.preserve-use-memo-ref-missing-reactive.ts │ │ │ │ │ │ │ │ ├── error.todo-useCallback-captures-invalidating-value.expect.md │ │ │ │ │ │ │ │ ├── error.todo-useCallback-captures-invalidating-value.ts │ │ │ │ │ │ │ │ ├── error.useCallback-aliased-var.expect.md │ │ │ │ │ │ │ │ ├── error.useCallback-aliased-var.ts │ │ │ │ │ │ │ │ ├── error.useCallback-conditional-access-noAlloc.expect.md │ │ │ │ │ │ │ │ ├── error.useCallback-conditional-access-noAlloc.ts │ │ │ │ │ │ │ │ ├── error.useCallback-infer-less-specific-conditional-access.expect.md │ │ │ │ │ │ │ │ ├── error.useCallback-infer-less-specific-conditional-access.ts │ │ │ │ │ │ │ │ ├── error.useCallback-property-call-dep.expect.md │ │ │ │ │ │ │ │ ├── error.useCallback-property-call-dep.ts │ │ │ │ │ │ │ │ ├── error.useMemo-aliased-var.expect.md │ │ │ │ │ │ │ │ ├── error.useMemo-aliased-var.ts │ │ │ │ │ │ │ │ ├── error.useMemo-infer-less-specific-conditional-access.expect.md │ │ │ │ │ │ │ │ ├── error.useMemo-infer-less-specific-conditional-access.ts │ │ │ │ │ │ │ │ ├── error.useMemo-infer-less-specific-conditional-value-block.expect.md │ │ │ │ │ │ │ │ ├── error.useMemo-infer-less-specific-conditional-value-block.ts │ │ │ │ │ │ │ │ ├── error.useMemo-property-call-chained-object.expect.md │ │ │ │ │ │ │ │ ├── error.useMemo-property-call-chained-object.ts │ │ │ │ │ │ │ │ ├── error.useMemo-property-call-dep.expect.md │ │ │ │ │ │ │ │ ├── error.useMemo-property-call-dep.ts │ │ │ │ │ │ │ │ ├── error.useMemo-unrelated-mutation-in-depslist.expect.md │ │ │ │ │ │ │ │ ├── error.useMemo-unrelated-mutation-in-depslist.ts │ │ │ │ │ │ │ │ ├── error.useMemo-with-refs.flow.expect.md │ │ │ │ │ │ │ │ ├── error.useMemo-with-refs.flow.js │ │ │ │ │ │ │ │ ├── error.validate-useMemo-named-function.expect.md │ │ │ │ │ │ │ │ ├── error.validate-useMemo-named-function.js │ │ │ │ │ │ │ │ ├── maybe-invalid-useMemo-no-memoblock-sideeffect.expect.md │ │ │ │ │ │ │ │ ├── maybe-invalid-useMemo-no-memoblock-sideeffect.ts │ │ │ │ │ │ │ │ ├── preserve-use-callback-stable-built-ins.expect.md │ │ │ │ │ │ │ │ ├── preserve-use-callback-stable-built-ins.ts │ │ │ │ │ │ │ │ ├── preserve-use-memo-ref-missing-ok.expect.md │ │ │ │ │ │ │ │ ├── preserve-use-memo-ref-missing-ok.ts │ │ │ │ │ │ │ │ ├── preserve-use-memo-transition.expect.md │ │ │ │ │ │ │ │ ├── preserve-use-memo-transition.ts │ │ │ │ │ │ │ │ ├── prune-nonescaping-useMemo-mult-returns-primitive.expect.md │ │ │ │ │ │ │ │ ├── prune-nonescaping-useMemo-mult-returns-primitive.ts │ │ │ │ │ │ │ │ ├── prune-nonescaping-useMemo-mult-returns.expect.md │ │ │ │ │ │ │ │ ├── prune-nonescaping-useMemo-mult-returns.ts │ │ │ │ │ │ │ │ ├── prune-nonescaping-useMemo.expect.md │ │ │ │ │ │ │ │ ├── prune-nonescaping-useMemo.ts │ │ │ │ │ │ │ │ ├── repro-maybe-invalid-useCallback-read-maybeRef.expect.md │ │ │ │ │ │ │ │ ├── repro-maybe-invalid-useCallback-read-maybeRef.ts │ │ │ │ │ │ │ │ ├── repro-maybe-invalid-useMemo-read-maybeRef.expect.md │ │ │ │ │ │ │ │ ├── repro-maybe-invalid-useMemo-read-maybeRef.ts │ │ │ │ │ │ │ │ ├── todo-ensure-constant-prop-decls-get-removed.expect.md │ │ │ │ │ │ │ │ ├── todo-ensure-constant-prop-decls-get-removed.ts │ │ │ │ │ │ │ │ ├── useCallback-alias-property-load-dep.expect.md │ │ │ │ │ │ │ │ ├── useCallback-alias-property-load-dep.ts │ │ │ │ │ │ │ │ ├── useCallback-captures-reassigned-context-property.expect.md │ │ │ │ │ │ │ │ ├── useCallback-captures-reassigned-context-property.tsx │ │ │ │ │ │ │ │ ├── useCallback-captures-reassigned-context.expect.md │ │ │ │ │ │ │ │ ├── useCallback-captures-reassigned-context.ts │ │ │ │ │ │ │ │ ├── useCallback-dep-scope-pruned.expect.md │ │ │ │ │ │ │ │ ├── useCallback-dep-scope-pruned.ts │ │ │ │ │ │ │ │ ├── useCallback-extended-contextvar-scope.expect.md │ │ │ │ │ │ │ │ ├── useCallback-extended-contextvar-scope.tsx │ │ │ │ │ │ │ │ ├── useCallback-in-other-reactive-block.expect.md │ │ │ │ │ │ │ │ ├── useCallback-in-other-reactive-block.ts │ │ │ │ │ │ │ │ ├── useCallback-infer-fewer-deps.expect.md │ │ │ │ │ │ │ │ ├── useCallback-infer-fewer-deps.ts │ │ │ │ │ │ │ │ ├── useCallback-infer-more-specific.expect.md │ │ │ │ │ │ │ │ ├── useCallback-infer-more-specific.ts │ │ │ │ │ │ │ │ ├── useCallback-infer-read-dep.expect.md │ │ │ │ │ │ │ │ ├── useCallback-infer-read-dep.ts │ │ │ │ │ │ │ │ ├── useCallback-infer-scope-global.expect.md │ │ │ │ │ │ │ │ ├── useCallback-infer-scope-global.ts │ │ │ │ │ │ │ │ ├── useCallback-nonescaping-invoked-callback-escaping-return.expect.md │ │ │ │ │ │ │ │ ├── useCallback-nonescaping-invoked-callback-escaping-return.js │ │ │ │ │ │ │ │ ├── useCallback-nonescaping.expect.md │ │ │ │ │ │ │ │ ├── useCallback-nonescaping.js │ │ │ │ │ │ │ │ ├── useCallback-reordering-deplist-controlflow.expect.md │ │ │ │ │ │ │ │ ├── useCallback-reordering-deplist-controlflow.tsx │ │ │ │ │ │ │ │ ├── useCallback-reordering-depslist-assignment.expect.md │ │ │ │ │ │ │ │ ├── useCallback-reordering-depslist-assignment.tsx │ │ │ │ │ │ │ │ ├── useCallback-with-no-depslist.expect.md │ │ │ │ │ │ │ │ ├── useCallback-with-no-depslist.ts │ │ │ │ │ │ │ │ ├── useMemo-alias-property-load-dep.expect.md │ │ │ │ │ │ │ │ ├── useMemo-alias-property-load-dep.ts │ │ │ │ │ │ │ │ ├── useMemo-conditional-access-alloc.expect.md │ │ │ │ │ │ │ │ ├── useMemo-conditional-access-alloc.ts │ │ │ │ │ │ │ │ ├── useMemo-conditional-access-noAlloc.expect.md │ │ │ │ │ │ │ │ ├── useMemo-conditional-access-noAlloc.ts │ │ │ │ │ │ │ │ ├── useMemo-conditional-access-own-scope.expect.md │ │ │ │ │ │ │ │ ├── useMemo-conditional-access-own-scope.ts │ │ │ │ │ │ │ │ ├── useMemo-constant-prop.expect.md │ │ │ │ │ │ │ │ ├── useMemo-constant-prop.ts │ │ │ │ │ │ │ │ ├── useMemo-dep-array-literal-access.expect.md │ │ │ │ │ │ │ │ ├── useMemo-dep-array-literal-access.ts │ │ │ │ │ │ │ │ ├── useMemo-in-other-reactive-block.expect.md │ │ │ │ │ │ │ │ ├── useMemo-in-other-reactive-block.ts │ │ │ │ │ │ │ │ ├── useMemo-infer-fewer-deps.expect.md │ │ │ │ │ │ │ │ ├── useMemo-infer-fewer-deps.ts │ │ │ │ │ │ │ │ ├── useMemo-infer-more-specific.expect.md │ │ │ │ │ │ │ │ ├── useMemo-infer-more-specific.ts │ │ │ │ │ │ │ │ ├── useMemo-infer-nonallocating.expect.md │ │ │ │ │ │ │ │ ├── useMemo-infer-nonallocating.ts │ │ │ │ │ │ │ │ ├── useMemo-infer-scope-global.expect.md │ │ │ │ │ │ │ │ ├── useMemo-infer-scope-global.ts │ │ │ │ │ │ │ │ ├── useMemo-inner-decl.expect.md │ │ │ │ │ │ │ │ ├── useMemo-inner-decl.ts │ │ │ │ │ │ │ │ ├── useMemo-invoke-prop.expect.md │ │ │ │ │ │ │ │ ├── useMemo-invoke-prop.ts │ │ │ │ │ │ │ │ ├── useMemo-reordering-depslist-assignment.expect.md │ │ │ │ │ │ │ │ ├── useMemo-reordering-depslist-assignment.ts │ │ │ │ │ │ │ │ ├── useMemo-reordering-depslist-controlflow.expect.md │ │ │ │ │ │ │ │ ├── useMemo-reordering-depslist-controlflow.tsx │ │ │ │ │ │ │ │ ├── useMemo-with-no-depslist.expect.md │ │ │ │ │ │ │ │ └── useMemo-with-no-depslist.ts │ │ │ │ │ │ │ ├── preserve-use-memo-transition-no-ispending.expect.md │ │ │ │ │ │ │ ├── preserve-use-memo-transition-no-ispending.js │ │ │ │ │ │ │ ├── preserve-use-memo-unused-state.expect.md │ │ │ │ │ │ │ ├── preserve-use-memo-unused-state.js │ │ │ │ │ │ │ ├── primitive-alias-mutate.expect.md │ │ │ │ │ │ │ ├── primitive-alias-mutate.js │ │ │ │ │ │ │ ├── primitive-as-dep-nested-scope.expect.md │ │ │ │ │ │ │ ├── primitive-as-dep-nested-scope.js │ │ │ │ │ │ │ ├── primitive-as-dep.expect.md │ │ │ │ │ │ │ ├── primitive-as-dep.js │ │ │ │ │ │ │ ├── primitive-reassigned-loop-force-scopes-enabled.expect.md │ │ │ │ │ │ │ ├── primitive-reassigned-loop-force-scopes-enabled.js │ │ │ │ │ │ │ ├── prop-capturing-function-1.expect.md │ │ │ │ │ │ │ ├── prop-capturing-function-1.js │ │ │ │ │ │ │ ├── propagate-scope-deps-hir-fork/ │ │ │ │ │ │ │ │ ├── conditional-break-labeled.expect.md │ │ │ │ │ │ │ │ ├── conditional-break-labeled.js │ │ │ │ │ │ │ │ ├── conditional-early-return.expect.md │ │ │ │ │ │ │ │ ├── conditional-early-return.js │ │ │ │ │ │ │ │ ├── conditional-on-mutable.expect.md │ │ │ │ │ │ │ │ ├── conditional-on-mutable.js │ │ │ │ │ │ │ │ ├── early-return-nested-early-return-within-reactive-scope.expect.md │ │ │ │ │ │ │ │ ├── early-return-nested-early-return-within-reactive-scope.js │ │ │ │ │ │ │ │ ├── early-return-within-reactive-scope.expect.md │ │ │ │ │ │ │ │ ├── early-return-within-reactive-scope.js │ │ │ │ │ │ │ │ ├── error.todo-optional-member-expression-with-conditional-optional.expect.md │ │ │ │ │ │ │ │ ├── error.todo-optional-member-expression-with-conditional-optional.js │ │ │ │ │ │ │ │ ├── error.todo-optional-member-expression-with-conditional.expect.md │ │ │ │ │ │ │ │ ├── error.todo-optional-member-expression-with-conditional.js │ │ │ │ │ │ │ │ ├── iife-return-modified-later-phi.expect.md │ │ │ │ │ │ │ │ ├── iife-return-modified-later-phi.js │ │ │ │ │ │ │ │ ├── infer-component-props-non-null.expect.md │ │ │ │ │ │ │ │ ├── infer-component-props-non-null.tsx │ │ │ │ │ │ │ │ ├── infer-non-null-destructure.expect.md │ │ │ │ │ │ │ │ ├── infer-non-null-destructure.ts │ │ │ │ │ │ │ │ ├── infer-sequential-optional-chain-nonnull.expect.md │ │ │ │ │ │ │ │ ├── infer-sequential-optional-chain-nonnull.ts │ │ │ │ │ │ │ │ ├── nested-optional-chains.expect.md │ │ │ │ │ │ │ │ ├── nested-optional-chains.ts │ │ │ │ │ │ │ │ ├── object-mutated-in-consequent-alternate-both-return.expect.md │ │ │ │ │ │ │ │ ├── object-mutated-in-consequent-alternate-both-return.js │ │ │ │ │ │ │ │ ├── optional-member-expression-as-memo-dep.expect.md │ │ │ │ │ │ │ │ ├── optional-member-expression-as-memo-dep.js │ │ │ │ │ │ │ │ ├── optional-member-expression-inverted-optionals-parallel-paths.expect.md │ │ │ │ │ │ │ │ ├── optional-member-expression-inverted-optionals-parallel-paths.js │ │ │ │ │ │ │ │ ├── optional-member-expression-single-with-unconditional.expect.md │ │ │ │ │ │ │ │ ├── optional-member-expression-single-with-unconditional.js │ │ │ │ │ │ │ │ ├── optional-member-expression-single.expect.md │ │ │ │ │ │ │ │ ├── optional-member-expression-single.js │ │ │ │ │ │ │ │ ├── partial-early-return-within-reactive-scope.expect.md │ │ │ │ │ │ │ │ ├── partial-early-return-within-reactive-scope.js │ │ │ │ │ │ │ │ ├── phi-type-inference-array-push-consecutive-phis.expect.md │ │ │ │ │ │ │ │ ├── phi-type-inference-array-push-consecutive-phis.js │ │ │ │ │ │ │ │ ├── phi-type-inference-array-push.expect.md │ │ │ │ │ │ │ │ ├── phi-type-inference-array-push.js │ │ │ │ │ │ │ │ ├── phi-type-inference-property-store.expect.md │ │ │ │ │ │ │ │ ├── phi-type-inference-property-store.js │ │ │ │ │ │ │ │ ├── reactive-dependencies-non-optional-properties-inside-optional-chain.expect.md │ │ │ │ │ │ │ │ ├── reactive-dependencies-non-optional-properties-inside-optional-chain.js │ │ │ │ │ │ │ │ ├── reduce-reactive-deps/ │ │ │ │ │ │ │ │ │ ├── conditional-member-expr.expect.md │ │ │ │ │ │ │ │ │ ├── conditional-member-expr.js │ │ │ │ │ │ │ │ │ ├── infer-function-cond-access-local-var.expect.md │ │ │ │ │ │ │ │ │ ├── infer-function-cond-access-local-var.tsx │ │ │ │ │ │ │ │ │ ├── infer-function-cond-access-not-hoisted.expect.md │ │ │ │ │ │ │ │ │ ├── infer-function-cond-access-not-hoisted.tsx │ │ │ │ │ │ │ │ │ ├── infer-function-uncond-access-hoisted.expect.md │ │ │ │ │ │ │ │ │ ├── infer-function-uncond-access-hoisted.tsx │ │ │ │ │ │ │ │ │ ├── infer-function-uncond-access-hoists-other-dep.expect.md │ │ │ │ │ │ │ │ │ ├── infer-function-uncond-access-hoists-other-dep.tsx │ │ │ │ │ │ │ │ │ ├── infer-function-uncond-access-local-var.expect.md │ │ │ │ │ │ │ │ │ ├── infer-function-uncond-access-local-var.tsx │ │ │ │ │ │ │ │ │ ├── infer-function-uncond-optional-hoists-other-dep.expect.md │ │ │ │ │ │ │ │ │ ├── infer-function-uncond-optional-hoists-other-dep.tsx │ │ │ │ │ │ │ │ │ ├── infer-nested-function-uncond-access-local-var.expect.md │ │ │ │ │ │ │ │ │ ├── infer-nested-function-uncond-access-local-var.tsx │ │ │ │ │ │ │ │ │ ├── infer-nested-function-uncond-access.expect.md │ │ │ │ │ │ │ │ │ ├── infer-nested-function-uncond-access.tsx │ │ │ │ │ │ │ │ │ ├── infer-object-method-uncond-access.expect.md │ │ │ │ │ │ │ │ │ ├── infer-object-method-uncond-access.tsx │ │ │ │ │ │ │ │ │ ├── infer-objectmethod-cond-access.expect.md │ │ │ │ │ │ │ │ │ ├── infer-objectmethod-cond-access.js │ │ │ │ │ │ │ │ │ ├── join-uncond-scopes-cond-deps.expect.md │ │ │ │ │ │ │ │ │ ├── join-uncond-scopes-cond-deps.js │ │ │ │ │ │ │ │ │ ├── memberexpr-join-optional-chain.expect.md │ │ │ │ │ │ │ │ │ ├── memberexpr-join-optional-chain.ts │ │ │ │ │ │ │ │ │ ├── memberexpr-join-optional-chain2.expect.md │ │ │ │ │ │ │ │ │ ├── memberexpr-join-optional-chain2.ts │ │ │ │ │ │ │ │ │ ├── merge-uncond-optional-chain-and-cond.expect.md │ │ │ │ │ │ │ │ │ ├── merge-uncond-optional-chain-and-cond.ts │ │ │ │ │ │ │ │ │ ├── promote-uncond.expect.md │ │ │ │ │ │ │ │ │ ├── promote-uncond.js │ │ │ │ │ │ │ │ │ ├── todo-infer-function-uncond-optionals-hoisted.expect.md │ │ │ │ │ │ │ │ │ └── todo-infer-function-uncond-optionals-hoisted.tsx │ │ │ │ │ │ │ │ ├── repro-invariant.expect.md │ │ │ │ │ │ │ │ ├── repro-invariant.tsx │ │ │ │ │ │ │ │ ├── repro-scope-missing-mutable-range.expect.md │ │ │ │ │ │ │ │ ├── repro-scope-missing-mutable-range.js │ │ │ │ │ │ │ │ ├── ssa-cascading-eliminated-phis.expect.md │ │ │ │ │ │ │ │ ├── ssa-cascading-eliminated-phis.js │ │ │ │ │ │ │ │ ├── ssa-leave-case.expect.md │ │ │ │ │ │ │ │ ├── ssa-leave-case.js │ │ │ │ │ │ │ │ ├── ssa-renaming-ternary-destruction-with-mutation.expect.md │ │ │ │ │ │ │ │ ├── ssa-renaming-ternary-destruction-with-mutation.js │ │ │ │ │ │ │ │ ├── ssa-renaming-ternary-destruction.expect.md │ │ │ │ │ │ │ │ ├── ssa-renaming-ternary-destruction.js │ │ │ │ │ │ │ │ ├── ssa-renaming-ternary-with-mutation.expect.md │ │ │ │ │ │ │ │ ├── ssa-renaming-ternary-with-mutation.js │ │ │ │ │ │ │ │ ├── ssa-renaming-ternary.expect.md │ │ │ │ │ │ │ │ ├── ssa-renaming-ternary.js │ │ │ │ │ │ │ │ ├── ssa-renaming-unconditional-ternary-with-mutation.expect.md │ │ │ │ │ │ │ │ ├── ssa-renaming-unconditional-ternary-with-mutation.js │ │ │ │ │ │ │ │ ├── ssa-renaming-unconditional-ternary.expect.md │ │ │ │ │ │ │ │ ├── ssa-renaming-unconditional-ternary.js │ │ │ │ │ │ │ │ ├── ssa-renaming-unconditional-with-mutation.expect.md │ │ │ │ │ │ │ │ ├── ssa-renaming-unconditional-with-mutation.js │ │ │ │ │ │ │ │ ├── ssa-renaming-via-destructuring-with-mutation.expect.md │ │ │ │ │ │ │ │ ├── ssa-renaming-via-destructuring-with-mutation.js │ │ │ │ │ │ │ │ ├── ssa-renaming-with-mutation.expect.md │ │ │ │ │ │ │ │ ├── ssa-renaming-with-mutation.js │ │ │ │ │ │ │ │ ├── switch-non-final-default.expect.md │ │ │ │ │ │ │ │ ├── switch-non-final-default.js │ │ │ │ │ │ │ │ ├── switch.expect.md │ │ │ │ │ │ │ │ ├── switch.js │ │ │ │ │ │ │ │ ├── todo-optional-call-chain-in-optional.expect.md │ │ │ │ │ │ │ │ ├── todo-optional-call-chain-in-optional.ts │ │ │ │ │ │ │ │ ├── try-catch-maybe-null-dependency.expect.md │ │ │ │ │ │ │ │ ├── try-catch-maybe-null-dependency.ts │ │ │ │ │ │ │ │ ├── try-catch-mutate-outer-value.expect.md │ │ │ │ │ │ │ │ ├── try-catch-mutate-outer-value.js │ │ │ │ │ │ │ │ ├── try-catch-try-value-modified-in-catch-escaping.expect.md │ │ │ │ │ │ │ │ ├── try-catch-try-value-modified-in-catch-escaping.js │ │ │ │ │ │ │ │ ├── try-catch-try-value-modified-in-catch.expect.md │ │ │ │ │ │ │ │ ├── try-catch-try-value-modified-in-catch.js │ │ │ │ │ │ │ │ ├── useMemo-multiple-if-else.expect.md │ │ │ │ │ │ │ │ └── useMemo-multiple-if-else.js │ │ │ │ │ │ │ ├── property-assignment.expect.md │ │ │ │ │ │ │ ├── property-assignment.js │ │ │ │ │ │ │ ├── property-call-evaluation-order.expect.md │ │ │ │ │ │ │ ├── property-call-evaluation-order.js │ │ │ │ │ │ │ ├── property-call-spread.expect.md │ │ │ │ │ │ │ ├── property-call-spread.js │ │ │ │ │ │ │ ├── props-method-dependency.expect.md │ │ │ │ │ │ │ ├── props-method-dependency.js │ │ │ │ │ │ │ ├── prune-scopes-whose-deps-invalidate-array.expect.md │ │ │ │ │ │ │ ├── prune-scopes-whose-deps-invalidate-array.js │ │ │ │ │ │ │ ├── prune-scopes-whose-deps-invalidate-jsx.expect.md │ │ │ │ │ │ │ ├── prune-scopes-whose-deps-invalidate-jsx.js │ │ │ │ │ │ │ ├── prune-scopes-whose-deps-invalidate-new.expect.md │ │ │ │ │ │ │ ├── prune-scopes-whose-deps-invalidate-new.js │ │ │ │ │ │ │ ├── prune-scopes-whose-deps-invalidate-object.expect.md │ │ │ │ │ │ │ ├── prune-scopes-whose-deps-invalidate-object.js │ │ │ │ │ │ │ ├── prune-scopes-whose-deps-may-invalidate-array.expect.md │ │ │ │ │ │ │ ├── prune-scopes-whose-deps-may-invalidate-array.js │ │ │ │ │ │ │ ├── quoted-strings-in-jsx-attribute-escaped.expect.md │ │ │ │ │ │ │ ├── quoted-strings-in-jsx-attribute-escaped.js │ │ │ │ │ │ │ ├── quoted-strings-in-jsx-attribute.expect.md │ │ │ │ │ │ │ ├── quoted-strings-in-jsx-attribute.js │ │ │ │ │ │ │ ├── quoted-strings-jsx-attribute-escaped-constant-propagation.expect.md │ │ │ │ │ │ │ ├── quoted-strings-jsx-attribute-escaped-constant-propagation.js │ │ │ │ │ │ │ ├── react-namespace.expect.md │ │ │ │ │ │ │ ├── react-namespace.js │ │ │ │ │ │ │ ├── reactive-control-dependency-do-while-indirect.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-do-while-indirect.js │ │ │ │ │ │ │ ├── reactive-control-dependency-do-while-test.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-do-while-test.js │ │ │ │ │ │ │ ├── reactive-control-dependency-for-init.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-for-init.js │ │ │ │ │ │ │ ├── reactive-control-dependency-for-test.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-for-test.js │ │ │ │ │ │ │ ├── reactive-control-dependency-for-update.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-for-update.js │ │ │ │ │ │ │ ├── reactive-control-dependency-forin-collection.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-forin-collection.js │ │ │ │ │ │ │ ├── reactive-control-dependency-forof-collection.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-forof-collection.js │ │ │ │ │ │ │ ├── reactive-control-dependency-from-interleaved-reactivity-do-while.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-from-interleaved-reactivity-do-while.js │ │ │ │ │ │ │ ├── reactive-control-dependency-from-interleaved-reactivity-for-in.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-from-interleaved-reactivity-for-in.js │ │ │ │ │ │ │ ├── reactive-control-dependency-from-interleaved-reactivity-for-init.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-from-interleaved-reactivity-for-init.js │ │ │ │ │ │ │ ├── reactive-control-dependency-from-interleaved-reactivity-for-of.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-from-interleaved-reactivity-for-of.js │ │ │ │ │ │ │ ├── reactive-control-dependency-from-interleaved-reactivity-for-test.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-from-interleaved-reactivity-for-test.js │ │ │ │ │ │ │ ├── reactive-control-dependency-from-interleaved-reactivity-for-update.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-from-interleaved-reactivity-for-update.js │ │ │ │ │ │ │ ├── reactive-control-dependency-from-interleaved-reactivity-if.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-from-interleaved-reactivity-if.js │ │ │ │ │ │ │ ├── reactive-control-dependency-from-interleaved-reactivity-switch.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-from-interleaved-reactivity-switch.js │ │ │ │ │ │ │ ├── reactive-control-dependency-from-interleaved-reactivity-while.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-from-interleaved-reactivity-while.js │ │ │ │ │ │ │ ├── reactive-control-dependency-if.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-if.js │ │ │ │ │ │ │ ├── reactive-control-dependency-on-context-variable.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-on-context-variable.js │ │ │ │ │ │ │ ├── reactive-control-dependency-phi-setState-type.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-phi-setState-type.js │ │ │ │ │ │ │ ├── reactive-control-dependency-reactive-after-fixpoint.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-reactive-after-fixpoint.js │ │ │ │ │ │ │ ├── reactive-control-dependency-switch-case-test.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-switch-case-test.js │ │ │ │ │ │ │ ├── reactive-control-dependency-switch-condition.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-switch-condition.js │ │ │ │ │ │ │ ├── reactive-control-dependency-via-mutation-if.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-via-mutation-if.js │ │ │ │ │ │ │ ├── reactive-control-dependency-via-mutation-switch.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-via-mutation-switch.js │ │ │ │ │ │ │ ├── reactive-control-dependency-while-test.expect.md │ │ │ │ │ │ │ ├── reactive-control-dependency-while-test.js │ │ │ │ │ │ │ ├── reactive-dependencies-non-optional-properties-inside-optional-chain.expect.md │ │ │ │ │ │ │ ├── reactive-dependencies-non-optional-properties-inside-optional-chain.js │ │ │ │ │ │ │ ├── reactive-dependency-fixpoint.expect.md │ │ │ │ │ │ │ ├── reactive-dependency-fixpoint.js │ │ │ │ │ │ │ ├── reactive-dependency-nonreactive-captured-with-reactive.expect.md │ │ │ │ │ │ │ ├── reactive-dependency-nonreactive-captured-with-reactive.js │ │ │ │ │ │ │ ├── reactive-dependency-object-captured-with-reactive-mutated.expect.md │ │ │ │ │ │ │ ├── reactive-dependency-object-captured-with-reactive-mutated.js │ │ │ │ │ │ │ ├── reactive-ref-param.expect.md │ │ │ │ │ │ │ ├── reactive-ref-param.tsx │ │ │ │ │ │ │ ├── reactive-ref.expect.md │ │ │ │ │ │ │ ├── reactive-ref.tsx │ │ │ │ │ │ │ ├── reactive-scope-grouping.expect.md │ │ │ │ │ │ │ ├── reactive-scope-grouping.js │ │ │ │ │ │ │ ├── reactive-scopes-if.expect.md │ │ │ │ │ │ │ ├── reactive-scopes-if.js │ │ │ │ │ │ │ ├── reactive-scopes.expect.md │ │ │ │ │ │ │ ├── reactive-scopes.js │ │ │ │ │ │ │ ├── reactivity-analysis-interleaved-reactivity.expect.md │ │ │ │ │ │ │ ├── reactivity-analysis-interleaved-reactivity.js │ │ │ │ │ │ │ ├── reactivity-analysis-reactive-via-mutation-of-computed-load.expect.md │ │ │ │ │ │ │ ├── reactivity-analysis-reactive-via-mutation-of-computed-load.js │ │ │ │ │ │ │ ├── reactivity-analysis-reactive-via-mutation-of-property-load.expect.md │ │ │ │ │ │ │ ├── reactivity-analysis-reactive-via-mutation-of-property-load.js │ │ │ │ │ │ │ ├── reactivity-via-aliased-mutation-array.expect.md │ │ │ │ │ │ │ ├── reactivity-via-aliased-mutation-array.js │ │ │ │ │ │ │ ├── reactivity-via-aliased-mutation-lambda.expect.md │ │ │ │ │ │ │ ├── reactivity-via-aliased-mutation-lambda.js │ │ │ │ │ │ │ ├── reactivity-via-aliased-mutation-through-property-load.expect.md │ │ │ │ │ │ │ ├── reactivity-via-aliased-mutation-through-property-load.js │ │ │ │ │ │ │ ├── reactivity-via-readonly-alias-of-mutable-value.expect.md │ │ │ │ │ │ │ ├── reactivity-via-readonly-alias-of-mutable-value.js │ │ │ │ │ │ │ ├── readonly-object-method-calls-mutable-lambda.expect.md │ │ │ │ │ │ │ ├── readonly-object-method-calls-mutable-lambda.js │ │ │ │ │ │ │ ├── readonly-object-method-calls.expect.md │ │ │ │ │ │ │ ├── readonly-object-method-calls.js │ │ │ │ │ │ │ ├── reanimated-no-memo-arg.expect.md │ │ │ │ │ │ │ ├── reanimated-no-memo-arg.js │ │ │ │ │ │ │ ├── reanimated-shared-value-writes.expect.md │ │ │ │ │ │ │ ├── reanimated-shared-value-writes.jsx │ │ │ │ │ │ │ ├── reassign-global-hook-arg.expect.md │ │ │ │ │ │ │ ├── reassign-global-hook-arg.js │ │ │ │ │ │ │ ├── reassign-global-return.expect.md │ │ │ │ │ │ │ ├── reassign-global-return.js │ │ │ │ │ │ │ ├── reassign-in-while-loop-condition.expect.md │ │ │ │ │ │ │ ├── reassign-in-while-loop-condition.js │ │ │ │ │ │ │ ├── reassign-object-in-context.expect.md │ │ │ │ │ │ │ ├── reassign-object-in-context.js │ │ │ │ │ │ │ ├── reassign-primitive-in-context.expect.md │ │ │ │ │ │ │ ├── reassign-primitive-in-context.js │ │ │ │ │ │ │ ├── reassign-variable-in-usememo.expect.md │ │ │ │ │ │ │ ├── reassign-variable-in-usememo.js │ │ │ │ │ │ │ ├── reassigned-phi-in-returned-function-expression.expect.md │ │ │ │ │ │ │ ├── reassigned-phi-in-returned-function-expression.js │ │ │ │ │ │ │ ├── reassignment-conditional.expect.md │ │ │ │ │ │ │ ├── reassignment-conditional.js │ │ │ │ │ │ │ ├── reassignment-separate-scopes.expect.md │ │ │ │ │ │ │ ├── reassignment-separate-scopes.js │ │ │ │ │ │ │ ├── reassignment.expect.md │ │ │ │ │ │ │ ├── reassignment.js │ │ │ │ │ │ │ ├── recursive-function-expression.expect.md │ │ │ │ │ │ │ ├── recursive-function-expression.js │ │ │ │ │ │ │ ├── recursive-function.expect.md │ │ │ │ │ │ │ ├── recursive-function.js │ │ │ │ │ │ │ ├── reduce-reactive-cond-deps-break-in-scope.expect.md │ │ │ │ │ │ │ ├── reduce-reactive-cond-deps-break-in-scope.ts │ │ │ │ │ │ │ ├── reduce-reactive-cond-deps-cfg-nested-testifelse.expect.md │ │ │ │ │ │ │ ├── reduce-reactive-cond-deps-cfg-nested-testifelse.ts │ │ │ │ │ │ │ ├── reduce-reactive-cond-deps-return-in-scope.expect.md │ │ │ │ │ │ │ ├── reduce-reactive-cond-deps-return-in-scope.ts │ │ │ │ │ │ │ ├── reduce-reactive-deps/ │ │ │ │ │ │ │ │ ├── cfg-condexpr.expect.md │ │ │ │ │ │ │ │ ├── cfg-condexpr.js │ │ │ │ │ │ │ │ ├── cfg-ifelse.expect.md │ │ │ │ │ │ │ │ ├── cfg-ifelse.js │ │ │ │ │ │ │ │ ├── cfg-nested-ifelse-missing.expect.md │ │ │ │ │ │ │ │ ├── cfg-nested-ifelse-missing.js │ │ │ │ │ │ │ │ ├── cfg-nested-ifelse.expect.md │ │ │ │ │ │ │ │ ├── cfg-nested-ifelse.js │ │ │ │ │ │ │ │ ├── cfg-switch-exhaustive.expect.md │ │ │ │ │ │ │ │ ├── cfg-switch-exhaustive.js │ │ │ │ │ │ │ │ ├── cfg-switch-missing-case.expect.md │ │ │ │ │ │ │ │ ├── cfg-switch-missing-case.js │ │ │ │ │ │ │ │ ├── cfg-switch-missing-default.expect.md │ │ │ │ │ │ │ │ ├── cfg-switch-missing-default.js │ │ │ │ │ │ │ │ ├── cond-scope.expect.md │ │ │ │ │ │ │ │ ├── cond-scope.js │ │ │ │ │ │ │ │ ├── conditional-member-expr.expect.md │ │ │ │ │ │ │ │ ├── conditional-member-expr.js │ │ │ │ │ │ │ │ ├── context-var-granular-dep.expect.md │ │ │ │ │ │ │ │ ├── context-var-granular-dep.js │ │ │ │ │ │ │ │ ├── edge-case-merge-uncond-optional-chain-and-cond.expect.md │ │ │ │ │ │ │ │ ├── edge-case-merge-uncond-optional-chain-and-cond.ts │ │ │ │ │ │ │ │ ├── hoist-deps-diff-ssa-instance.expect.md │ │ │ │ │ │ │ │ ├── hoist-deps-diff-ssa-instance.tsx │ │ │ │ │ │ │ │ ├── hoist-deps-diff-ssa-instance1.expect.md │ │ │ │ │ │ │ │ ├── hoist-deps-diff-ssa-instance1.tsx │ │ │ │ │ │ │ │ ├── infer-function-cond-access-not-hoisted.expect.md │ │ │ │ │ │ │ │ ├── infer-function-cond-access-not-hoisted.tsx │ │ │ │ │ │ │ │ ├── join-uncond-scopes-cond-deps.expect.md │ │ │ │ │ │ │ │ ├── join-uncond-scopes-cond-deps.js │ │ │ │ │ │ │ │ ├── jump-poisoned/ │ │ │ │ │ │ │ │ │ ├── break-in-scope.expect.md │ │ │ │ │ │ │ │ │ ├── break-in-scope.ts │ │ │ │ │ │ │ │ │ ├── break-poisons-outer-scope.expect.md │ │ │ │ │ │ │ │ │ ├── break-poisons-outer-scope.ts │ │ │ │ │ │ │ │ │ ├── loop-break-in-scope.expect.md │ │ │ │ │ │ │ │ │ ├── loop-break-in-scope.ts │ │ │ │ │ │ │ │ │ ├── reduce-if-nonexhaustive-poisoned-deps.expect.md │ │ │ │ │ │ │ │ │ ├── reduce-if-nonexhaustive-poisoned-deps.ts │ │ │ │ │ │ │ │ │ ├── reduce-if-nonexhaustive-poisoned-deps1.expect.md │ │ │ │ │ │ │ │ │ ├── reduce-if-nonexhaustive-poisoned-deps1.ts │ │ │ │ │ │ │ │ │ ├── return-in-scope.expect.md │ │ │ │ │ │ │ │ │ ├── return-in-scope.ts │ │ │ │ │ │ │ │ │ ├── return-poisons-outer-scope.expect.md │ │ │ │ │ │ │ │ │ └── return-poisons-outer-scope.ts │ │ │ │ │ │ │ │ ├── jump-unpoisoned/ │ │ │ │ │ │ │ │ │ ├── else-branch-scope-unpoisoned.expect.md │ │ │ │ │ │ │ │ │ ├── else-branch-scope-unpoisoned.ts │ │ │ │ │ │ │ │ │ ├── jump-target-within-scope-label.expect.md │ │ │ │ │ │ │ │ │ ├── jump-target-within-scope-label.ts │ │ │ │ │ │ │ │ │ ├── jump-target-within-scope-loop-break.expect.md │ │ │ │ │ │ │ │ │ ├── jump-target-within-scope-loop-break.ts │ │ │ │ │ │ │ │ │ ├── reduce-if-exhaustive-nonpoisoned-deps.expect.md │ │ │ │ │ │ │ │ │ ├── reduce-if-exhaustive-nonpoisoned-deps.ts │ │ │ │ │ │ │ │ │ ├── reduce-if-exhaustive-nonpoisoned-deps1.expect.md │ │ │ │ │ │ │ │ │ ├── reduce-if-exhaustive-nonpoisoned-deps1.ts │ │ │ │ │ │ │ │ │ ├── return-before-scope-starts.expect.md │ │ │ │ │ │ │ │ │ ├── return-before-scope-starts.ts │ │ │ │ │ │ │ │ │ ├── throw-before-scope-starts.expect.md │ │ │ │ │ │ │ │ │ └── throw-before-scope-starts.ts │ │ │ │ │ │ │ │ ├── memberexpr-join-optional-chain.expect.md │ │ │ │ │ │ │ │ ├── memberexpr-join-optional-chain.ts │ │ │ │ │ │ │ │ ├── memberexpr-join-optional-chain2.expect.md │ │ │ │ │ │ │ │ ├── memberexpr-join-optional-chain2.ts │ │ │ │ │ │ │ │ ├── no-uncond.expect.md │ │ │ │ │ │ │ │ ├── no-uncond.js │ │ │ │ │ │ │ │ ├── promote-uncond.expect.md │ │ │ │ │ │ │ │ ├── promote-uncond.js │ │ │ │ │ │ │ │ ├── reduce-if-exhaustive-poisoned-deps.expect.md │ │ │ │ │ │ │ │ ├── reduce-if-exhaustive-poisoned-deps.ts │ │ │ │ │ │ │ │ ├── subpath-order1.expect.md │ │ │ │ │ │ │ │ ├── subpath-order1.js │ │ │ │ │ │ │ │ ├── subpath-order2.expect.md │ │ │ │ │ │ │ │ ├── subpath-order2.js │ │ │ │ │ │ │ │ ├── superpath-order1.expect.md │ │ │ │ │ │ │ │ ├── superpath-order1.js │ │ │ │ │ │ │ │ ├── superpath-order2.expect.md │ │ │ │ │ │ │ │ ├── superpath-order2.js │ │ │ │ │ │ │ │ ├── todo-infer-function-uncond-optionals-hoisted.expect.md │ │ │ │ │ │ │ │ ├── todo-infer-function-uncond-optionals-hoisted.tsx │ │ │ │ │ │ │ │ ├── todo-merge-ssa-phi-access-nodes.expect.md │ │ │ │ │ │ │ │ ├── todo-merge-ssa-phi-access-nodes.ts │ │ │ │ │ │ │ │ ├── uncond-access-in-mutable-range.expect.md │ │ │ │ │ │ │ │ ├── uncond-access-in-mutable-range.js │ │ │ │ │ │ │ │ ├── uncond-nonoverlap-descendant.expect.md │ │ │ │ │ │ │ │ ├── uncond-nonoverlap-descendant.js │ │ │ │ │ │ │ │ ├── uncond-nonoverlap-direct.expect.md │ │ │ │ │ │ │ │ ├── uncond-nonoverlap-direct.js │ │ │ │ │ │ │ │ ├── uncond-overlap-descendant.expect.md │ │ │ │ │ │ │ │ ├── uncond-overlap-descendant.js │ │ │ │ │ │ │ │ ├── uncond-overlap-direct.expect.md │ │ │ │ │ │ │ │ ├── uncond-overlap-direct.js │ │ │ │ │ │ │ │ ├── uncond-subpath-order1.expect.md │ │ │ │ │ │ │ │ ├── uncond-subpath-order1.js │ │ │ │ │ │ │ │ ├── uncond-subpath-order2.expect.md │ │ │ │ │ │ │ │ ├── uncond-subpath-order2.js │ │ │ │ │ │ │ │ ├── uncond-subpath-order3.expect.md │ │ │ │ │ │ │ │ └── uncond-subpath-order3.js │ │ │ │ │ │ │ ├── ref-current-aliased-no-added-to-dep.expect.md │ │ │ │ │ │ │ ├── ref-current-aliased-no-added-to-dep.js │ │ │ │ │ │ │ ├── ref-current-aliased-not-added-to-dep-2.expect.md │ │ │ │ │ │ │ ├── ref-current-aliased-not-added-to-dep-2.js │ │ │ │ │ │ │ ├── ref-current-field-not-added-to-dep.expect.md │ │ │ │ │ │ │ ├── ref-current-field-not-added-to-dep.js │ │ │ │ │ │ │ ├── ref-current-field-write-not-added-to-dep.expect.md │ │ │ │ │ │ │ ├── ref-current-field-write-not-added-to-dep.js │ │ │ │ │ │ │ ├── ref-current-not-added-to-dep-2.expect.md │ │ │ │ │ │ │ ├── ref-current-not-added-to-dep-2.js │ │ │ │ │ │ │ ├── ref-current-not-added-to-dep.expect.md │ │ │ │ │ │ │ ├── ref-current-not-added-to-dep.js │ │ │ │ │ │ │ ├── ref-current-optional-field-no-added-to-dep.expect.md │ │ │ │ │ │ │ ├── ref-current-optional-field-no-added-to-dep.js │ │ │ │ │ │ │ ├── ref-current-write-not-added-to-dep.expect.md │ │ │ │ │ │ │ ├── ref-current-write-not-added-to-dep.js │ │ │ │ │ │ │ ├── ref-in-effect.expect.md │ │ │ │ │ │ │ ├── ref-in-effect.js │ │ │ │ │ │ │ ├── ref-like-name-in-effect.expect.md │ │ │ │ │ │ │ ├── ref-like-name-in-effect.js │ │ │ │ │ │ │ ├── ref-like-name-in-useCallback-2.expect.md │ │ │ │ │ │ │ ├── ref-like-name-in-useCallback-2.js │ │ │ │ │ │ │ ├── ref-like-name-in-useCallback.expect.md │ │ │ │ │ │ │ ├── ref-like-name-in-useCallback.js │ │ │ │ │ │ │ ├── ref-parameter-mutate-in-effect.expect.md │ │ │ │ │ │ │ ├── ref-parameter-mutate-in-effect.js │ │ │ │ │ │ │ ├── regexp-literal.expect.md │ │ │ │ │ │ │ ├── regexp-literal.js │ │ │ │ │ │ │ ├── relay-transitive-mixeddata.expect.md │ │ │ │ │ │ │ ├── relay-transitive-mixeddata.js │ │ │ │ │ │ │ ├── renaming-jsx-tag-lowercase.expect.md │ │ │ │ │ │ │ ├── renaming-jsx-tag-lowercase.tsx │ │ │ │ │ │ │ ├── reordering-across-blocks.expect.md │ │ │ │ │ │ │ ├── reordering-across-blocks.js │ │ │ │ │ │ │ ├── repeated-dependencies-more-precise.expect.md │ │ │ │ │ │ │ ├── repeated-dependencies-more-precise.js │ │ │ │ │ │ │ ├── repro-aliased-capture-aliased-mutate.expect.md │ │ │ │ │ │ │ ├── repro-aliased-capture-aliased-mutate.js │ │ │ │ │ │ │ ├── repro-aliased-capture-mutate.expect.md │ │ │ │ │ │ │ ├── repro-aliased-capture-mutate.js │ │ │ │ │ │ │ ├── repro-allocating-ternary-test-instruction-scope.expect.md │ │ │ │ │ │ │ ├── repro-allocating-ternary-test-instruction-scope.ts │ │ │ │ │ │ │ ├── repro-backedge-reference-effect.expect.md │ │ │ │ │ │ │ ├── repro-backedge-reference-effect.js │ │ │ │ │ │ │ ├── repro-bailout-nopanic-shouldnt-outline.expect.md │ │ │ │ │ │ │ ├── repro-bailout-nopanic-shouldnt-outline.js │ │ │ │ │ │ │ ├── repro-capturing-func-maybealias-captured-mutate.expect.md │ │ │ │ │ │ │ ├── repro-capturing-func-maybealias-captured-mutate.ts │ │ │ │ │ │ │ ├── repro-context-var-reassign-no-scope.expect.md │ │ │ │ │ │ │ ├── repro-context-var-reassign-no-scope.js │ │ │ │ │ │ │ ├── repro-dce-circular-reference.expect.md │ │ │ │ │ │ │ ├── repro-dce-circular-reference.js │ │ │ │ │ │ │ ├── repro-declaration-for-all-identifiers.expect.md │ │ │ │ │ │ │ ├── repro-declaration-for-all-identifiers.js │ │ │ │ │ │ │ ├── repro-dispatch-spread-event-marks-event-frozen.expect.md │ │ │ │ │ │ │ ├── repro-dispatch-spread-event-marks-event-frozen.js │ │ │ │ │ │ │ ├── repro-dont-memoize-array-with-capturing-map-after-hook.expect.md │ │ │ │ │ │ │ ├── repro-dont-memoize-array-with-capturing-map-after-hook.js │ │ │ │ │ │ │ ├── repro-dont-memoize-array-with-mutable-map-after-hook.expect.md │ │ │ │ │ │ │ ├── repro-dont-memoize-array-with-mutable-map-after-hook.js │ │ │ │ │ │ │ ├── repro-duplicate-import-specifier.expect.md │ │ │ │ │ │ │ ├── repro-duplicate-import-specifier.ts │ │ │ │ │ │ │ ├── repro-duplicate-instruction-from-merge-consecutive-scopes.expect.md │ │ │ │ │ │ │ ├── repro-duplicate-instruction-from-merge-consecutive-scopes.js │ │ │ │ │ │ │ ├── repro-duplicate-type-import.expect.md │ │ │ │ │ │ │ ├── repro-duplicate-type-import.tsx │ │ │ │ │ │ │ ├── repro-false-positive-ref-validation-in-use-effect.expect.md │ │ │ │ │ │ │ ├── repro-false-positive-ref-validation-in-use-effect.js │ │ │ │ │ │ │ ├── repro-for-in-in-try.expect.md │ │ │ │ │ │ │ ├── repro-for-in-in-try.js │ │ │ │ │ │ │ ├── repro-for-loop-in-try.expect.md │ │ │ │ │ │ │ ├── repro-for-loop-in-try.js │ │ │ │ │ │ │ ├── repro-for-of-in-try.expect.md │ │ │ │ │ │ │ ├── repro-for-of-in-try.js │ │ │ │ │ │ │ ├── repro-hoisting-variable-collision.expect.md │ │ │ │ │ │ │ ├── repro-hoisting-variable-collision.js │ │ │ │ │ │ │ ├── repro-hoisting.expect.md │ │ │ │ │ │ │ ├── repro-hoisting.js │ │ │ │ │ │ │ ├── repro-independently-memoized-property-load-for-method-call.expect.md │ │ │ │ │ │ │ ├── repro-independently-memoized-property-load-for-method-call.js │ │ │ │ │ │ │ ├── repro-instruction-part-of-already-closed-scope.expect.md │ │ │ │ │ │ │ ├── repro-instruction-part-of-already-closed-scope.js │ │ │ │ │ │ │ ├── repro-invalid-destructuring-reassignment-undefined-variable.expect.md │ │ │ │ │ │ │ ├── repro-invalid-destructuring-reassignment-undefined-variable.js │ │ │ │ │ │ │ ├── repro-invalid-phi-as-dependency.expect.md │ │ │ │ │ │ │ ├── repro-invalid-phi-as-dependency.tsx │ │ │ │ │ │ │ ├── repro-invalid-pruned-scope-leaks-value-via-alias.expect.md │ │ │ │ │ │ │ ├── repro-invalid-pruned-scope-leaks-value-via-alias.ts │ │ │ │ │ │ │ ├── repro-invalid-pruned-scope-leaks-value.expect.md │ │ │ │ │ │ │ ├── repro-invalid-pruned-scope-leaks-value.ts │ │ │ │ │ │ │ ├── repro-invalid-reactivity-value-block.expect.md │ │ │ │ │ │ │ ├── repro-invalid-reactivity-value-block.ts │ │ │ │ │ │ │ ├── repro-invalid-scope-merging-value-blocks.expect.md │ │ │ │ │ │ │ ├── repro-invalid-scope-merging-value-blocks.ts │ │ │ │ │ │ │ ├── repro-local-mutation-of-new-object-from-destructured-prop.expect.md │ │ │ │ │ │ │ ├── repro-local-mutation-of-new-object-from-destructured-prop.js │ │ │ │ │ │ │ ├── repro-memoize-array-with-immutable-map-after-hook.expect.md │ │ │ │ │ │ │ ├── repro-memoize-array-with-immutable-map-after-hook.js │ │ │ │ │ │ │ ├── repro-memoize-for-of-collection-when-loop-body-returns.expect.md │ │ │ │ │ │ │ ├── repro-memoize-for-of-collection-when-loop-body-returns.js │ │ │ │ │ │ │ ├── repro-missing-dependency-if-within-while.expect.md │ │ │ │ │ │ │ ├── repro-missing-dependency-if-within-while.js │ │ │ │ │ │ │ ├── repro-missing-memoization-lack-of-phi-types.expect.md │ │ │ │ │ │ │ ├── repro-missing-memoization-lack-of-phi-types.js │ │ │ │ │ │ │ ├── repro-missing-phi-after-dce-merge-scopes.expect.md │ │ │ │ │ │ │ ├── repro-missing-phi-after-dce-merge-scopes.js │ │ │ │ │ │ │ ├── repro-mutable-range-extending-into-ternary.expect.md │ │ │ │ │ │ │ ├── repro-mutable-range-extending-into-ternary.js │ │ │ │ │ │ │ ├── repro-mutate-ref-in-function-passed-to-hook.expect.md │ │ │ │ │ │ │ ├── repro-mutate-ref-in-function-passed-to-hook.js │ │ │ │ │ │ │ ├── repro-mutate-result-of-function-call-with-frozen-argument-in-function-expression.expect.md │ │ │ │ │ │ │ ├── repro-mutate-result-of-function-call-with-frozen-argument-in-function-expression.js │ │ │ │ │ │ │ ├── repro-mutate-result-of-method-call-on-frozen-value-in-function-expression.expect.md │ │ │ │ │ │ │ ├── repro-mutate-result-of-method-call-on-frozen-value-in-function-expression.js │ │ │ │ │ │ │ ├── repro-mutate-result-of-method-call-on-frozen-value-is-allowed.expect.md │ │ │ │ │ │ │ ├── repro-mutate-result-of-method-call-on-frozen-value-is-allowed.js │ │ │ │ │ │ │ ├── repro-nested-try-catch-in-usememo.expect.md │ │ │ │ │ │ │ ├── repro-nested-try-catch-in-usememo.js │ │ │ │ │ │ │ ├── repro-no-declarations-in-reactive-scope-with-early-return.expect.md │ │ │ │ │ │ │ ├── repro-no-declarations-in-reactive-scope-with-early-return.js │ │ │ │ │ │ │ ├── repro-no-value-for-temporary-reactive-scope-with-early-return.expect.md │ │ │ │ │ │ │ ├── repro-no-value-for-temporary-reactive-scope-with-early-return.js │ │ │ │ │ │ │ ├── repro-no-value-for-temporary.expect.md │ │ │ │ │ │ │ ├── repro-no-value-for-temporary.js │ │ │ │ │ │ │ ├── repro-non-identifier-object-keys.expect.md │ │ │ │ │ │ │ ├── repro-non-identifier-object-keys.ts │ │ │ │ │ │ │ ├── repro-object-expression-computed-key-modified-during-after-construction-hoisted-sequence-expr.expect.md │ │ │ │ │ │ │ ├── repro-object-expression-computed-key-modified-during-after-construction-hoisted-sequence-expr.js │ │ │ │ │ │ │ ├── repro-object-fromEntries-entries.expect.md │ │ │ │ │ │ │ ├── repro-object-fromEntries-entries.js │ │ │ │ │ │ │ ├── repro-object-pattern.expect.md │ │ │ │ │ │ │ ├── repro-object-pattern.js │ │ │ │ │ │ │ ├── repro-preds-undefined-try-catch-return-primitive.expect.md │ │ │ │ │ │ │ ├── repro-preds-undefined-try-catch-return-primitive.js │ │ │ │ │ │ │ ├── repro-preserve-memoization-inner-destructured-value-mistaken-as-dependency.expect.md │ │ │ │ │ │ │ ├── repro-preserve-memoization-inner-destructured-value-mistaken-as-dependency.js │ │ │ │ │ │ │ ├── repro-propagate-type-of-ternary-jsx.expect.md │ │ │ │ │ │ │ ├── repro-propagate-type-of-ternary-jsx.js │ │ │ │ │ │ │ ├── repro-propagate-type-of-ternary-nested.expect.md │ │ │ │ │ │ │ ├── repro-propagate-type-of-ternary-nested.js │ │ │ │ │ │ │ ├── repro-reassign-props.expect.md │ │ │ │ │ │ │ ├── repro-reassign-props.js │ │ │ │ │ │ │ ├── repro-reassign-to-variable-without-mutable-range.expect.md │ │ │ │ │ │ │ ├── repro-reassign-to-variable-without-mutable-range.js │ │ │ │ │ │ │ ├── repro-ref-mutable-range.expect.md │ │ │ │ │ │ │ ├── repro-ref-mutable-range.tsx │ │ │ │ │ │ │ ├── repro-renaming-conflicting-decls.expect.md │ │ │ │ │ │ │ ├── repro-renaming-conflicting-decls.js │ │ │ │ │ │ │ ├── repro-retain-source-when-bailout.expect.md │ │ │ │ │ │ │ ├── repro-retain-source-when-bailout.js │ │ │ │ │ │ │ ├── repro-returned-inner-fn-mutates-context.expect.md │ │ │ │ │ │ │ ├── repro-returned-inner-fn-mutates-context.js │ │ │ │ │ │ │ ├── repro-returned-inner-fn-reassigns-context.expect.md │ │ │ │ │ │ │ ├── repro-returned-inner-fn-reassigns-context.js │ │ │ │ │ │ │ ├── repro-scope-missing-mutable-range.expect.md │ │ │ │ │ │ │ ├── repro-scope-missing-mutable-range.js │ │ │ │ │ │ │ ├── repro-separate-memoization-due-to-callback-capturing.expect.md │ │ │ │ │ │ │ ├── repro-separate-memoization-due-to-callback-capturing.js │ │ │ │ │ │ │ ├── repro-separate-scopes-for-divs.expect.md │ │ │ │ │ │ │ ├── repro-separate-scopes-for-divs.js │ │ │ │ │ │ │ ├── repro-slow-validate-preserve-memo.expect.md │ │ │ │ │ │ │ ├── repro-slow-validate-preserve-memo.ts │ │ │ │ │ │ │ ├── repro-stale-closure-forward-reference.expect.md │ │ │ │ │ │ │ ├── repro-stale-closure-forward-reference.js │ │ │ │ │ │ │ ├── repro-undefined-expression-of-jsxexpressioncontainer.expect.md │ │ │ │ │ │ │ ├── repro-undefined-expression-of-jsxexpressioncontainer.js │ │ │ │ │ │ │ ├── repro-unmerged-fbt-call-merge-overlapping-reactive-scopes.expect.md │ │ │ │ │ │ │ ├── repro-unmerged-fbt-call-merge-overlapping-reactive-scopes.js │ │ │ │ │ │ │ ├── repro-unreachable-code-early-return-in-useMemo.expect.md │ │ │ │ │ │ │ ├── repro-unreachable-code-early-return-in-useMemo.js │ │ │ │ │ │ │ ├── repro-useMemo-if-else-both-early-return.expect.md │ │ │ │ │ │ │ ├── repro-useMemo-if-else-both-early-return.js │ │ │ │ │ │ │ ├── repro.expect.md │ │ │ │ │ │ │ ├── repro.js │ │ │ │ │ │ │ ├── resolve-react-hooks-based-on-import-name.expect.md │ │ │ │ │ │ │ ├── resolve-react-hooks-based-on-import-name.js │ │ │ │ │ │ │ ├── rest-param-with-array-pattern.expect.md │ │ │ │ │ │ │ ├── rest-param-with-array-pattern.js │ │ │ │ │ │ │ ├── rest-param-with-identifier.expect.md │ │ │ │ │ │ │ ├── rest-param-with-identifier.js │ │ │ │ │ │ │ ├── rest-param-with-object-spread-pattern.expect.md │ │ │ │ │ │ │ ├── rest-param-with-object-spread-pattern.js │ │ │ │ │ │ │ ├── return-conditional.expect.md │ │ │ │ │ │ │ ├── return-conditional.js │ │ │ │ │ │ │ ├── return-ref-callback-structure.expect.md │ │ │ │ │ │ │ ├── return-ref-callback-structure.js │ │ │ │ │ │ │ ├── return-ref-callback.expect.md │ │ │ │ │ │ │ ├── return-ref-callback.js │ │ │ │ │ │ │ ├── return-undefined.expect.md │ │ │ │ │ │ │ ├── return-undefined.js │ │ │ │ │ │ │ ├── reverse-postorder.expect.md │ │ │ │ │ │ │ ├── reverse-postorder.js │ │ │ │ │ │ │ ├── rewrite-phis-in-lambda-capture-context.expect.md │ │ │ │ │ │ │ ├── rewrite-phis-in-lambda-capture-context.js │ │ │ │ │ │ │ ├── rules-of-hooks/ │ │ │ │ │ │ │ │ ├── allow-locals-named-like-hooks.expect.md │ │ │ │ │ │ │ │ ├── allow-locals-named-like-hooks.js │ │ │ │ │ │ │ │ ├── allow-props-named-like-hooks.expect.md │ │ │ │ │ │ │ │ ├── allow-props-named-like-hooks.js │ │ │ │ │ │ │ │ ├── error.bail.rules-of-hooks-3d692676194b.expect.md │ │ │ │ │ │ │ │ ├── error.bail.rules-of-hooks-3d692676194b.js │ │ │ │ │ │ │ │ ├── error.bail.rules-of-hooks-8503ca76d6f8.expect.md │ │ │ │ │ │ │ │ ├── error.bail.rules-of-hooks-8503ca76d6f8.js │ │ │ │ │ │ │ │ ├── error.invalid-call-phi-possibly-hook.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-call-phi-possibly-hook.js │ │ │ │ │ │ │ │ ├── error.invalid-conditionally-call-local-named-like-hook.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-conditionally-call-local-named-like-hook.js │ │ │ │ │ │ │ │ ├── error.invalid-conditionally-call-prop-named-like-hook.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-conditionally-call-prop-named-like-hook.js │ │ │ │ │ │ │ │ ├── error.invalid-conditionally-methodcall-hooklike-property-of-local.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-conditionally-methodcall-hooklike-property-of-local.js │ │ │ │ │ │ │ │ ├── error.invalid-condtionally-call-hooklike-property-of-local.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-condtionally-call-hooklike-property-of-local.js │ │ │ │ │ │ │ │ ├── error.invalid-dynamic-hook-via-hooklike-local.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-dynamic-hook-via-hooklike-local.js │ │ │ │ │ │ │ │ ├── error.invalid-hook-after-early-return.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-hook-after-early-return.js │ │ │ │ │ │ │ │ ├── error.invalid-hook-as-conditional-test.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-hook-as-conditional-test.js │ │ │ │ │ │ │ │ ├── error.invalid-hook-as-prop.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-hook-as-prop.js │ │ │ │ │ │ │ │ ├── error.invalid-hook-for.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-hook-for.js │ │ │ │ │ │ │ │ ├── error.invalid-hook-from-hook-return.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-hook-from-hook-return.js │ │ │ │ │ │ │ │ ├── error.invalid-hook-from-property-of-other-hook.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-hook-from-property-of-other-hook.js │ │ │ │ │ │ │ │ ├── error.invalid-hook-if-alternate.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-hook-if-alternate.js │ │ │ │ │ │ │ │ ├── error.invalid-hook-if-consequent.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-hook-if-consequent.js │ │ │ │ │ │ │ │ ├── error.invalid-hook-in-nested-function-expression-object-expression.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-hook-in-nested-function-expression-object-expression.js │ │ │ │ │ │ │ │ ├── error.invalid-hook-in-nested-object-method.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-hook-in-nested-object-method.js │ │ │ │ │ │ │ │ ├── error.invalid-hook-optional-methodcall.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-hook-optional-methodcall.js │ │ │ │ │ │ │ │ ├── error.invalid-hook-optional-property.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-hook-optional-property.js │ │ │ │ │ │ │ │ ├── error.invalid-hook-optionalcall.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-hook-optionalcall.js │ │ │ │ │ │ │ │ ├── error.invalid-hook-reassigned-in-conditional.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-hook-reassigned-in-conditional.js │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-1b9527f967f3.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-1b9527f967f3.js │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-2aabd222fc6a.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-2aabd222fc6a.js │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-49d341e5d68f.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-49d341e5d68f.js │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-79128a755612.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-79128a755612.js │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-9718e30b856c.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-9718e30b856c.js │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-9bf17c174134.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-9bf17c174134.js │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-b4dcda3d60ed.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-b4dcda3d60ed.js │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-c906cace44e9.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-c906cace44e9.js │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-d740d54e9c21.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-d740d54e9c21.js │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-d85c144bdf40.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-d85c144bdf40.js │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-ea7c2fb545a9.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-ea7c2fb545a9.js │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-f3d6c5e9c83d.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-f3d6c5e9c83d.js │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-f69800950ff0.expect.md │ │ │ │ │ │ │ │ ├── error.invalid-rules-of-hooks-f69800950ff0.js │ │ │ │ │ │ │ │ ├── error.invalid.invalid-rules-of-hooks-0a1dbff27ba0.expect.md │ │ │ │ │ │ │ │ ├── error.invalid.invalid-rules-of-hooks-0a1dbff27ba0.js │ │ │ │ │ │ │ │ ├── error.invalid.invalid-rules-of-hooks-0de1224ce64b.expect.md │ │ │ │ │ │ │ │ ├── error.invalid.invalid-rules-of-hooks-0de1224ce64b.js │ │ │ │ │ │ │ │ ├── error.invalid.invalid-rules-of-hooks-449a37146a83.expect.md │ │ │ │ │ │ │ │ ├── error.invalid.invalid-rules-of-hooks-449a37146a83.js │ │ │ │ │ │ │ │ ├── error.invalid.invalid-rules-of-hooks-76a74b4666e9.expect.md │ │ │ │ │ │ │ │ ├── error.invalid.invalid-rules-of-hooks-76a74b4666e9.js │ │ │ │ │ │ │ │ ├── error.invalid.invalid-rules-of-hooks-d842d36db450.expect.md │ │ │ │ │ │ │ │ ├── error.invalid.invalid-rules-of-hooks-d842d36db450.js │ │ │ │ │ │ │ │ ├── error.invalid.invalid-rules-of-hooks-d952b82c2597.expect.md │ │ │ │ │ │ │ │ ├── error.invalid.invalid-rules-of-hooks-d952b82c2597.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-0592bd574811.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-0592bd574811.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-0e2214abc294.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-0e2214abc294.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-1ff6c3fbbc94.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-1ff6c3fbbc94.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-23dc7fffde57.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-23dc7fffde57.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-2bec02ac982b.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-2bec02ac982b.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-2e405c78cb80.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-2e405c78cb80.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-33a6e23edac1.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-33a6e23edac1.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-347b0dae66f1.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-347b0dae66f1.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-485bf041f55f.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-485bf041f55f.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-4f6c78a14bf7.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-4f6c78a14bf7.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-69521d94fa03.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-69521d94fa03.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-7e52f5eec669.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-7e52f5eec669.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-844a496db20b.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-844a496db20b.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-8f1c2c3f71c9.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-8f1c2c3f71c9.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-93dc5d5e538a.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-93dc5d5e538a.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-9a47e97b5d13.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-9a47e97b5d13.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-9d7879272ff6.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-9d7879272ff6.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-c1e8c7f4c191.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-c1e8c7f4c191.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-c5d1f3143c4c.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-c5d1f3143c4c.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-cfdfe5572fc7.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-cfdfe5572fc7.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-df4d750736f3.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-df4d750736f3.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-dfde14171fcd.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-dfde14171fcd.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-e5dd6caf4084.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-e5dd6caf4084.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-e66a744cffbe.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-e66a744cffbe.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-eacfcaa6ef89.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-eacfcaa6ef89.js │ │ │ │ │ │ │ │ ├── rules-of-hooks-fe6042f7628b.expect.md │ │ │ │ │ │ │ │ ├── rules-of-hooks-fe6042f7628b.js │ │ │ │ │ │ │ │ ├── todo.bail.rules-of-hooks-279ac76f53af.expect.md │ │ │ │ │ │ │ │ ├── todo.bail.rules-of-hooks-279ac76f53af.js │ │ │ │ │ │ │ │ ├── todo.bail.rules-of-hooks-28a78701970c.expect.md │ │ │ │ │ │ │ │ ├── todo.bail.rules-of-hooks-28a78701970c.js │ │ │ │ │ │ │ │ ├── todo.bail.rules-of-hooks-6949b255e7eb.expect.md │ │ │ │ │ │ │ │ ├── todo.bail.rules-of-hooks-6949b255e7eb.js │ │ │ │ │ │ │ │ ├── todo.bail.rules-of-hooks-e0a5db3ae21e.expect.md │ │ │ │ │ │ │ │ ├── todo.bail.rules-of-hooks-e0a5db3ae21e.js │ │ │ │ │ │ │ │ ├── todo.bail.rules-of-hooks-e9f9bac89f8f.expect.md │ │ │ │ │ │ │ │ ├── todo.bail.rules-of-hooks-e9f9bac89f8f.js │ │ │ │ │ │ │ │ ├── todo.bail.rules-of-hooks-fadd52c1e460.expect.md │ │ │ │ │ │ │ │ ├── todo.bail.rules-of-hooks-fadd52c1e460.js │ │ │ │ │ │ │ │ ├── todo.error.invalid-rules-of-hooks-368024110a58.expect.md │ │ │ │ │ │ │ │ ├── todo.error.invalid-rules-of-hooks-368024110a58.js │ │ │ │ │ │ │ │ ├── todo.error.invalid-rules-of-hooks-8566f9a360e2.expect.md │ │ │ │ │ │ │ │ ├── todo.error.invalid-rules-of-hooks-8566f9a360e2.js │ │ │ │ │ │ │ │ ├── todo.error.invalid-rules-of-hooks-a0058f0b446d.expect.md │ │ │ │ │ │ │ │ ├── todo.error.invalid-rules-of-hooks-a0058f0b446d.js │ │ │ │ │ │ │ │ ├── todo.error.rules-of-hooks-27c18dc8dad2.expect.md │ │ │ │ │ │ │ │ ├── todo.error.rules-of-hooks-27c18dc8dad2.js │ │ │ │ │ │ │ │ ├── todo.error.rules-of-hooks-d0935abedc42.expect.md │ │ │ │ │ │ │ │ ├── todo.error.rules-of-hooks-d0935abedc42.js │ │ │ │ │ │ │ │ ├── todo.error.rules-of-hooks-e29c874aa913.expect.md │ │ │ │ │ │ │ │ ├── todo.error.rules-of-hooks-e29c874aa913.js │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-191029ac48c8.expect.md │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-191029ac48c8.js │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-206e2811c87c.expect.md │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-206e2811c87c.js │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-28a7111f56a7.expect.md │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-28a7111f56a7.js │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-2c51251df67a.expect.md │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-2c51251df67a.js │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-5a7ac9a6e8fa.expect.md │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-5a7ac9a6e8fa.js │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-8303403b8e4c.expect.md │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-8303403b8e4c.js │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-99b5c750d1d1.expect.md │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-99b5c750d1d1.js │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-9c79feec4b9b.expect.md │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-9c79feec4b9b.js │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-a63fd4f9dcc0.expect.md │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-a63fd4f9dcc0.js │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-acb56658fe7e.expect.md │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-acb56658fe7e.js │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-c59788ef5676.expect.md │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-c59788ef5676.js │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-ddeca9708b63.expect.md │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-ddeca9708b63.js │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-e675f0a672d8.expect.md │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-e675f0a672d8.js │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-e69ffce323c3.expect.md │ │ │ │ │ │ │ │ ├── todo.invalid.invalid-rules-of-hooks-e69ffce323c3.js │ │ │ │ │ │ │ │ └── todo.invalid.invalid-rules-of-hooks-f6f37b63b2d4 │ │ │ │ │ │ │ ├── same-variable-as-dep-and-redeclare-maybe-frozen.expect.md │ │ │ │ │ │ │ ├── same-variable-as-dep-and-redeclare-maybe-frozen.js │ │ │ │ │ │ │ ├── same-variable-as-dep-and-redeclare.expect.md │ │ │ │ │ │ │ ├── same-variable-as-dep-and-redeclare.js │ │ │ │ │ │ │ ├── script-source-type.expect.md │ │ │ │ │ │ │ ├── script-source-type.js │ │ │ │ │ │ │ ├── sequence-expression.expect.md │ │ │ │ │ │ │ ├── sequence-expression.js │ │ │ │ │ │ │ ├── sequential-destructuring-assignment-to-scope-declarations.expect.md │ │ │ │ │ │ │ ├── sequential-destructuring-assignment-to-scope-declarations.js │ │ │ │ │ │ │ ├── sequential-destructuring-both-mixed-local-and-scope-declaration.expect.md │ │ │ │ │ │ │ ├── sequential-destructuring-both-mixed-local-and-scope-declaration.js │ │ │ │ │ │ │ ├── sequentially-constant-progagatable-if-test-conditions.expect.md │ │ │ │ │ │ │ ├── sequentially-constant-progagatable-if-test-conditions.js │ │ │ │ │ │ │ ├── shapes-object-key.expect.md │ │ │ │ │ │ │ ├── shapes-object-key.ts │ │ │ │ │ │ │ ├── should-bailout-without-compilation-annotation-mode.expect.md │ │ │ │ │ │ │ ├── should-bailout-without-compilation-annotation-mode.js │ │ │ │ │ │ │ ├── should-bailout-without-compilation-infer-mode.expect.md │ │ │ │ │ │ │ ├── should-bailout-without-compilation-infer-mode.js │ │ │ │ │ │ │ ├── simple-alias.expect.md │ │ │ │ │ │ │ ├── simple-alias.js │ │ │ │ │ │ │ ├── simple-function-1.expect.md │ │ │ │ │ │ │ ├── simple-function-1.js │ │ │ │ │ │ │ ├── simple-scope.expect.md │ │ │ │ │ │ │ ├── simple-scope.js │ │ │ │ │ │ │ ├── simple.expect.md │ │ │ │ │ │ │ ├── simple.js │ │ │ │ │ │ │ ├── skip-useMemoCache.expect.md │ │ │ │ │ │ │ ├── skip-useMemoCache.js │ │ │ │ │ │ │ ├── ssa-arrayexpression.expect.md │ │ │ │ │ │ │ ├── ssa-arrayexpression.js │ │ │ │ │ │ │ ├── ssa-call-jsx-2.expect.md │ │ │ │ │ │ │ ├── ssa-call-jsx-2.js │ │ │ │ │ │ │ ├── ssa-call-jsx.expect.md │ │ │ │ │ │ │ ├── ssa-call-jsx.js │ │ │ │ │ │ │ ├── ssa-cascading-eliminated-phis.expect.md │ │ │ │ │ │ │ ├── ssa-cascading-eliminated-phis.js │ │ │ │ │ │ │ ├── ssa-complex-multiple-if.expect.md │ │ │ │ │ │ │ ├── ssa-complex-multiple-if.js │ │ │ │ │ │ │ ├── ssa-complex-single-if.expect.md │ │ │ │ │ │ │ ├── ssa-complex-single-if.js │ │ │ │ │ │ │ ├── ssa-for-of.expect.md │ │ │ │ │ │ │ ├── ssa-for-of.js │ │ │ │ │ │ │ ├── ssa-for-trivial-update.expect.md │ │ │ │ │ │ │ ├── ssa-for-trivial-update.js │ │ │ │ │ │ │ ├── ssa-for.expect.md │ │ │ │ │ │ │ ├── ssa-for.js │ │ │ │ │ │ │ ├── ssa-if-else.expect.md │ │ │ │ │ │ │ ├── ssa-if-else.js │ │ │ │ │ │ │ ├── ssa-leave-case.expect.md │ │ │ │ │ │ │ ├── ssa-leave-case.js │ │ │ │ │ │ │ ├── ssa-multiple-phis.expect.md │ │ │ │ │ │ │ ├── ssa-multiple-phis.js │ │ │ │ │ │ │ ├── ssa-nested-loops-no-reassign.expect.md │ │ │ │ │ │ │ ├── ssa-nested-loops-no-reassign.js │ │ │ │ │ │ │ ├── ssa-nested-partial-phi.expect.md │ │ │ │ │ │ │ ├── ssa-nested-partial-phi.js │ │ │ │ │ │ │ ├── ssa-nested-partial-reassignment.expect.md │ │ │ │ │ │ │ ├── ssa-nested-partial-reassignment.js │ │ │ │ │ │ │ ├── ssa-newexpression.expect.md │ │ │ │ │ │ │ ├── ssa-newexpression.js │ │ │ │ │ │ │ ├── ssa-non-empty-initializer.expect.md │ │ │ │ │ │ │ ├── ssa-non-empty-initializer.js │ │ │ │ │ │ │ ├── ssa-objectexpression-phi.expect.md │ │ │ │ │ │ │ ├── ssa-objectexpression-phi.js │ │ │ │ │ │ │ ├── ssa-objectexpression.expect.md │ │ │ │ │ │ │ ├── ssa-objectexpression.js │ │ │ │ │ │ │ ├── ssa-property-alias-alias-mutate-if.expect.md │ │ │ │ │ │ │ ├── ssa-property-alias-alias-mutate-if.js │ │ │ │ │ │ │ ├── ssa-property-alias-if.expect.md │ │ │ │ │ │ │ ├── ssa-property-alias-if.js │ │ │ │ │ │ │ ├── ssa-property-alias-mutate-if.expect.md │ │ │ │ │ │ │ ├── ssa-property-alias-mutate-if.js │ │ │ │ │ │ │ ├── ssa-property-alias-mutate-inside-if.expect.md │ │ │ │ │ │ │ ├── ssa-property-alias-mutate-inside-if.js │ │ │ │ │ │ │ ├── ssa-property-alias-mutate.expect.md │ │ │ │ │ │ │ ├── ssa-property-alias-mutate.js │ │ │ │ │ │ │ ├── ssa-property-call.expect.md │ │ │ │ │ │ │ ├── ssa-property-call.js │ │ │ │ │ │ │ ├── ssa-property-mutate-2.expect.md │ │ │ │ │ │ │ ├── ssa-property-mutate-2.js │ │ │ │ │ │ │ ├── ssa-property-mutate-alias.expect.md │ │ │ │ │ │ │ ├── ssa-property-mutate-alias.js │ │ │ │ │ │ │ ├── ssa-property-mutate.expect.md │ │ │ │ │ │ │ ├── ssa-property-mutate.js │ │ │ │ │ │ │ ├── ssa-property.expect.md │ │ │ │ │ │ │ ├── ssa-property.js │ │ │ │ │ │ │ ├── ssa-reassign-in-rval.expect.md │ │ │ │ │ │ │ ├── ssa-reassign-in-rval.js │ │ │ │ │ │ │ ├── ssa-reassign.expect.md │ │ │ │ │ │ │ ├── ssa-reassign.js │ │ │ │ │ │ │ ├── ssa-renaming-ternary-destruction-with-mutation.expect.md │ │ │ │ │ │ │ ├── ssa-renaming-ternary-destruction-with-mutation.js │ │ │ │ │ │ │ ├── ssa-renaming-ternary-destruction.expect.md │ │ │ │ │ │ │ ├── ssa-renaming-ternary-destruction.js │ │ │ │ │ │ │ ├── ssa-renaming-ternary-with-mutation.expect.md │ │ │ │ │ │ │ ├── ssa-renaming-ternary-with-mutation.js │ │ │ │ │ │ │ ├── ssa-renaming-ternary.expect.md │ │ │ │ │ │ │ ├── ssa-renaming-ternary.js │ │ │ │ │ │ │ ├── ssa-renaming-unconditional-ternary-with-mutation.expect.md │ │ │ │ │ │ │ ├── ssa-renaming-unconditional-ternary-with-mutation.js │ │ │ │ │ │ │ ├── ssa-renaming-unconditional-ternary.expect.md │ │ │ │ │ │ │ ├── ssa-renaming-unconditional-ternary.js │ │ │ │ │ │ │ ├── ssa-renaming-unconditional-with-mutation.expect.md │ │ │ │ │ │ │ ├── ssa-renaming-unconditional-with-mutation.js │ │ │ │ │ │ │ ├── ssa-renaming-via-destructuring-with-mutation.expect.md │ │ │ │ │ │ │ ├── ssa-renaming-via-destructuring-with-mutation.js │ │ │ │ │ │ │ ├── ssa-renaming-via-destructuring.expect.md │ │ │ │ │ │ │ ├── ssa-renaming-via-destructuring.js │ │ │ │ │ │ │ ├── ssa-renaming-with-mutation.expect.md │ │ │ │ │ │ │ ├── ssa-renaming-with-mutation.js │ │ │ │ │ │ │ ├── ssa-renaming.expect.md │ │ │ │ │ │ │ ├── ssa-renaming.js │ │ │ │ │ │ │ ├── ssa-return.expect.md │ │ │ │ │ │ │ ├── ssa-return.js │ │ │ │ │ │ │ ├── ssa-shadowing.expect.md │ │ │ │ │ │ │ ├── ssa-shadowing.js │ │ │ │ │ │ │ ├── ssa-sibling-phis.expect.md │ │ │ │ │ │ │ ├── ssa-sibling-phis.js │ │ │ │ │ │ │ ├── ssa-simple-phi.expect.md │ │ │ │ │ │ │ ├── ssa-simple-phi.js │ │ │ │ │ │ │ ├── ssa-simple.expect.md │ │ │ │ │ │ │ ├── ssa-simple.js │ │ │ │ │ │ │ ├── ssa-single-if.expect.md │ │ │ │ │ │ │ ├── ssa-single-if.js │ │ │ │ │ │ │ ├── ssa-switch.expect.md │ │ │ │ │ │ │ ├── ssa-switch.js │ │ │ │ │ │ │ ├── ssa-throw.expect.md │ │ │ │ │ │ │ ├── ssa-throw.js │ │ │ │ │ │ │ ├── ssa-while-no-reassign.expect.md │ │ │ │ │ │ │ ├── ssa-while-no-reassign.js │ │ │ │ │ │ │ ├── ssa-while.expect.md │ │ │ │ │ │ │ ├── ssa-while.js │ │ │ │ │ │ │ ├── ssr/ │ │ │ │ │ │ │ │ ├── optimize-ssr.expect.md │ │ │ │ │ │ │ │ ├── optimize-ssr.js │ │ │ │ │ │ │ │ ├── ssr-infer-event-handlers-from-setState.expect.md │ │ │ │ │ │ │ │ ├── ssr-infer-event-handlers-from-setState.js │ │ │ │ │ │ │ │ ├── ssr-infer-event-handlers-from-startTransition.expect.md │ │ │ │ │ │ │ │ ├── ssr-infer-event-handlers-from-startTransition.js │ │ │ │ │ │ │ │ ├── ssr-use-reducer-initializer.expect.md │ │ │ │ │ │ │ │ ├── ssr-use-reducer-initializer.js │ │ │ │ │ │ │ │ ├── ssr-use-reducer.expect.md │ │ │ │ │ │ │ │ └── ssr-use-reducer.js │ │ │ │ │ │ │ ├── static-components/ │ │ │ │ │ │ │ │ ├── invalid-conditionally-assigned-dynamically-constructed-component-in-render.expect.md │ │ │ │ │ │ │ │ ├── invalid-conditionally-assigned-dynamically-constructed-component-in-render.js │ │ │ │ │ │ │ │ ├── invalid-dynamically-construct-component-in-render.expect.md │ │ │ │ │ │ │ │ ├── invalid-dynamically-construct-component-in-render.js │ │ │ │ │ │ │ │ ├── invalid-dynamically-constructed-component-function.expect.md │ │ │ │ │ │ │ │ ├── invalid-dynamically-constructed-component-function.js │ │ │ │ │ │ │ │ ├── invalid-dynamically-constructed-component-method-call.expect.md │ │ │ │ │ │ │ │ ├── invalid-dynamically-constructed-component-method-call.js │ │ │ │ │ │ │ │ ├── invalid-dynamically-constructed-component-new.expect.md │ │ │ │ │ │ │ │ └── invalid-dynamically-constructed-component-new.js │ │ │ │ │ │ │ ├── store-via-call.expect.md │ │ │ │ │ │ │ ├── store-via-call.js │ │ │ │ │ │ │ ├── store-via-new.expect.md │ │ │ │ │ │ │ ├── store-via-new.js │ │ │ │ │ │ │ ├── switch-global-propertyload-case-test.expect.md │ │ │ │ │ │ │ ├── switch-global-propertyload-case-test.js │ │ │ │ │ │ │ ├── switch-non-final-default.expect.md │ │ │ │ │ │ │ ├── switch-non-final-default.js │ │ │ │ │ │ │ ├── switch-with-fallthrough.expect.md │ │ │ │ │ │ │ ├── switch-with-fallthrough.js │ │ │ │ │ │ │ ├── switch-with-only-default.expect.md │ │ │ │ │ │ │ ├── switch-with-only-default.js │ │ │ │ │ │ │ ├── switch.expect.md │ │ │ │ │ │ │ ├── switch.js │ │ │ │ │ │ │ ├── tagged-template-in-hook.expect.md │ │ │ │ │ │ │ ├── tagged-template-in-hook.js │ │ │ │ │ │ │ ├── tagged-template-literal.expect.md │ │ │ │ │ │ │ ├── tagged-template-literal.js │ │ │ │ │ │ │ ├── target-flag-meta-internal.expect.md │ │ │ │ │ │ │ ├── target-flag-meta-internal.js │ │ │ │ │ │ │ ├── target-flag.expect.md │ │ │ │ │ │ │ ├── target-flag.js │ │ │ │ │ │ │ ├── template-literal.expect.md │ │ │ │ │ │ │ ├── template-literal.js │ │ │ │ │ │ │ ├── temporary-accessed-outside-scope.expect.md │ │ │ │ │ │ │ ├── temporary-accessed-outside-scope.js │ │ │ │ │ │ │ ├── temporary-at-start-of-value-block.expect.md │ │ │ │ │ │ │ ├── temporary-at-start-of-value-block.js │ │ │ │ │ │ │ ├── temporary-property-load-accessed-outside-scope.expect.md │ │ │ │ │ │ │ ├── temporary-property-load-accessed-outside-scope.js │ │ │ │ │ │ │ ├── ternary-assignment-expression.expect.md │ │ │ │ │ │ │ ├── ternary-assignment-expression.js │ │ │ │ │ │ │ ├── ternary-expression.expect.md │ │ │ │ │ │ │ ├── ternary-expression.js │ │ │ │ │ │ │ ├── timers.expect.md │ │ │ │ │ │ │ ├── timers.js │ │ │ │ │ │ │ ├── todo-function-expression-captures-value-later-frozen.expect.md │ │ │ │ │ │ │ ├── todo-function-expression-captures-value-later-frozen.js │ │ │ │ │ │ │ ├── todo-global-load-cached.expect.md │ │ │ │ │ │ │ ├── todo-global-load-cached.tsx │ │ │ │ │ │ │ ├── todo-global-property-load-cached.expect.md │ │ │ │ │ │ │ ├── todo-global-property-load-cached.tsx │ │ │ │ │ │ │ ├── todo-granular-iterator-semantics.expect.md │ │ │ │ │ │ │ ├── todo-granular-iterator-semantics.js │ │ │ │ │ │ │ ├── todo-optional-call-chain-in-optional.expect.md │ │ │ │ │ │ │ ├── todo-optional-call-chain-in-optional.ts │ │ │ │ │ │ │ ├── todo.error.object-pattern-computed-key.expect.md │ │ │ │ │ │ │ ├── todo.error.object-pattern-computed-key.js │ │ │ │ │ │ │ ├── todo.memoize-loops-that-produce-memoizeable-values.expect.md │ │ │ │ │ │ │ ├── todo.memoize-loops-that-produce-memoizeable-values.js │ │ │ │ │ │ │ ├── todo.unnecessary-lambda-memoization.expect.md │ │ │ │ │ │ │ ├── todo.unnecessary-lambda-memoization.js │ │ │ │ │ │ │ ├── transitive-alias-fields.expect.md │ │ │ │ │ │ │ ├── transitive-alias-fields.js │ │ │ │ │ │ │ ├── transitive-freeze-array.expect.md │ │ │ │ │ │ │ ├── transitive-freeze-array.js │ │ │ │ │ │ │ ├── transitive-freeze-function-expressions.expect.md │ │ │ │ │ │ │ ├── transitive-freeze-function-expressions.js │ │ │ │ │ │ │ ├── trivial.expect.md │ │ │ │ │ │ │ ├── trivial.js │ │ │ │ │ │ │ ├── try-catch-alias-try-values.expect.md │ │ │ │ │ │ │ ├── try-catch-alias-try-values.js │ │ │ │ │ │ │ ├── try-catch-empty-try.expect.md │ │ │ │ │ │ │ ├── try-catch-empty-try.js │ │ │ │ │ │ │ ├── try-catch-in-nested-scope.expect.md │ │ │ │ │ │ │ ├── try-catch-in-nested-scope.ts │ │ │ │ │ │ │ ├── try-catch-logical-and-optional.expect.md │ │ │ │ │ │ │ ├── try-catch-logical-and-optional.js │ │ │ │ │ │ │ ├── try-catch-logical-expression.expect.md │ │ │ │ │ │ │ ├── try-catch-logical-expression.js │ │ │ │ │ │ │ ├── try-catch-maybe-null-dependency.expect.md │ │ │ │ │ │ │ ├── try-catch-maybe-null-dependency.ts │ │ │ │ │ │ │ ├── try-catch-multiple-value-blocks.expect.md │ │ │ │ │ │ │ ├── try-catch-multiple-value-blocks.js │ │ │ │ │ │ │ ├── try-catch-mutate-outer-value.expect.md │ │ │ │ │ │ │ ├── try-catch-mutate-outer-value.js │ │ │ │ │ │ │ ├── try-catch-nested-optional-chaining.expect.md │ │ │ │ │ │ │ ├── try-catch-nested-optional-chaining.js │ │ │ │ │ │ │ ├── try-catch-nullish-coalescing.expect.md │ │ │ │ │ │ │ ├── try-catch-nullish-coalescing.js │ │ │ │ │ │ │ ├── try-catch-optional-call.expect.md │ │ │ │ │ │ │ ├── try-catch-optional-call.js │ │ │ │ │ │ │ ├── try-catch-optional-chaining.expect.md │ │ │ │ │ │ │ ├── try-catch-optional-chaining.js │ │ │ │ │ │ │ ├── try-catch-ternary-expression.expect.md │ │ │ │ │ │ │ ├── try-catch-ternary-expression.js │ │ │ │ │ │ │ ├── try-catch-try-immediately-returns.expect.md │ │ │ │ │ │ │ ├── try-catch-try-immediately-returns.js │ │ │ │ │ │ │ ├── try-catch-try-immediately-throws-after-constant-propagation.expect.md │ │ │ │ │ │ │ ├── try-catch-try-immediately-throws-after-constant-propagation.js │ │ │ │ │ │ │ ├── try-catch-try-value-modified-in-catch-escaping.expect.md │ │ │ │ │ │ │ ├── try-catch-try-value-modified-in-catch-escaping.js │ │ │ │ │ │ │ ├── try-catch-try-value-modified-in-catch.expect.md │ │ │ │ │ │ │ ├── try-catch-try-value-modified-in-catch.js │ │ │ │ │ │ │ ├── try-catch-with-catch-param.expect.md │ │ │ │ │ │ │ ├── try-catch-with-catch-param.js │ │ │ │ │ │ │ ├── try-catch-with-return.expect.md │ │ │ │ │ │ │ ├── try-catch-with-return.js │ │ │ │ │ │ │ ├── try-catch-within-function-expression-returns-caught-value.expect.md │ │ │ │ │ │ │ ├── try-catch-within-function-expression-returns-caught-value.js │ │ │ │ │ │ │ ├── try-catch-within-function-expression.expect.md │ │ │ │ │ │ │ ├── try-catch-within-function-expression.js │ │ │ │ │ │ │ ├── try-catch-within-mutable-range.expect.md │ │ │ │ │ │ │ ├── try-catch-within-mutable-range.js │ │ │ │ │ │ │ ├── try-catch-within-object-method-returns-caught-value.expect.md │ │ │ │ │ │ │ ├── try-catch-within-object-method-returns-caught-value.js │ │ │ │ │ │ │ ├── try-catch-within-object-method.expect.md │ │ │ │ │ │ │ ├── try-catch-within-object-method.js │ │ │ │ │ │ │ ├── try-catch.expect.md │ │ │ │ │ │ │ ├── try-catch.js │ │ │ │ │ │ │ ├── ts-as-expression-default-value.expect.md │ │ │ │ │ │ │ ├── ts-as-expression-default-value.tsx │ │ │ │ │ │ │ ├── ts-enum-inline.expect.md │ │ │ │ │ │ │ ├── ts-enum-inline.tsx │ │ │ │ │ │ │ ├── ts-instantiation-default-param.expect.md │ │ │ │ │ │ │ ├── ts-instantiation-default-param.tsx │ │ │ │ │ │ │ ├── ts-instantiation-expression.expect.md │ │ │ │ │ │ │ ├── ts-instantiation-expression.tsx │ │ │ │ │ │ │ ├── ts-non-null-expression-default-value.expect.md │ │ │ │ │ │ │ ├── ts-non-null-expression-default-value.tsx │ │ │ │ │ │ │ ├── type-alias-declaration.expect.md │ │ │ │ │ │ │ ├── type-alias-declaration.ts │ │ │ │ │ │ │ ├── type-alias-used-as-annotation.expect.md │ │ │ │ │ │ │ ├── type-alias-used-as-annotation.ts │ │ │ │ │ │ │ ├── type-alias-used-as-annotation_.flow.expect.md │ │ │ │ │ │ │ ├── type-alias-used-as-annotation_.flow.js │ │ │ │ │ │ │ ├── type-alias-used-as-variable-annotation.expect.md │ │ │ │ │ │ │ ├── type-alias-used-as-variable-annotation.ts │ │ │ │ │ │ │ ├── type-alias-used-as-variable-annotation_.flow.expect.md │ │ │ │ │ │ │ ├── type-alias-used-as-variable-annotation_.flow.js │ │ │ │ │ │ │ ├── type-alias.flow.expect.md │ │ │ │ │ │ │ ├── type-alias.flow.js │ │ │ │ │ │ │ ├── type-args-test-binary-operator.expect.md │ │ │ │ │ │ │ ├── type-args-test-binary-operator.js │ │ │ │ │ │ │ ├── type-binary-operator.expect.md │ │ │ │ │ │ │ ├── type-binary-operator.js │ │ │ │ │ │ │ ├── type-cast-expression.flow.expect.md │ │ │ │ │ │ │ ├── type-cast-expression.flow.js │ │ │ │ │ │ │ ├── type-field-load.expect.md │ │ │ │ │ │ │ ├── type-field-load.js │ │ │ │ │ │ │ ├── type-inference-array-from.expect.md │ │ │ │ │ │ │ ├── type-inference-array-from.js │ │ │ │ │ │ │ ├── type-provider-log-default-import.expect.md │ │ │ │ │ │ │ ├── type-provider-log-default-import.tsx │ │ │ │ │ │ │ ├── type-provider-log.expect.md │ │ │ │ │ │ │ ├── type-provider-log.tsx │ │ │ │ │ │ │ ├── type-provider-store-capture-namespace-import.expect.md │ │ │ │ │ │ │ ├── type-provider-store-capture-namespace-import.tsx │ │ │ │ │ │ │ ├── type-provider-store-capture.expect.md │ │ │ │ │ │ │ ├── type-provider-store-capture.tsx │ │ │ │ │ │ │ ├── type-provider-tagged-template-expression.expect.md │ │ │ │ │ │ │ ├── type-provider-tagged-template-expression.js │ │ │ │ │ │ │ ├── type-test-field-load-binary-op.expect.md │ │ │ │ │ │ │ ├── type-test-field-load-binary-op.js │ │ │ │ │ │ │ ├── type-test-field-store.expect.md │ │ │ │ │ │ │ ├── type-test-field-store.js │ │ │ │ │ │ │ ├── type-test-polymorphic.expect.md │ │ │ │ │ │ │ ├── type-test-polymorphic.js │ │ │ │ │ │ │ ├── type-test-primitive.expect.md │ │ │ │ │ │ │ ├── type-test-primitive.js │ │ │ │ │ │ │ ├── type-test-return-type-inference.expect.md │ │ │ │ │ │ │ ├── type-test-return-type-inference.js │ │ │ │ │ │ │ ├── unary-expr.expect.md │ │ │ │ │ │ │ ├── unary-expr.js │ │ │ │ │ │ │ ├── unclosed-eslint-suppression-skips-all-components.expect.md │ │ │ │ │ │ │ ├── unclosed-eslint-suppression-skips-all-components.js │ │ │ │ │ │ │ ├── unconditional-break-label.expect.md │ │ │ │ │ │ │ ├── unconditional-break-label.js │ │ │ │ │ │ │ ├── uninitialized-declaration-in-reactive-scope.expect.md │ │ │ │ │ │ │ ├── uninitialized-declaration-in-reactive-scope.js │ │ │ │ │ │ │ ├── unknown-hooks-do-not-assert.expect.md │ │ │ │ │ │ │ ├── unknown-hooks-do-not-assert.js │ │ │ │ │ │ │ ├── unlabeled-break-within-label-loop.expect.md │ │ │ │ │ │ │ ├── unlabeled-break-within-label-loop.ts │ │ │ │ │ │ │ ├── unlabeled-break-within-label-switch.expect.md │ │ │ │ │ │ │ ├── unlabeled-break-within-label-switch.ts │ │ │ │ │ │ │ ├── unmemoized-nonreactive-dependency-is-pruned-as-dependency.expect.md │ │ │ │ │ │ │ ├── unmemoized-nonreactive-dependency-is-pruned-as-dependency.js │ │ │ │ │ │ │ ├── unused-array-middle-element.expect.md │ │ │ │ │ │ │ ├── unused-array-middle-element.js │ │ │ │ │ │ │ ├── unused-array-rest-element.expect.md │ │ │ │ │ │ │ ├── unused-array-rest-element.js │ │ │ │ │ │ │ ├── unused-conditional.expect.md │ │ │ │ │ │ │ ├── unused-conditional.js │ │ │ │ │ │ │ ├── unused-logical-assigned-to-variable.expect.md │ │ │ │ │ │ │ ├── unused-logical-assigned-to-variable.js │ │ │ │ │ │ │ ├── unused-logical.expect.md │ │ │ │ │ │ │ ├── unused-logical.js │ │ │ │ │ │ │ ├── unused-object-element-with-rest.expect.md │ │ │ │ │ │ │ ├── unused-object-element-with-rest.js │ │ │ │ │ │ │ ├── unused-object-element.expect.md │ │ │ │ │ │ │ ├── unused-object-element.js │ │ │ │ │ │ │ ├── unused-optional-method-assigned-to-variable.expect.md │ │ │ │ │ │ │ ├── unused-optional-method-assigned-to-variable.js │ │ │ │ │ │ │ ├── unused-ternary-assigned-to-variable.expect.md │ │ │ │ │ │ │ ├── unused-ternary-assigned-to-variable.js │ │ │ │ │ │ │ ├── update-expression-constant-propagation.expect.md │ │ │ │ │ │ │ ├── update-expression-constant-propagation.js │ │ │ │ │ │ │ ├── update-expression-in-sequence.expect.md │ │ │ │ │ │ │ ├── update-expression-in-sequence.js │ │ │ │ │ │ │ ├── update-expression-on-function-parameter-1.expect.md │ │ │ │ │ │ │ ├── update-expression-on-function-parameter-1.js │ │ │ │ │ │ │ ├── update-expression-on-function-parameter-2.expect.md │ │ │ │ │ │ │ ├── update-expression-on-function-parameter-2.js │ │ │ │ │ │ │ ├── update-expression-on-function-parameter-3.expect.md │ │ │ │ │ │ │ ├── update-expression-on-function-parameter-3.js │ │ │ │ │ │ │ ├── update-expression-on-function-parameter-4.expect.md │ │ │ │ │ │ │ ├── update-expression-on-function-parameter-4.js │ │ │ │ │ │ │ ├── update-expression.expect.md │ │ │ │ │ │ │ ├── update-expression.ts │ │ │ │ │ │ │ ├── update-global-in-callback.expect.md │ │ │ │ │ │ │ ├── update-global-in-callback.tsx │ │ │ │ │ │ │ ├── use-callback-simple.expect.md │ │ │ │ │ │ │ ├── use-callback-simple.js │ │ │ │ │ │ │ ├── use-effect-cleanup-reassigns.expect.md │ │ │ │ │ │ │ ├── use-effect-cleanup-reassigns.js │ │ │ │ │ │ │ ├── use-memo-noemit.expect.md │ │ │ │ │ │ │ ├── use-memo-noemit.js │ │ │ │ │ │ │ ├── use-memo-simple.expect.md │ │ │ │ │ │ │ ├── use-memo-simple.js │ │ │ │ │ │ │ ├── use-no-forget-module-level.expect.md │ │ │ │ │ │ │ ├── use-no-forget-module-level.js │ │ │ │ │ │ │ ├── use-no-forget-multiple-with-eslint-suppression.expect.md │ │ │ │ │ │ │ ├── use-no-forget-multiple-with-eslint-suppression.js │ │ │ │ │ │ │ ├── use-no-forget-with-eslint-suppression.expect.md │ │ │ │ │ │ │ ├── use-no-forget-with-eslint-suppression.js │ │ │ │ │ │ │ ├── use-no-forget-with-no-errors.expect.md │ │ │ │ │ │ │ ├── use-no-forget-with-no-errors.js │ │ │ │ │ │ │ ├── use-no-memo-module-level.expect.md │ │ │ │ │ │ │ ├── use-no-memo-module-level.js │ │ │ │ │ │ │ ├── use-no-memo-module-scope-usememo-function-scope.expect.md │ │ │ │ │ │ │ ├── use-no-memo-module-scope-usememo-function-scope.js │ │ │ │ │ │ │ ├── use-no-memo-simple.expect.md │ │ │ │ │ │ │ ├── use-no-memo-simple.js │ │ │ │ │ │ │ ├── use-operator-call-expression.expect.md │ │ │ │ │ │ │ ├── use-operator-call-expression.js │ │ │ │ │ │ │ ├── use-operator-conditional.expect.md │ │ │ │ │ │ │ ├── use-operator-conditional.js │ │ │ │ │ │ │ ├── use-operator-method-call.expect.md │ │ │ │ │ │ │ ├── use-operator-method-call.js │ │ │ │ │ │ │ ├── useActionState-dispatch-considered-as-non-reactive.expect.md │ │ │ │ │ │ │ ├── useActionState-dispatch-considered-as-non-reactive.js │ │ │ │ │ │ │ ├── useCallback-call-second-function-which-captures-maybe-mutable-value-dont-preserve-memoization.expect.md │ │ │ │ │ │ │ ├── useCallback-call-second-function-which-captures-maybe-mutable-value-dont-preserve-memoization.js │ │ │ │ │ │ │ ├── useCallback-call-second-function-which-captures-maybe-mutable-value-preserve-memoization.expect.md │ │ │ │ │ │ │ ├── useCallback-call-second-function-which-captures-maybe-mutable-value-preserve-memoization.js │ │ │ │ │ │ │ ├── useCallback-maybe-modify-free-variable-dont-preserve-memoization-guarantee.expect.md │ │ │ │ │ │ │ ├── useCallback-maybe-modify-free-variable-dont-preserve-memoization-guarantee.js │ │ │ │ │ │ │ ├── useCallback-maybe-modify-free-variable-preserve-memoization-guarantee.expect.md │ │ │ │ │ │ │ ├── useCallback-maybe-modify-free-variable-preserve-memoization-guarantee.js │ │ │ │ │ │ │ ├── useCallback-multiple-callbacks-modifying-same-ref-preserve-memoization.expect.md │ │ │ │ │ │ │ ├── useCallback-multiple-callbacks-modifying-same-ref-preserve-memoization.js │ │ │ │ │ │ │ ├── useCallback-ref-in-render.expect.md │ │ │ │ │ │ │ ├── useCallback-ref-in-render.js │ │ │ │ │ │ │ ├── useCallback-set-ref-nested-property-preserve-memoization.expect.md │ │ │ │ │ │ │ ├── useCallback-set-ref-nested-property-preserve-memoization.js │ │ │ │ │ │ │ ├── useCallback-set-ref-nested-property.expect.md │ │ │ │ │ │ │ ├── useCallback-set-ref-nested-property.js │ │ │ │ │ │ │ ├── useCallback-set-ref-value-dont-preserve-memoization.expect.md │ │ │ │ │ │ │ ├── useCallback-set-ref-value-dont-preserve-memoization.js │ │ │ │ │ │ │ ├── useCallback-set-ref-value-preserve-memoization.expect.md │ │ │ │ │ │ │ ├── useCallback-set-ref-value-preserve-memoization.js │ │ │ │ │ │ │ ├── useContext-maybe-mutate-context-in-callback.expect.md │ │ │ │ │ │ │ ├── useContext-maybe-mutate-context-in-callback.js │ │ │ │ │ │ │ ├── useContext-read-context-in-callback-if-condition.expect.md │ │ │ │ │ │ │ ├── useContext-read-context-in-callback-if-condition.js │ │ │ │ │ │ │ ├── useContext-read-context-in-callback.expect.md │ │ │ │ │ │ │ ├── useContext-read-context-in-callback.js │ │ │ │ │ │ │ ├── useEffect-arg-memoized.expect.md │ │ │ │ │ │ │ ├── useEffect-arg-memoized.js │ │ │ │ │ │ │ ├── useEffect-external-mutate.expect.md │ │ │ │ │ │ │ ├── useEffect-external-mutate.js │ │ │ │ │ │ │ ├── useEffect-global-pruned.expect.md │ │ │ │ │ │ │ ├── useEffect-global-pruned.js │ │ │ │ │ │ │ ├── useEffect-method-call.expect.md │ │ │ │ │ │ │ ├── useEffect-method-call.js │ │ │ │ │ │ │ ├── useEffect-namespace-pruned.expect.md │ │ │ │ │ │ │ ├── useEffect-namespace-pruned.js │ │ │ │ │ │ │ ├── useEffect-nested-lambdas.expect.md │ │ │ │ │ │ │ ├── useEffect-nested-lambdas.js │ │ │ │ │ │ │ ├── useEffect-snap-test.expect.md │ │ │ │ │ │ │ ├── useEffect-snap-test.js │ │ │ │ │ │ │ ├── useImperativeHandle-ref-mutate.expect.md │ │ │ │ │ │ │ ├── useImperativeHandle-ref-mutate.js │ │ │ │ │ │ │ ├── useMemo-arrow-implicit-return.expect.md │ │ │ │ │ │ │ ├── useMemo-arrow-implicit-return.js │ │ │ │ │ │ │ ├── useMemo-empty-return.expect.md │ │ │ │ │ │ │ ├── useMemo-empty-return.js │ │ │ │ │ │ │ ├── useMemo-explicit-null-return.expect.md │ │ │ │ │ │ │ ├── useMemo-explicit-null-return.js │ │ │ │ │ │ │ ├── useMemo-if-else-multiple-return.expect.md │ │ │ │ │ │ │ ├── useMemo-if-else-multiple-return.js │ │ │ │ │ │ │ ├── useMemo-independently-memoizeable.expect.md │ │ │ │ │ │ │ ├── useMemo-independently-memoizeable.js │ │ │ │ │ │ │ ├── useMemo-inlining-block-return.expect.md │ │ │ │ │ │ │ ├── useMemo-inlining-block-return.js │ │ │ │ │ │ │ ├── useMemo-inverted-if.expect.md │ │ │ │ │ │ │ ├── useMemo-inverted-if.js │ │ │ │ │ │ │ ├── useMemo-labeled-statement-unconditional-return.expect.md │ │ │ │ │ │ │ ├── useMemo-labeled-statement-unconditional-return.js │ │ │ │ │ │ │ ├── useMemo-logical.expect.md │ │ │ │ │ │ │ ├── useMemo-logical.js │ │ │ │ │ │ │ ├── useMemo-mabye-modified-free-variable-dont-preserve-memoization-guarantees.expect.md │ │ │ │ │ │ │ ├── useMemo-mabye-modified-free-variable-dont-preserve-memoization-guarantees.js │ │ │ │ │ │ │ ├── useMemo-mabye-modified-free-variable-preserve-memoization-guarantees.expect.md │ │ │ │ │ │ │ ├── useMemo-mabye-modified-free-variable-preserve-memoization-guarantees.js │ │ │ │ │ │ │ ├── useMemo-maybe-modified-later-dont-preserve-memoization-guarantees.expect.md │ │ │ │ │ │ │ ├── useMemo-maybe-modified-later-dont-preserve-memoization-guarantees.js │ │ │ │ │ │ │ ├── useMemo-maybe-modified-later-preserve-memoization-guarantees.expect.md │ │ │ │ │ │ │ ├── useMemo-maybe-modified-later-preserve-memoization-guarantees.js │ │ │ │ │ │ │ ├── useMemo-multiple-if-else.expect.md │ │ │ │ │ │ │ ├── useMemo-multiple-if-else.js │ │ │ │ │ │ │ ├── useMemo-multiple-returns.expect.md │ │ │ │ │ │ │ ├── useMemo-multiple-returns.js │ │ │ │ │ │ │ ├── useMemo-named-function.expect.md │ │ │ │ │ │ │ ├── useMemo-named-function.ts │ │ │ │ │ │ │ ├── useMemo-nested-ifs.expect.md │ │ │ │ │ │ │ ├── useMemo-nested-ifs.js │ │ │ │ │ │ │ ├── useMemo-simple.expect.md │ │ │ │ │ │ │ ├── useMemo-simple.js │ │ │ │ │ │ │ ├── useMemo-switch-no-fallthrough.expect.md │ │ │ │ │ │ │ ├── useMemo-switch-no-fallthrough.js │ │ │ │ │ │ │ ├── useMemo-switch-return.expect.md │ │ │ │ │ │ │ ├── useMemo-switch-return.js │ │ │ │ │ │ │ ├── useMemo-with-optional.expect.md │ │ │ │ │ │ │ ├── useMemo-with-optional.js │ │ │ │ │ │ │ ├── useReducer-returned-dispatcher-is-non-reactive.expect.md │ │ │ │ │ │ │ ├── useReducer-returned-dispatcher-is-non-reactive.js │ │ │ │ │ │ │ ├── valid-set-state-in-useEffect-from-ref.expect.md │ │ │ │ │ │ │ ├── valid-set-state-in-useEffect-from-ref.js │ │ │ │ │ │ │ ├── valid-setState-in-effect-from-ref-arithmetic.expect.md │ │ │ │ │ │ │ ├── valid-setState-in-effect-from-ref-arithmetic.js │ │ │ │ │ │ │ ├── valid-setState-in-effect-from-ref-array-index.expect.md │ │ │ │ │ │ │ ├── valid-setState-in-effect-from-ref-array-index.js │ │ │ │ │ │ │ ├── valid-setState-in-effect-from-ref-function-call.expect.md │ │ │ │ │ │ │ ├── valid-setState-in-effect-from-ref-function-call.js │ │ │ │ │ │ │ ├── valid-setState-in-useEffect-controlled-by-ref-value.expect.md │ │ │ │ │ │ │ ├── valid-setState-in-useEffect-controlled-by-ref-value.js │ │ │ │ │ │ │ ├── valid-setState-in-useEffect-listener-transitive.expect.md │ │ │ │ │ │ │ ├── valid-setState-in-useEffect-listener-transitive.js │ │ │ │ │ │ │ ├── valid-setState-in-useEffect-listener.expect.md │ │ │ │ │ │ │ ├── valid-setState-in-useEffect-listener.js │ │ │ │ │ │ │ ├── valid-setState-in-useEffect-via-useEffectEvent-listener.expect.md │ │ │ │ │ │ │ ├── valid-setState-in-useEffect-via-useEffectEvent-listener.js │ │ │ │ │ │ │ ├── valid-setState-in-useEffect-via-useEffectEvent-with-ref.expect.md │ │ │ │ │ │ │ ├── valid-setState-in-useEffect-via-useEffectEvent-with-ref.js │ │ │ │ │ │ │ ├── valid-setState-in-useLayoutEffect-from-ref.expect.md │ │ │ │ │ │ │ ├── valid-setState-in-useLayoutEffect-from-ref.js │ │ │ │ │ │ │ ├── validate-no-set-state-in-render-uncalled-function-with-mutable-range-is-valid.expect.md │ │ │ │ │ │ │ ├── validate-no-set-state-in-render-uncalled-function-with-mutable-range-is-valid.js │ │ │ │ │ │ │ ├── validate-no-set-state-in-render-unconditional-lambda-which-conditionally-sets-state-ok.expect.md │ │ │ │ │ │ │ ├── validate-no-set-state-in-render-unconditional-lambda-which-conditionally-sets-state-ok.js │ │ │ │ │ │ │ ├── value-block-mutates-outer-value.expect.md │ │ │ │ │ │ │ ├── value-block-mutates-outer-value.ts │ │ │ │ │ │ │ ├── weakmap-constructor.expect.md │ │ │ │ │ │ │ ├── weakmap-constructor.js │ │ │ │ │ │ │ ├── weakset-constructor.expect.md │ │ │ │ │ │ │ ├── weakset-constructor.js │ │ │ │ │ │ │ ├── while-break.expect.md │ │ │ │ │ │ │ ├── while-break.js │ │ │ │ │ │ │ ├── while-conditional-continue.expect.md │ │ │ │ │ │ │ ├── while-conditional-continue.js │ │ │ │ │ │ │ ├── while-logical.expect.md │ │ │ │ │ │ │ ├── while-logical.js │ │ │ │ │ │ │ ├── while-property.expect.md │ │ │ │ │ │ │ ├── while-property.js │ │ │ │ │ │ │ ├── while-with-assignment-in-test.expect.md │ │ │ │ │ │ │ └── while-with-assignment-in-test.js │ │ │ │ │ │ └── tsconfig.json │ │ │ │ │ ├── parseConfigPragma-test.ts │ │ │ │ │ └── test-utils/ │ │ │ │ │ └── validateNoUseBeforeDefine.ts │ │ │ │ └── index.ts │ │ │ ├── tsconfig.json │ │ │ └── tsup.config.ts │ │ ├── eslint-plugin-react-compiler/ │ │ │ ├── README.md │ │ │ ├── __tests__/ │ │ │ │ ├── ImpureFunctionCallsRule-test.ts │ │ │ │ ├── InvalidHooksRule-test.ts │ │ │ │ ├── NoAmbiguousJsxRule-test.ts │ │ │ │ ├── NoCapitalizedCallsRule-test.ts │ │ │ │ ├── NoRefAccessInRender-tests.ts │ │ │ │ ├── PluginTest-test.ts │ │ │ │ ├── ReactCompilerRuleTypescript-test.ts │ │ │ │ └── shared-utils.ts │ │ │ ├── babel.config.js │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── index.ts │ │ │ │ ├── rules/ │ │ │ │ │ └── ReactCompilerRule.ts │ │ │ │ ├── shared/ │ │ │ │ │ └── RunReactCompiler.ts │ │ │ │ └── types/ │ │ │ │ ├── hermes-eslint.d.ts │ │ │ │ └── hermes-parser.d.ts │ │ │ ├── tsconfig.json │ │ │ └── tsup.config.ts │ │ ├── make-read-only-util/ │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── jest.config.js │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── __tests__/ │ │ │ │ │ └── makeReadOnly-test.ts │ │ │ │ └── makeReadOnly.ts │ │ │ ├── tsconfig.json │ │ │ └── tsup.config.ts │ │ ├── react-compiler-healthcheck/ │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── checks/ │ │ │ │ │ ├── libraryCompat.ts │ │ │ │ │ ├── reactCompiler.ts │ │ │ │ │ └── strictMode.ts │ │ │ │ ├── config.ts │ │ │ │ └── index.ts │ │ │ ├── tsconfig.json │ │ │ └── tsup.config.ts │ │ ├── react-compiler-runtime/ │ │ │ ├── README.md │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ └── index.ts │ │ │ ├── tsconfig.json │ │ │ └── tsup.config.ts │ │ ├── react-forgive/ │ │ │ ├── .vscode-test.mjs │ │ │ ├── .vscodeignore │ │ │ ├── .yarnrc │ │ │ ├── LICENSE │ │ │ ├── client/ │ │ │ │ ├── package.json │ │ │ │ └── src/ │ │ │ │ ├── colors.ts │ │ │ │ ├── extension.ts │ │ │ │ └── mapping.ts │ │ │ ├── package.json │ │ │ ├── scripts/ │ │ │ │ ├── build.mjs │ │ │ │ ├── client.mjs │ │ │ │ └── server.mjs │ │ │ ├── server/ │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ ├── compiler/ │ │ │ │ │ │ ├── compat.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── utils/ │ │ │ │ │ └── range.ts │ │ │ │ └── tsconfig.json │ │ │ └── tsconfig.json │ │ ├── react-mcp-server/ │ │ │ ├── README.md │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── compiler/ │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ ├── tools/ │ │ │ │ │ ├── componentTree.ts │ │ │ │ │ └── runtimePerf.ts │ │ │ │ ├── types/ │ │ │ │ │ └── algolia.ts │ │ │ │ └── utils/ │ │ │ │ ├── algolia.ts │ │ │ │ └── assertExhaustive.ts │ │ │ ├── todo.md │ │ │ ├── tsconfig.json │ │ │ └── tsup.config.ts │ │ └── snap/ │ │ ├── package.json │ │ ├── scripts/ │ │ │ └── link-react-compiler-runtime.sh │ │ ├── src/ │ │ │ ├── SproutTodoFilter.ts │ │ │ ├── compiler.ts │ │ │ ├── constants.ts │ │ │ ├── fixture-utils.ts │ │ │ ├── main.ts │ │ │ ├── minimize.ts │ │ │ ├── reporter.ts │ │ │ ├── runner-watch.ts │ │ │ ├── runner-worker.ts │ │ │ ├── runner.ts │ │ │ ├── sprout/ │ │ │ │ ├── README.md │ │ │ │ ├── ReactForgetFeatureFlag.ts │ │ │ │ ├── evaluator.ts │ │ │ │ ├── index.ts │ │ │ │ ├── shared-runtime-type-provider.ts │ │ │ │ ├── shared-runtime.ts │ │ │ │ └── useEffectWrapper.ts │ │ │ └── types.d.ts │ │ └── tsconfig.json │ └── scripts/ │ ├── anonymize.js │ ├── build-eslint-docs.js │ ├── copyright.js │ ├── enable-feature-flag.js │ ├── hash.sh │ ├── release/ │ │ ├── ci-npmrc │ │ ├── prompt-for-otp.js │ │ ├── publish.js │ │ └── shared/ │ │ ├── build-packages.js │ │ ├── packages.js │ │ └── utils.js │ └── update-commit-message.js ├── dangerfile.js ├── fixtures/ │ ├── art/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── VectorWidget.js │ │ ├── app.js │ │ ├── index.html │ │ ├── package.json │ │ └── webpack.config.js │ ├── attribute-behavior/ │ │ ├── .gitignore │ │ ├── AttributeTableSnapshot.md │ │ ├── README.md │ │ ├── package.json │ │ ├── public/ │ │ │ ├── index.html │ │ │ └── manifest.json │ │ └── src/ │ │ ├── App.js │ │ ├── App.test.js │ │ ├── attributes.js │ │ ├── index.css │ │ └── index.js │ ├── concurrent/ │ │ └── time-slicing/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package.json │ │ ├── public/ │ │ │ ├── index.html │ │ │ └── manifest.json │ │ └── src/ │ │ ├── Charts.js │ │ ├── Clock.js │ │ ├── index.css │ │ └── index.js │ ├── devtools/ │ │ ├── regression/ │ │ │ ├── 14.9.html │ │ │ ├── 15.0.html │ │ │ ├── 15.1.html │ │ │ ├── 15.2.html │ │ │ ├── 15.3.html │ │ │ ├── 15.4.html │ │ │ ├── 15.5.html │ │ │ ├── 15.6.html │ │ │ ├── 16.0.html │ │ │ ├── 16.1.html │ │ │ ├── 16.2.html │ │ │ ├── 16.3.html │ │ │ ├── 16.4.html │ │ │ ├── 16.5.html │ │ │ ├── 16.6.html │ │ │ ├── 16.7.html │ │ │ ├── canary.html │ │ │ ├── index.html │ │ │ ├── next.html │ │ │ ├── server.js │ │ │ ├── shared.js │ │ │ └── styles.css │ │ ├── scheduling-profiler/ │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── app.js │ │ │ ├── index.html │ │ │ └── run.js │ │ └── standalone/ │ │ └── index.html │ ├── dom/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package.json │ │ ├── public/ │ │ │ ├── act-dom.html │ │ │ ├── index.html │ │ │ ├── renderer.html │ │ │ └── renderer.js │ │ └── src/ │ │ ├── __tests__/ │ │ │ └── nested-act-test.js │ │ ├── components/ │ │ │ ├── App.js │ │ │ ├── Fixture.js │ │ │ ├── FixtureSet.js │ │ │ ├── Header.js │ │ │ ├── Iframe.js │ │ │ ├── IssueList.js │ │ │ ├── TestCase.js │ │ │ ├── VersionPicker.js │ │ │ ├── fixtures/ │ │ │ │ ├── buttons/ │ │ │ │ │ └── index.js │ │ │ │ ├── custom-elements/ │ │ │ │ │ └── index.js │ │ │ │ ├── date-inputs/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── switch-date-test-case.js │ │ │ │ ├── email-inputs/ │ │ │ │ │ ├── EmailDisabledAttributesTestCase.js │ │ │ │ │ ├── EmailEnabledAttributesTestCase.js │ │ │ │ │ ├── JumpingCursorTestCase.js │ │ │ │ │ └── index.js │ │ │ │ ├── error-handling/ │ │ │ │ │ └── index.js │ │ │ │ ├── event-pooling/ │ │ │ │ │ ├── hit-box.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── mouse-move.js │ │ │ │ │ └── persistence.js │ │ │ │ ├── form-actions/ │ │ │ │ │ └── index.js │ │ │ │ ├── form-state/ │ │ │ │ │ ├── ControlledFormFixture.js │ │ │ │ │ └── index.js │ │ │ │ ├── fragment-refs/ │ │ │ │ │ ├── CompareDocumentPositionCase.js │ │ │ │ │ ├── CompareDocumentPositionFragmentContainer.js │ │ │ │ │ ├── EventDispatchCase.js │ │ │ │ │ ├── EventFragmentContainer.js │ │ │ │ │ ├── EventListenerCase.js │ │ │ │ │ ├── FocusCase.js │ │ │ │ │ ├── GetClientRectsCase.js │ │ │ │ │ ├── GetRootNodeFragmentContainer.js │ │ │ │ │ ├── IntersectionObserverCase.js │ │ │ │ │ ├── PrintRectsFragmentContainer.js │ │ │ │ │ ├── ResizeObserverCase.js │ │ │ │ │ ├── ScrollIntoViewCase.js │ │ │ │ │ ├── ScrollIntoViewCaseComplex.js │ │ │ │ │ ├── ScrollIntoViewCaseSimple.js │ │ │ │ │ ├── ScrollIntoViewTargetElement.js │ │ │ │ │ ├── TextNodesCase.js │ │ │ │ │ └── index.js │ │ │ │ ├── home.js │ │ │ │ ├── hydration/ │ │ │ │ │ ├── Code.js │ │ │ │ │ ├── code-transformer.js │ │ │ │ │ ├── codemirror-paraiso-dark.css │ │ │ │ │ ├── data.js │ │ │ │ │ ├── hydration.css │ │ │ │ │ └── index.js │ │ │ │ ├── index.js │ │ │ │ ├── input-change-events/ │ │ │ │ │ ├── InputPlaceholderFixture.js │ │ │ │ │ ├── RadioClickFixture.js │ │ │ │ │ ├── RadioGroupFixture.js │ │ │ │ │ ├── RadioNameChangeFixture.js │ │ │ │ │ ├── RangeKeyboardFixture.js │ │ │ │ │ └── index.js │ │ │ │ ├── media-events/ │ │ │ │ │ └── index.js │ │ │ │ ├── mouse-events/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── mouse-enter.js │ │ │ │ │ └── mouse-movement.js │ │ │ │ ├── number-inputs/ │ │ │ │ │ ├── NumberInputDecimal.js │ │ │ │ │ ├── NumberInputExtraZeroes.js │ │ │ │ │ ├── NumberTestCase.js │ │ │ │ │ └── index.js │ │ │ │ ├── password-inputs/ │ │ │ │ │ ├── PasswordTestCase.js │ │ │ │ │ └── index.js │ │ │ │ ├── pointer-events/ │ │ │ │ │ ├── drag-box.js │ │ │ │ │ ├── drag.js │ │ │ │ │ ├── hover-box.js │ │ │ │ │ ├── hover.js │ │ │ │ │ └── index.js │ │ │ │ ├── progress/ │ │ │ │ │ └── index.js │ │ │ │ ├── range-inputs/ │ │ │ │ │ └── index.js │ │ │ │ ├── selection-events/ │ │ │ │ │ ├── OnSelectEventTestCase.js │ │ │ │ │ ├── ReorderedInputsTestCase.js │ │ │ │ │ └── index.js │ │ │ │ ├── selects/ │ │ │ │ │ └── index.js │ │ │ │ ├── suspense/ │ │ │ │ │ └── index.js │ │ │ │ ├── text-inputs/ │ │ │ │ │ ├── InputTestCase.js │ │ │ │ │ ├── README.md │ │ │ │ │ ├── ReplaceEmailInput.js │ │ │ │ │ └── index.js │ │ │ │ └── textareas/ │ │ │ │ └── index.js │ │ │ └── propTypes.js │ │ ├── find-dom-node.js │ │ ├── index.js │ │ ├── polyfills.js │ │ ├── react-loader.js │ │ ├── style.css │ │ └── tags.js │ ├── eslint-v10/ │ │ ├── README.md │ │ ├── build.mjs │ │ ├── eslint.config.ts │ │ ├── index.js │ │ ├── package.json │ │ └── tsconfig.json │ ├── eslint-v6/ │ │ ├── .eslintrc.json │ │ ├── README.md │ │ ├── build.mjs │ │ ├── index.js │ │ └── package.json │ ├── eslint-v7/ │ │ ├── .eslintrc.json │ │ ├── README.md │ │ ├── build.mjs │ │ ├── index.js │ │ └── package.json │ ├── eslint-v8/ │ │ ├── .eslintrc.json │ │ ├── README.md │ │ ├── build.mjs │ │ ├── index.js │ │ └── package.json │ ├── eslint-v9/ │ │ ├── README.md │ │ ├── build.mjs │ │ ├── eslint.config.ts │ │ ├── index.js │ │ ├── package.json │ │ └── tsconfig.json │ ├── expiration/ │ │ ├── .gitignore │ │ ├── package.json │ │ ├── public/ │ │ │ └── index.html │ │ └── src/ │ │ └── index.js │ ├── fiber-debugger/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package.json │ │ ├── public/ │ │ │ └── index.html │ │ └── src/ │ │ ├── App.js │ │ ├── Editor.js │ │ ├── Fibers.js │ │ ├── describeFibers.js │ │ ├── index.css │ │ └── index.js │ ├── fizz/ │ │ ├── README.md │ │ ├── package.json │ │ ├── public/ │ │ │ └── main.css │ │ ├── scripts/ │ │ │ └── build.js │ │ ├── server/ │ │ │ ├── delays.js │ │ │ ├── render-to-buffer.js │ │ │ ├── render-to-stream.js │ │ │ ├── render-to-string.js │ │ │ └── server.js │ │ └── src/ │ │ ├── App.js │ │ ├── BigComponent.js │ │ ├── Html.js │ │ └── index.js │ ├── fizz-ssr-browser/ │ │ └── index.html │ ├── flight/ │ │ ├── .gitignore │ │ ├── .nvmrc │ │ ├── __tests__/ │ │ │ └── __e2e__/ │ │ │ └── smoke.test.js │ │ ├── config/ │ │ │ ├── env.js │ │ │ ├── modules.js │ │ │ ├── package.json │ │ │ ├── paths.js │ │ │ └── webpack.config.js │ │ ├── loader/ │ │ │ ├── global.js │ │ │ ├── package.json │ │ │ └── region.js │ │ ├── package.json │ │ ├── playwright.config.js │ │ ├── scripts/ │ │ │ ├── build.js │ │ │ ├── package.json │ │ │ └── test.js │ │ ├── server/ │ │ │ ├── global.js │ │ │ ├── package.json │ │ │ └── region.js │ │ └── src/ │ │ ├── App.js │ │ ├── Button.js │ │ ├── Client.js │ │ ├── ClientContext.js │ │ ├── Container.js │ │ ├── Counter.js │ │ ├── Counter2.js │ │ ├── Dynamic.js │ │ ├── ErrorBoundary.js │ │ ├── Form.js │ │ ├── GenerateImage.js │ │ ├── LargeContent.js │ │ ├── Navigate.js │ │ ├── ServerState.js │ │ ├── ShowMore.js │ │ ├── actions.js │ │ ├── cjs/ │ │ │ ├── Counter3.js │ │ │ ├── Note.js │ │ │ └── package.json │ │ ├── index.js │ │ ├── library.js │ │ └── style.css │ ├── flight-esm/ │ │ ├── .gitignore │ │ ├── .nvmrc │ │ ├── loader/ │ │ │ ├── package.json │ │ │ └── region.js │ │ ├── package.json │ │ ├── server/ │ │ │ ├── global.js │ │ │ ├── package.json │ │ │ └── region.js │ │ └── src/ │ │ ├── App.js │ │ ├── Button.js │ │ ├── ErrorBoundary.js │ │ ├── Form.js │ │ ├── ServerState.js │ │ ├── actions.js │ │ ├── index.js │ │ └── style.css │ ├── flight-parcel/ │ │ ├── .gitignore │ │ ├── package.json │ │ ├── src/ │ │ │ ├── Dialog.tsx │ │ │ ├── TodoCreate.tsx │ │ │ ├── TodoDetail.tsx │ │ │ ├── TodoItem.tsx │ │ │ ├── TodoList.tsx │ │ │ ├── Todos.css │ │ │ ├── Todos.tsx │ │ │ ├── actions.ts │ │ │ ├── client.tsx │ │ │ └── server.tsx │ │ ├── tsconfig.json │ │ └── types.d.ts │ ├── legacy-jsx-runtimes/ │ │ ├── README.md │ │ ├── babel.config.js │ │ ├── lint-runtimes.js │ │ ├── package.json │ │ ├── react-14/ │ │ │ ├── cjs/ │ │ │ │ ├── react-jsx-dev-runtime.development.js │ │ │ │ └── react-jsx-runtime.development.js │ │ │ ├── jsx-dev-runtime.js │ │ │ ├── jsx-runtime.js │ │ │ ├── package.json │ │ │ └── react-14.test.js │ │ ├── react-15/ │ │ │ ├── cjs/ │ │ │ │ ├── react-jsx-dev-runtime.development.js │ │ │ │ └── react-jsx-runtime.development.js │ │ │ ├── jsx-dev-runtime.js │ │ │ ├── jsx-runtime.js │ │ │ ├── package.json │ │ │ └── react-15.test.js │ │ ├── react-16/ │ │ │ ├── cjs/ │ │ │ │ ├── react-jsx-dev-runtime.development.js │ │ │ │ └── react-jsx-runtime.development.js │ │ │ ├── jsx-dev-runtime.js │ │ │ ├── jsx-runtime.js │ │ │ ├── package.json │ │ │ └── react-16.test.js │ │ ├── react-17/ │ │ │ ├── cjs/ │ │ │ │ ├── react-jsx-dev-runtime.development.js │ │ │ │ └── react-jsx-runtime.development.js │ │ │ ├── jsx-dev-runtime.js │ │ │ ├── jsx-runtime.js │ │ │ ├── package.json │ │ │ └── react-17.test.js │ │ └── setupTests.js │ ├── nesting/ │ │ ├── .eslintignore │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package.json │ │ ├── public/ │ │ │ └── index.html │ │ └── src/ │ │ ├── index.js │ │ ├── legacy/ │ │ │ ├── Greeting.js │ │ │ ├── createLegacyRoot.js │ │ │ └── package.json │ │ ├── modern/ │ │ │ ├── AboutPage.js │ │ │ ├── App.js │ │ │ ├── HomePage.js │ │ │ ├── index.js │ │ │ ├── lazyLegacyRoot.js │ │ │ └── package.json │ │ ├── shared/ │ │ │ ├── Clock.js │ │ │ ├── ThemeContext.js │ │ │ └── useTime.js │ │ └── store.js │ ├── owner-stacks/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package.json │ │ ├── public/ │ │ │ ├── index.html │ │ │ ├── manifest.json │ │ │ └── robots.txt │ │ └── src/ │ │ ├── App.css │ │ ├── App.js │ │ ├── index.css │ │ ├── index.js │ │ └── reportWebVitals.js │ ├── packaging/ │ │ ├── README.md │ │ ├── babel-standalone/ │ │ │ └── dev.html │ │ ├── browserify/ │ │ │ ├── dev/ │ │ │ │ ├── .gitignore │ │ │ │ ├── index.html │ │ │ │ ├── input.js │ │ │ │ └── package.json │ │ │ └── prod/ │ │ │ ├── .gitignore │ │ │ ├── index.html │ │ │ ├── input.js │ │ │ └── package.json │ │ ├── brunch/ │ │ │ ├── dev/ │ │ │ │ ├── .gitignore │ │ │ │ ├── app/ │ │ │ │ │ └── initialize.js │ │ │ │ ├── config.js │ │ │ │ ├── index.html │ │ │ │ ├── input.js │ │ │ │ └── package.json │ │ │ └── prod/ │ │ │ ├── .gitignore │ │ │ ├── app/ │ │ │ │ └── initialize.js │ │ │ ├── config.js │ │ │ ├── index.html │ │ │ ├── input.js │ │ │ └── package.json │ │ ├── build-all.js │ │ ├── globals/ │ │ │ ├── dev.html │ │ │ └── prod.html │ │ ├── index.html │ │ ├── requirejs/ │ │ │ ├── dev.html │ │ │ └── prod.html │ │ ├── rjs/ │ │ │ ├── dev/ │ │ │ │ ├── .gitignore │ │ │ │ ├── config.js │ │ │ │ ├── index.html │ │ │ │ ├── input.js │ │ │ │ └── package.json │ │ │ └── prod/ │ │ │ ├── .gitignore │ │ │ ├── config.js │ │ │ ├── index.html │ │ │ ├── input.js │ │ │ └── package.json │ │ ├── systemjs/ │ │ │ ├── dev.html │ │ │ └── prod.html │ │ ├── systemjs-builder/ │ │ │ ├── dev/ │ │ │ │ ├── .gitignore │ │ │ │ ├── build.js │ │ │ │ ├── config.js │ │ │ │ ├── index.html │ │ │ │ ├── input.js │ │ │ │ └── package.json │ │ │ └── prod/ │ │ │ ├── .gitignore │ │ │ ├── build.js │ │ │ ├── config.js │ │ │ ├── index.html │ │ │ ├── input.js │ │ │ └── package.json │ │ ├── webpack/ │ │ │ ├── dev/ │ │ │ │ ├── .gitignore │ │ │ │ ├── config.js │ │ │ │ ├── index.html │ │ │ │ ├── input.js │ │ │ │ └── package.json │ │ │ └── prod/ │ │ │ ├── .gitignore │ │ │ ├── config.js │ │ │ ├── index.html │ │ │ ├── input.js │ │ │ └── package.json │ │ └── webpack-alias/ │ │ ├── dev/ │ │ │ ├── .gitignore │ │ │ ├── config.js │ │ │ ├── index.html │ │ │ ├── input.js │ │ │ └── package.json │ │ └── prod/ │ │ ├── .gitignore │ │ ├── config.js │ │ ├── index.html │ │ ├── input.js │ │ └── package.json │ ├── scheduler/ │ │ └── index.html │ ├── ssr/ │ │ ├── README.md │ │ ├── package.json │ │ ├── public/ │ │ │ └── index.html │ │ ├── server/ │ │ │ ├── index.js │ │ │ └── render.js │ │ └── src/ │ │ ├── components/ │ │ │ ├── App.js │ │ │ ├── Chrome.css │ │ │ ├── Chrome.js │ │ │ ├── LargeContent.js │ │ │ ├── Page.css │ │ │ ├── Page.js │ │ │ ├── Page2.js │ │ │ ├── Suspend.js │ │ │ └── Theme.js │ │ └── index.js │ ├── ssr2/ │ │ ├── README.md │ │ ├── package.json │ │ ├── public/ │ │ │ └── main.css │ │ ├── scripts/ │ │ │ └── build.js │ │ ├── server/ │ │ │ ├── delays.js │ │ │ ├── render.js │ │ │ └── server.js │ │ └── src/ │ │ ├── App.js │ │ ├── Comments.js │ │ ├── Html.js │ │ ├── Layout.js │ │ ├── NavBar.js │ │ ├── Post.js │ │ ├── Sidebar.js │ │ ├── Spinner.js │ │ ├── data.js │ │ └── index.js │ ├── stacks/ │ │ ├── BabelClasses-compiled.js │ │ ├── BabelClasses.js │ │ ├── Components.js │ │ ├── Example.js │ │ ├── babel.config.json │ │ ├── index.html │ │ └── package.json │ └── view-transition/ │ ├── README.md │ ├── loader/ │ │ ├── package.json │ │ └── server.js │ ├── package.json │ ├── public/ │ │ └── index.html │ ├── server/ │ │ ├── index.js │ │ └── render.js │ └── src/ │ ├── components/ │ │ ├── App.js │ │ ├── Chrome.css │ │ ├── Chrome.js │ │ ├── NestedReveal.js │ │ ├── Page.css │ │ ├── Page.js │ │ ├── SwipeRecognizer.js │ │ └── Transitions.module.css │ └── index.js ├── flow-typed/ │ ├── environments/ │ │ ├── bom.js │ │ ├── cssom.js │ │ ├── dom.js │ │ ├── geometry.js │ │ ├── html.js │ │ ├── node.js │ │ ├── serviceworkers.js │ │ ├── streams.js │ │ └── web-animations.js │ └── npm/ │ ├── error-stack-parser_v2.x.x.js │ └── minimist_v1.x.x.js ├── flow-typed.config.json ├── package.json ├── packages/ │ ├── dom-event-testing-library/ │ │ ├── README.md │ │ ├── __tests__/ │ │ │ ├── __snapshots__/ │ │ │ │ └── index-test.internal.js.snap │ │ │ └── index-test.internal.js │ │ ├── constants.js │ │ ├── domEnvironment.js │ │ ├── domEventSequences.js │ │ ├── domEvents.js │ │ ├── index.js │ │ ├── package.json │ │ ├── testHelpers.js │ │ └── touchStore.js │ ├── eslint-plugin-react-hooks/ │ │ ├── CHANGELOG.md │ │ ├── README.md │ │ ├── __tests__/ │ │ │ ├── ESLintRuleExhaustiveDeps-test.js │ │ │ ├── ESLintRulesOfHooks-test.js │ │ │ ├── ReactCompilerRuleFlow-test.ts │ │ │ └── ReactCompilerRuleTypescript-test.ts │ │ ├── babel.config.js │ │ ├── index.js │ │ ├── jest.config.js │ │ ├── npm/ │ │ │ ├── index.d.ts │ │ │ └── index.js │ │ ├── package.json │ │ ├── src/ │ │ │ ├── code-path-analysis/ │ │ │ │ ├── LICENSE │ │ │ │ ├── README.md │ │ │ │ ├── assert.js │ │ │ │ ├── code-path-analyzer.js │ │ │ │ ├── code-path-segment.js │ │ │ │ ├── code-path-state.js │ │ │ │ ├── code-path.js │ │ │ │ ├── fork-context.js │ │ │ │ └── id-generator.js │ │ │ ├── index.ts │ │ │ ├── rules/ │ │ │ │ ├── ExhaustiveDeps.ts │ │ │ │ └── RulesOfHooks.ts │ │ │ ├── shared/ │ │ │ │ ├── ReactCompiler.ts │ │ │ │ ├── ReactFeatureFlags.d.ts │ │ │ │ ├── RunReactCompiler.ts │ │ │ │ └── Utils.ts │ │ │ └── types/ │ │ │ ├── estree.d.ts │ │ │ ├── global.d.ts │ │ │ ├── hermes-eslint.d.ts │ │ │ └── hermes-parser.d.ts │ │ └── tsconfig.json │ ├── internal-test-utils/ │ │ ├── ReactInternalTestUtils.js │ │ ├── ReactJSDOM.js │ │ ├── ReactJSDOMUtils.js │ │ ├── __tests__/ │ │ │ ├── ReactInternalTestUtils-test.js │ │ │ └── ReactInternalTestUtilsDOM-test.js │ │ ├── consoleMock.js │ │ ├── debugInfo.js │ │ ├── enqueueTask.js │ │ ├── index.js │ │ ├── internalAct.js │ │ ├── package.json │ │ ├── shouldIgnoreConsoleError.js │ │ ├── shouldIgnoreConsoleWarn.js │ │ └── simulateBrowserEventDispatch.js │ ├── jest-react/ │ │ ├── README.md │ │ ├── index.js │ │ ├── npm/ │ │ │ └── index.js │ │ ├── package.json │ │ └── src/ │ │ └── JestReact.js │ ├── react/ │ │ ├── README.md │ │ ├── compiler-runtime.js │ │ ├── index.development.js │ │ ├── index.experimental.development.js │ │ ├── index.experimental.js │ │ ├── index.fb.js │ │ ├── index.js │ │ ├── index.stable.development.js │ │ ├── index.stable.js │ │ ├── jsx-dev-runtime.js │ │ ├── jsx-dev-runtime.react-server.js │ │ ├── jsx-runtime.js │ │ ├── jsx-runtime.react-server.js │ │ ├── npm/ │ │ │ ├── compiler-runtime.js │ │ │ ├── index.js │ │ │ ├── jsx-dev-runtime.js │ │ │ ├── jsx-dev-runtime.react-server.js │ │ │ ├── jsx-runtime.js │ │ │ ├── jsx-runtime.react-server.js │ │ │ ├── react.react-server.js │ │ │ └── unstable-cache.js │ │ ├── package.json │ │ ├── react.react-server.js │ │ └── src/ │ │ ├── BadMapPolyfill.js │ │ ├── ReactAct.js │ │ ├── ReactBaseClasses.js │ │ ├── ReactCacheClient.js │ │ ├── ReactCacheImpl.js │ │ ├── ReactCacheServer.js │ │ ├── ReactChildren.js │ │ ├── ReactClient.js │ │ ├── ReactCompilerRuntime.js │ │ ├── ReactContext.js │ │ ├── ReactCreateRef.js │ │ ├── ReactForwardRef.js │ │ ├── ReactHooks.js │ │ ├── ReactLazy.js │ │ ├── ReactMemo.js │ │ ├── ReactNoopUpdateQueue.js │ │ ├── ReactOwnerStack.js │ │ ├── ReactServer.experimental.development.js │ │ ├── ReactServer.experimental.js │ │ ├── ReactServer.fb.js │ │ ├── ReactServer.js │ │ ├── ReactSharedInternalsClient.js │ │ ├── ReactSharedInternalsServer.js │ │ ├── ReactStartTransition.js │ │ ├── ReactTaint.js │ │ ├── ReactTaintRegistry.js │ │ ├── ReactTransitionType.js │ │ ├── __tests__/ │ │ │ ├── React-hooks-arity.js │ │ │ ├── ReactChildren-test.js │ │ │ ├── ReactClassEquivalence-test.js │ │ │ ├── ReactCoffeeScriptClass-test.coffee │ │ │ ├── ReactContextValidator-test.js │ │ │ ├── ReactCreateElement-test.js │ │ │ ├── ReactCreateRef-test.js │ │ │ ├── ReactES6Class-test.js │ │ │ ├── ReactElementClone-test.js │ │ │ ├── ReactElementValidator-test.internal.js │ │ │ ├── ReactJSXElementValidator-test.js │ │ │ ├── ReactJSXRuntime-test.js │ │ │ ├── ReactJSXTransformIntegration-test.js │ │ │ ├── ReactMismatchedVersions-test.js │ │ │ ├── ReactProfiler-test.internal.js │ │ │ ├── ReactProfilerComponent-test.internal.js │ │ │ ├── ReactProfilerDevToolsIntegration-test.internal.js │ │ │ ├── ReactPureComponent-test.js │ │ │ ├── ReactStartTransition-test.js │ │ │ ├── ReactStrictMode-test.internal.js │ │ │ ├── ReactStrictMode-test.js │ │ │ ├── ReactTypeScriptClass-test.ts │ │ │ ├── ReactVersion-test.js │ │ │ ├── __snapshots__/ │ │ │ │ └── ReactProfilerComponent-test.internal.js.snap │ │ │ ├── createReactClassIntegration-test.js │ │ │ ├── forwardRef-test.internal.js │ │ │ ├── forwardRef-test.js │ │ │ ├── onlyChild-test.js │ │ │ └── testDefinitions/ │ │ │ ├── PropTypes.d.ts │ │ │ ├── React.d.ts │ │ │ ├── ReactDOM.d.ts │ │ │ ├── ReactDOMClient.d.ts │ │ │ └── ReactInternalAct.d.ts │ │ └── jsx/ │ │ ├── ReactJSX.js │ │ ├── ReactJSXElement.js │ │ └── ReactJSXServer.js │ ├── react-art/ │ │ ├── Circle.js │ │ ├── README.md │ │ ├── Rectangle.js │ │ ├── Wedge.js │ │ ├── index.js │ │ ├── npm/ │ │ │ ├── Circle.js │ │ │ ├── Rectangle.js │ │ │ ├── Wedge.js │ │ │ └── index.js │ │ ├── package.json │ │ └── src/ │ │ ├── ReactART.js │ │ ├── ReactARTInternals.js │ │ ├── ReactFiberConfigART.js │ │ └── __tests__/ │ │ ├── ReactART-test.js │ │ └── __snapshots__/ │ │ └── ReactART-test.js.snap │ ├── react-cache/ │ │ ├── README.md │ │ ├── index.js │ │ ├── npm/ │ │ │ └── index.js │ │ ├── package.json │ │ └── src/ │ │ ├── LRU.js │ │ ├── ReactCacheOld.js │ │ └── __tests__/ │ │ └── ReactCacheOld-test.internal.js │ ├── react-client/ │ │ ├── README.md │ │ ├── flight.js │ │ ├── npm/ │ │ │ └── flight.js │ │ ├── package.json │ │ └── src/ │ │ ├── ReactClientConsoleConfigBrowser.js │ │ ├── ReactClientConsoleConfigPlain.js │ │ ├── ReactClientConsoleConfigServer.js │ │ ├── ReactClientDebugConfigBrowser.js │ │ ├── ReactClientDebugConfigNode.js │ │ ├── ReactClientDebugConfigPlain.js │ │ ├── ReactFlightClient.js │ │ ├── ReactFlightClientConfig.js │ │ ├── ReactFlightClientDevToolsHook.js │ │ ├── ReactFlightClientStreamConfigNode.js │ │ ├── ReactFlightClientStreamConfigWeb.js │ │ ├── ReactFlightPerformanceTrack.js │ │ ├── ReactFlightReplyClient.js │ │ ├── ReactFlightTemporaryReferences.js │ │ ├── __tests__/ │ │ │ ├── ReactFlight-test.js │ │ │ └── ReactFlightDebugChannel-test.js │ │ └── forks/ │ │ ├── ReactFlightClientConfig.custom.js │ │ ├── ReactFlightClientConfig.dom-browser-esm.js │ │ ├── ReactFlightClientConfig.dom-browser-parcel.js │ │ ├── ReactFlightClientConfig.dom-browser-turbopack.js │ │ ├── ReactFlightClientConfig.dom-browser.js │ │ ├── ReactFlightClientConfig.dom-bun.js │ │ ├── ReactFlightClientConfig.dom-edge-parcel.js │ │ ├── ReactFlightClientConfig.dom-edge-turbopack.js │ │ ├── ReactFlightClientConfig.dom-edge-webpack.js │ │ ├── ReactFlightClientConfig.dom-legacy.js │ │ ├── ReactFlightClientConfig.dom-node-esm.js │ │ ├── ReactFlightClientConfig.dom-node-parcel.js │ │ ├── ReactFlightClientConfig.dom-node-turbopack.js │ │ ├── ReactFlightClientConfig.dom-node-unbundled.js │ │ ├── ReactFlightClientConfig.dom-node.js │ │ ├── ReactFlightClientConfig.markup.js │ │ └── ReactFlightClientConfig.noop.js │ ├── react-debug-tools/ │ │ ├── README.md │ │ ├── index.js │ │ ├── npm/ │ │ │ └── index.js │ │ ├── package.json │ │ └── src/ │ │ ├── ReactDebugHooks.js │ │ ├── ReactDebugTools.js │ │ └── __tests__/ │ │ ├── ReactDevToolsHooksIntegration-test.js │ │ ├── ReactHooksInspection-test.js │ │ ├── ReactHooksInspectionIntegration-test.js │ │ └── ReactHooksInspectionIntegrationDOM-test.js │ ├── react-devtools/ │ │ ├── CHANGELOG.md │ │ ├── CONTRIBUTING.md │ │ ├── OVERVIEW.md │ │ ├── README.md │ │ ├── app.html │ │ ├── app.js │ │ ├── bin.js │ │ ├── package.json │ │ └── preload.js │ ├── react-devtools-core/ │ │ ├── README.md │ │ ├── backend.js │ │ ├── package.json │ │ ├── src/ │ │ │ ├── backend.js │ │ │ ├── editor.js │ │ │ └── standalone.js │ │ ├── standalone.js │ │ ├── webpack.backend.js │ │ └── webpack.standalone.js │ ├── react-devtools-extensions/ │ │ ├── .circleci/ │ │ │ └── config.yml │ │ ├── README.md │ │ ├── build.js │ │ ├── chrome/ │ │ │ ├── README.md │ │ │ ├── build.js │ │ │ ├── deploy.js │ │ │ ├── manifest.json │ │ │ ├── now.json │ │ │ └── test.js │ │ ├── deploy.chrome.html │ │ ├── deploy.edge.html │ │ ├── deploy.firefox.html │ │ ├── deploy.html │ │ ├── deploy.js │ │ ├── edge/ │ │ │ ├── README.md │ │ │ ├── build.js │ │ │ ├── deploy.js │ │ │ ├── manifest.json │ │ │ ├── now.json │ │ │ └── test.js │ │ ├── firefox/ │ │ │ ├── README.md │ │ │ ├── build.js │ │ │ ├── deploy.js │ │ │ ├── manifest.json │ │ │ ├── now.json │ │ │ └── test.js │ │ ├── flow-typed/ │ │ │ ├── jest.js │ │ │ └── npm/ │ │ │ └── react-test-renderer_v16.x.x.js │ │ ├── improveImages.mjs │ │ ├── main.html │ │ ├── package.json │ │ ├── panel.html │ │ ├── popups/ │ │ │ ├── deadcode.html │ │ │ ├── development.html │ │ │ ├── disabled.html │ │ │ ├── outdated.html │ │ │ ├── production.html │ │ │ ├── restricted.html │ │ │ ├── shared.css │ │ │ ├── shared.js │ │ │ └── unminified.html │ │ ├── src/ │ │ │ ├── __tests__/ │ │ │ │ └── ignoreList-test.js │ │ │ ├── backend.js │ │ │ ├── background/ │ │ │ │ ├── dynamicallyInjectContentScripts.js │ │ │ │ ├── executeScript.js │ │ │ │ ├── index.js │ │ │ │ ├── messageHandlers.js │ │ │ │ ├── setExtensionIconAndPopup.js │ │ │ │ └── tabsManager.js │ │ │ ├── contentScripts/ │ │ │ │ ├── backendManager.js │ │ │ │ ├── fallbackEvalContext.js │ │ │ │ ├── fileFetcher.js │ │ │ │ ├── hookSettingsInjector.js │ │ │ │ ├── installHook.js │ │ │ │ ├── messages.js │ │ │ │ ├── prepareInjection.js │ │ │ │ ├── proxy.js │ │ │ │ └── reactBuildType.js │ │ │ ├── evalScripts.js │ │ │ ├── main/ │ │ │ │ ├── cloneStyleTags.js │ │ │ │ ├── debounce.js │ │ │ │ ├── elementSelection.js │ │ │ │ ├── evalInInspectedWindow.js │ │ │ │ ├── fetchFileWithCaching.js │ │ │ │ ├── getProfilingFlags.js │ │ │ │ ├── index.js │ │ │ │ ├── injectBackendManager.js │ │ │ │ ├── reactPolling.js │ │ │ │ ├── registerEventsLogger.js │ │ │ │ ├── requestAnimationFramePolyfill.js │ │ │ │ └── sourceSelection.js │ │ │ ├── panel.js │ │ │ └── utils.js │ │ ├── utils.js │ │ └── webpack.config.js │ ├── react-devtools-fusebox/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── frontend.d.ts │ │ │ └── frontend.js │ │ └── webpack.config.frontend.js │ ├── react-devtools-inline/ │ │ ├── README.md │ │ ├── __tests__/ │ │ │ └── __e2e__/ │ │ │ ├── components.test.js │ │ │ ├── devtools-utils.js │ │ │ ├── list-app-utils.js │ │ │ ├── profiler.test.js │ │ │ └── utils.js │ │ ├── backend.js │ │ ├── frontend.js │ │ ├── hookNames.js │ │ ├── package.json │ │ ├── playwright.config.js │ │ ├── src/ │ │ │ ├── backend.js │ │ │ ├── frontend.js │ │ │ └── hookNames.js │ │ └── webpack.config.js │ ├── react-devtools-shared/ │ │ ├── README.md │ │ ├── SourceMapIgnoreListPlugin.js │ │ ├── babel.config.js │ │ ├── buildUtils.js │ │ ├── package.json │ │ └── src/ │ │ ├── Logger.js │ │ ├── PerformanceLoggingUtils.js │ │ ├── UnsupportedBridgeOperationError.js │ │ ├── __tests__/ │ │ │ ├── FastRefreshDevToolsIntegration-test.js │ │ │ ├── TimelineProfiler-test.js │ │ │ ├── __mocks__/ │ │ │ │ └── cssMock.js │ │ │ ├── __serializers__/ │ │ │ │ ├── dehydratedValueSerializer.js │ │ │ │ ├── hookSerializer.js │ │ │ │ ├── inspectedElementSerializer.js │ │ │ │ ├── numberToFixedSerializer.js │ │ │ │ ├── profilingSerializer.js │ │ │ │ ├── storeSerializer.js │ │ │ │ ├── timelineDataSerializer.js │ │ │ │ └── treeContextStateSerializer.js │ │ │ ├── bridge-test.js │ │ │ ├── compiler-integration-test.js │ │ │ ├── componentStacks-test.js │ │ │ ├── console-test.js │ │ │ ├── editing-test.js │ │ │ ├── events-test.js │ │ │ ├── gate-test.js │ │ │ ├── inspectedElement-test.js │ │ │ ├── legacy/ │ │ │ │ ├── editing-test.js │ │ │ │ ├── inspectElement-test.js │ │ │ │ └── storeLegacy-v15-test.js │ │ │ ├── optimisticKeyDevToolsIntegration.js │ │ │ ├── ownersListContext-test.js │ │ │ ├── preprocessData-test.js │ │ │ ├── profilerChangeDescriptions-test.js │ │ │ ├── profilerContext-test.js │ │ │ ├── profilerStore-test.js │ │ │ ├── profilingCache-test.js │ │ │ ├── profilingCharts-test.js │ │ │ ├── profilingCommitTreeBuilder-test.js │ │ │ ├── profilingHostRoot-test.js │ │ │ ├── profilingUtils-test.js │ │ │ ├── setupTests.js │ │ │ ├── store-test.js │ │ │ ├── storeComponentFilters-test.js │ │ │ ├── storeForceError-test.js │ │ │ ├── storeOwners-test.js │ │ │ ├── storeStressSync-test.js │ │ │ ├── storeStressTestConcurrent-test.js │ │ │ ├── traceUpdates-test.js │ │ │ ├── transform-react-version-pragma-test.js │ │ │ ├── treeContext-test.js │ │ │ ├── useEditableValue-test.js │ │ │ ├── utils-test.js │ │ │ └── utils.js │ │ ├── attachRenderer.js │ │ ├── backend/ │ │ │ ├── DevToolsNativeHost.js │ │ │ ├── NativeStyleEditor/ │ │ │ │ ├── resolveBoxStyle.js │ │ │ │ ├── setupNativeStyleEditor.js │ │ │ │ └── types.js │ │ │ ├── StyleX/ │ │ │ │ ├── __tests__/ │ │ │ │ │ └── utils-test.js │ │ │ │ └── utils.js │ │ │ ├── agent.js │ │ │ ├── fiber/ │ │ │ │ ├── DevToolsFiberComponentStack.js │ │ │ │ ├── renderer.js │ │ │ │ └── shared/ │ │ │ │ ├── DevToolsFiberChangeDetection.js │ │ │ │ ├── DevToolsFiberInspection.js │ │ │ │ ├── DevToolsFiberInternalReactConstants.js │ │ │ │ ├── DevToolsFiberSuspense.js │ │ │ │ └── DevToolsFiberTypes.js │ │ │ ├── flight/ │ │ │ │ ├── DevToolsComponentInfoStack.js │ │ │ │ └── renderer.js │ │ │ ├── index.js │ │ │ ├── legacy/ │ │ │ │ ├── renderer.js │ │ │ │ └── utils.js │ │ │ ├── profilingHooks.js │ │ │ ├── shared/ │ │ │ │ ├── DevToolsComponentStackFrame.js │ │ │ │ ├── DevToolsConsolePatching.js │ │ │ │ ├── DevToolsOwnerStack.js │ │ │ │ ├── DevToolsServerComponentLogs.js │ │ │ │ └── ReactSymbols.js │ │ │ ├── types.js │ │ │ ├── utils/ │ │ │ │ ├── formatConsoleArguments.js │ │ │ │ ├── formatWithStyles.js │ │ │ │ ├── index.js │ │ │ │ └── parseStackTrace.js │ │ │ └── views/ │ │ │ ├── Highlighter/ │ │ │ │ ├── Highlighter.js │ │ │ │ ├── Overlay.js │ │ │ │ └── index.js │ │ │ ├── TraceUpdates/ │ │ │ │ ├── canvas.js │ │ │ │ └── index.js │ │ │ └── utils.js │ │ ├── backendAPI.js │ │ ├── bridge.js │ │ ├── config/ │ │ │ ├── DevToolsFeatureFlags.core-fb.js │ │ │ ├── DevToolsFeatureFlags.core-oss.js │ │ │ ├── DevToolsFeatureFlags.default.js │ │ │ ├── DevToolsFeatureFlags.extension-fb.js │ │ │ └── DevToolsFeatureFlags.extension-oss.js │ │ ├── constants.js │ │ ├── devtools/ │ │ │ ├── ContextMenu/ │ │ │ │ ├── ContextMenu.css │ │ │ │ ├── ContextMenu.js │ │ │ │ ├── ContextMenuContainer.js │ │ │ │ ├── ContextMenuItem.css │ │ │ │ ├── ContextMenuItem.js │ │ │ │ ├── types.js │ │ │ │ └── useContextMenu.js │ │ │ ├── ProfilerStore.js │ │ │ ├── ProfilingCache.js │ │ │ ├── cache.js │ │ │ ├── constants.js │ │ │ ├── index.js │ │ │ ├── store.js │ │ │ ├── utils.js │ │ │ └── views/ │ │ │ ├── Button.css │ │ │ ├── Button.js │ │ │ ├── ButtonIcon.css │ │ │ ├── ButtonIcon.js │ │ │ ├── ButtonLabel.css │ │ │ ├── ButtonLabel.js │ │ │ ├── Components/ │ │ │ │ ├── ActivitySlice.css │ │ │ │ ├── ActivitySlice.js │ │ │ │ ├── Badge.css │ │ │ │ ├── Badge.js │ │ │ │ ├── ComponentSearchInput.js │ │ │ │ ├── Components.css │ │ │ │ ├── Components.js │ │ │ │ ├── EditableName.css │ │ │ │ ├── EditableName.js │ │ │ │ ├── EditableValue.css │ │ │ │ ├── EditableValue.js │ │ │ │ ├── Element.css │ │ │ │ ├── Element.js │ │ │ │ ├── ElementBadges.css │ │ │ │ ├── ElementBadges.js │ │ │ │ ├── ExpandCollapseToggle.css │ │ │ │ ├── ExpandCollapseToggle.js │ │ │ │ ├── FetchFileWithCachingContext.js │ │ │ │ ├── ForgetBadge.css │ │ │ │ ├── ForgetBadge.js │ │ │ │ ├── HookNamesModuleLoaderContext.js │ │ │ │ ├── IndexableDisplayName.js │ │ │ │ ├── IndexableElementBadges.css │ │ │ │ ├── IndexableElementBadges.js │ │ │ │ ├── InspectHostNodesToggle.js │ │ │ │ ├── InspectedElement.css │ │ │ │ ├── InspectedElement.js │ │ │ │ ├── InspectedElementBadges.css │ │ │ │ ├── InspectedElementBadges.js │ │ │ │ ├── InspectedElementContext.js │ │ │ │ ├── InspectedElementContextTree.js │ │ │ │ ├── InspectedElementErrorBoundary.css │ │ │ │ ├── InspectedElementErrorBoundary.js │ │ │ │ ├── InspectedElementErrorsAndWarningsTree.css │ │ │ │ ├── InspectedElementErrorsAndWarningsTree.js │ │ │ │ ├── InspectedElementHooksTree.css │ │ │ │ ├── InspectedElementHooksTree.js │ │ │ │ ├── InspectedElementPropsTree.js │ │ │ │ ├── InspectedElementSharedStyles.css │ │ │ │ ├── InspectedElementSourcePanel.css │ │ │ │ ├── InspectedElementSourcePanel.js │ │ │ │ ├── InspectedElementStateTree.js │ │ │ │ ├── InspectedElementStyleXPlugin.css │ │ │ │ ├── InspectedElementStyleXPlugin.js │ │ │ │ ├── InspectedElementSuspendedBy.js │ │ │ │ ├── InspectedElementView.css │ │ │ │ ├── InspectedElementView.js │ │ │ │ ├── InspectedElementViewSourceButton.js │ │ │ │ ├── KeyValue.css │ │ │ │ ├── KeyValue.js │ │ │ │ ├── KeyValueContextMenuContainer.css │ │ │ │ ├── KeyValueContextMenuContainer.js │ │ │ │ ├── LoadingAnimation.css │ │ │ │ ├── LoadingAnimation.js │ │ │ │ ├── NativeStyleEditor/ │ │ │ │ │ ├── AutoSizeInput.css │ │ │ │ │ ├── AutoSizeInput.js │ │ │ │ │ ├── LayoutViewer.css │ │ │ │ │ ├── LayoutViewer.js │ │ │ │ │ ├── StyleEditor.css │ │ │ │ │ ├── StyleEditor.js │ │ │ │ │ ├── context.js │ │ │ │ │ ├── index.css │ │ │ │ │ ├── index.js │ │ │ │ │ └── types.js │ │ │ │ ├── NativeTagBadge.css │ │ │ │ ├── NativeTagBadge.js │ │ │ │ ├── NewArrayValue.css │ │ │ │ ├── NewArrayValue.js │ │ │ │ ├── NewKeyValue.css │ │ │ │ ├── NewKeyValue.js │ │ │ │ ├── OpenInEditorButton.js │ │ │ │ ├── OwnerView.css │ │ │ │ ├── OwnerView.js │ │ │ │ ├── OwnersListContext.js │ │ │ │ ├── OwnersStack.css │ │ │ │ ├── OwnersStack.js │ │ │ │ ├── Skeleton.css │ │ │ │ ├── Skeleton.js │ │ │ │ ├── StackTraceView.css │ │ │ │ ├── StackTraceView.js │ │ │ │ ├── Tree.css │ │ │ │ ├── Tree.js │ │ │ │ ├── TreeContext.js │ │ │ │ ├── TreeFocusedContext.js │ │ │ │ ├── ViewElementSourceContext.js │ │ │ │ ├── constants.js │ │ │ │ ├── formatLocationForDisplay.js │ │ │ │ ├── reach-ui/ │ │ │ │ │ ├── Tooltip.css │ │ │ │ │ ├── menu-button.js │ │ │ │ │ └── tooltip.js │ │ │ │ └── utils.js │ │ │ ├── DevTools.css │ │ │ ├── DevTools.js │ │ │ ├── Editor/ │ │ │ │ ├── EditorPane.css │ │ │ │ ├── EditorPane.js │ │ │ │ ├── EditorSettings.css │ │ │ │ ├── EditorSettings.js │ │ │ │ ├── OpenInEditorButton.js │ │ │ │ └── utils.js │ │ │ ├── ErrorBoundary/ │ │ │ │ ├── CaughtErrorView.js │ │ │ │ ├── ErrorBoundary.js │ │ │ │ ├── ErrorView.js │ │ │ │ ├── ReportNewIssue.js │ │ │ │ ├── SearchingGitHubIssues.js │ │ │ │ ├── SuspendingErrorView.js │ │ │ │ ├── TimeoutView.js │ │ │ │ ├── UnsupportedBridgeOperationView.js │ │ │ │ ├── UpdateExistingIssue.js │ │ │ │ ├── WorkplaceGroup.js │ │ │ │ ├── cache.js │ │ │ │ ├── githubAPI.js │ │ │ │ ├── index.js │ │ │ │ └── shared.css │ │ │ ├── Icon.css │ │ │ ├── Icon.js │ │ │ ├── InspectedElement/ │ │ │ │ ├── InspectedElementPane.css │ │ │ │ └── InspectedElementPane.js │ │ │ ├── ModalDialog.css │ │ │ ├── ModalDialog.js │ │ │ ├── Profiler/ │ │ │ │ ├── ChartNode.css │ │ │ │ ├── ChartNode.js │ │ │ │ ├── ClearProfilingDataButton.js │ │ │ │ ├── CommitFlamegraph.css │ │ │ │ ├── CommitFlamegraph.js │ │ │ │ ├── CommitFlamegraphListItem.js │ │ │ │ ├── CommitRanked.css │ │ │ │ ├── CommitRanked.js │ │ │ │ ├── CommitRankedListItem.js │ │ │ │ ├── CommitTreeBuilder.js │ │ │ │ ├── FlamegraphChartBuilder.js │ │ │ │ ├── HookChangeSummary.css │ │ │ │ ├── HookChangeSummary.js │ │ │ │ ├── HoveredFiberInfo.css │ │ │ │ ├── HoveredFiberInfo.js │ │ │ │ ├── NoCommitData.css │ │ │ │ ├── NoCommitData.js │ │ │ │ ├── NoProfilingData.js │ │ │ │ ├── ProcessingData.js │ │ │ │ ├── Profiler.css │ │ │ │ ├── Profiler.js │ │ │ │ ├── ProfilerContext.js │ │ │ │ ├── ProfilingImportExportButtons.css │ │ │ │ ├── ProfilingImportExportButtons.js │ │ │ │ ├── ProfilingNotSupported.js │ │ │ │ ├── RankedChartBuilder.js │ │ │ │ ├── RecordToggle.css │ │ │ │ ├── RecordToggle.js │ │ │ │ ├── RecordingInProgress.js │ │ │ │ ├── ReloadAndProfileButton.js │ │ │ │ ├── RootSelector.css │ │ │ │ ├── RootSelector.js │ │ │ │ ├── SidebarCommitInfo.css │ │ │ │ ├── SidebarCommitInfo.js │ │ │ │ ├── SidebarEventInfo.css │ │ │ │ ├── SidebarEventInfo.js │ │ │ │ ├── SidebarSelectedFiberInfo.css │ │ │ │ ├── SidebarSelectedFiberInfo.js │ │ │ │ ├── SnapshotCommitList.css │ │ │ │ ├── SnapshotCommitList.js │ │ │ │ ├── SnapshotCommitListItem.css │ │ │ │ ├── SnapshotCommitListItem.js │ │ │ │ ├── SnapshotSelector.css │ │ │ │ ├── SnapshotSelector.js │ │ │ │ ├── Tooltip.css │ │ │ │ ├── Tooltip.js │ │ │ │ ├── Updaters.css │ │ │ │ ├── Updaters.js │ │ │ │ ├── WhatChanged.css │ │ │ │ ├── WhatChanged.js │ │ │ │ ├── constants.js │ │ │ │ ├── types.js │ │ │ │ ├── useCommitFilteringAndNavigation.js │ │ │ │ └── utils.js │ │ │ ├── ReactLogo.css │ │ │ ├── ReactLogo.js │ │ │ ├── SearchInput.css │ │ │ ├── SearchInput.js │ │ │ ├── Settings/ │ │ │ │ ├── CodeEditorByDefault.js │ │ │ │ ├── CodeEditorOptions.js │ │ │ │ ├── ComponentsSettings.js │ │ │ │ ├── DebuggingSettings.js │ │ │ │ ├── GeneralSettings.js │ │ │ │ ├── ProfilerSettings.js │ │ │ │ ├── SettingsContext.js │ │ │ │ ├── SettingsModal.css │ │ │ │ ├── SettingsModal.js │ │ │ │ ├── SettingsModalContext.js │ │ │ │ ├── SettingsModalContextToggle.js │ │ │ │ └── SettingsShared.css │ │ │ ├── SuspenseTab/ │ │ │ │ ├── ActivityList.css │ │ │ │ ├── ActivityList.js │ │ │ │ ├── SuspenseBreadcrumbs.css │ │ │ │ ├── SuspenseBreadcrumbs.js │ │ │ │ ├── SuspenseEnvironmentColors.css │ │ │ │ ├── SuspenseEnvironmentColors.js │ │ │ │ ├── SuspenseRects.css │ │ │ │ ├── SuspenseRects.js │ │ │ │ ├── SuspenseScrubber.css │ │ │ │ ├── SuspenseScrubber.js │ │ │ │ ├── SuspenseTab.css │ │ │ │ ├── SuspenseTab.js │ │ │ │ ├── SuspenseTimeline.css │ │ │ │ ├── SuspenseTimeline.js │ │ │ │ └── SuspenseTreeContext.js │ │ │ ├── TabBar.css │ │ │ ├── TabBar.js │ │ │ ├── ThemeProvider.js │ │ │ ├── Toggle.css │ │ │ ├── Toggle.js │ │ │ ├── UnsupportedBridgeProtocolDialog.css │ │ │ ├── UnsupportedBridgeProtocolDialog.js │ │ │ ├── UnsupportedVersionDialog.css │ │ │ ├── UnsupportedVersionDialog.js │ │ │ ├── WarnIfLegacyBackendDetected.css │ │ │ ├── WarnIfLegacyBackendDetected.js │ │ │ ├── context.js │ │ │ ├── hooks.js │ │ │ ├── portaledContent.js │ │ │ ├── root.css │ │ │ ├── useEditorURL.js │ │ │ ├── useInferredName.js │ │ │ ├── useOpenResource.js │ │ │ ├── useThemeStyles.js │ │ │ └── utils.js │ │ ├── dynamicImportCache.js │ │ ├── errors/ │ │ │ ├── ElementPollingCancellationError.js │ │ │ ├── PermissionNotGrantedError.js │ │ │ ├── TimeoutError.js │ │ │ ├── UnknownHookError.js │ │ │ └── UserError.js │ │ ├── events.js │ │ ├── frontend/ │ │ │ ├── hooks/ │ │ │ │ └── useExtensionComponentsPanelVisibility.js │ │ │ ├── types.js │ │ │ └── utils/ │ │ │ └── withPermissionsCheck.js │ │ ├── hook.js │ │ ├── hookNamesCache.js │ │ ├── hookSourceLocation.js │ │ ├── hooks/ │ │ │ ├── ErrorTester.js │ │ │ ├── ErrorTesterCompiled.js │ │ │ ├── SourceMapConsumer.js │ │ │ ├── SourceMapMetadataConsumer.js │ │ │ ├── SourceMapTypes.js │ │ │ ├── SourceMapUtils.js │ │ │ ├── __tests__/ │ │ │ │ ├── __source__/ │ │ │ │ │ ├── ComponentUsingHooksIndirectly.js │ │ │ │ │ ├── ComponentWithCustomHook.js │ │ │ │ │ ├── ComponentWithExternalCustomHooks.js │ │ │ │ │ ├── ComponentWithMultipleHooksPerLine.js │ │ │ │ │ ├── ComponentWithNestedHooks.js │ │ │ │ │ ├── ContainingStringSourceMappingURL.js │ │ │ │ │ ├── Example.js │ │ │ │ │ ├── InlineRequire.js │ │ │ │ │ ├── README.md │ │ │ │ │ ├── ToDoList.js │ │ │ │ │ ├── __compiled__/ │ │ │ │ │ │ ├── bundle/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── external/ │ │ │ │ │ │ │ ├── ComponentUsingHooksIndirectly.js │ │ │ │ │ │ │ ├── ComponentWithCustomHook.js │ │ │ │ │ │ │ ├── ComponentWithExternalCustomHooks.js │ │ │ │ │ │ │ ├── ComponentWithMultipleHooksPerLine.js │ │ │ │ │ │ │ ├── ComponentWithNestedHooks.js │ │ │ │ │ │ │ ├── ContainingStringSourceMappingURL.js │ │ │ │ │ │ │ ├── Example.js │ │ │ │ │ │ │ ├── InlineRequire.js │ │ │ │ │ │ │ ├── ToDoList.js │ │ │ │ │ │ │ ├── fb-sources-extended/ │ │ │ │ │ │ │ │ ├── ComponentUsingHooksIndirectly.js │ │ │ │ │ │ │ │ ├── ComponentWithCustomHook.js │ │ │ │ │ │ │ │ ├── ComponentWithExternalCustomHooks.js │ │ │ │ │ │ │ │ ├── ComponentWithMultipleHooksPerLine.js │ │ │ │ │ │ │ │ ├── ComponentWithNestedHooks.js │ │ │ │ │ │ │ │ ├── ContainingStringSourceMappingURL.js │ │ │ │ │ │ │ │ ├── Example.js │ │ │ │ │ │ │ │ ├── InlineRequire.js │ │ │ │ │ │ │ │ ├── ToDoList.js │ │ │ │ │ │ │ │ ├── index-map/ │ │ │ │ │ │ │ │ │ ├── ComponentUsingHooksIndirectly.js │ │ │ │ │ │ │ │ │ ├── ComponentWithCustomHook.js │ │ │ │ │ │ │ │ │ ├── ComponentWithExternalCustomHooks.js │ │ │ │ │ │ │ │ │ ├── ComponentWithMultipleHooksPerLine.js │ │ │ │ │ │ │ │ │ ├── ComponentWithNestedHooks.js │ │ │ │ │ │ │ │ │ ├── ContainingStringSourceMappingURL.js │ │ │ │ │ │ │ │ │ ├── Example.js │ │ │ │ │ │ │ │ │ ├── InlineRequire.js │ │ │ │ │ │ │ │ │ ├── ToDoList.js │ │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ │ └── useTheme.js │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ └── useTheme.js │ │ │ │ │ │ │ ├── index-map/ │ │ │ │ │ │ │ │ ├── ComponentUsingHooksIndirectly.js │ │ │ │ │ │ │ │ ├── ComponentWithCustomHook.js │ │ │ │ │ │ │ │ ├── ComponentWithExternalCustomHooks.js │ │ │ │ │ │ │ │ ├── ComponentWithMultipleHooksPerLine.js │ │ │ │ │ │ │ │ ├── ComponentWithNestedHooks.js │ │ │ │ │ │ │ │ ├── ContainingStringSourceMappingURL.js │ │ │ │ │ │ │ │ ├── Example.js │ │ │ │ │ │ │ │ ├── InlineRequire.js │ │ │ │ │ │ │ │ ├── ToDoList.js │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ └── useTheme.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── react-sources-extended/ │ │ │ │ │ │ │ │ ├── ComponentUsingHooksIndirectly.js │ │ │ │ │ │ │ │ ├── ComponentWithCustomHook.js │ │ │ │ │ │ │ │ ├── ComponentWithExternalCustomHooks.js │ │ │ │ │ │ │ │ ├── ComponentWithMultipleHooksPerLine.js │ │ │ │ │ │ │ │ ├── ComponentWithNestedHooks.js │ │ │ │ │ │ │ │ ├── ContainingStringSourceMappingURL.js │ │ │ │ │ │ │ │ ├── Example.js │ │ │ │ │ │ │ │ ├── InlineRequire.js │ │ │ │ │ │ │ │ ├── ToDoList.js │ │ │ │ │ │ │ │ ├── index-map/ │ │ │ │ │ │ │ │ │ ├── ComponentUsingHooksIndirectly.js │ │ │ │ │ │ │ │ │ ├── ComponentWithCustomHook.js │ │ │ │ │ │ │ │ │ ├── ComponentWithExternalCustomHooks.js │ │ │ │ │ │ │ │ │ ├── ComponentWithMultipleHooksPerLine.js │ │ │ │ │ │ │ │ │ ├── ComponentWithNestedHooks.js │ │ │ │ │ │ │ │ │ ├── ContainingStringSourceMappingURL.js │ │ │ │ │ │ │ │ │ ├── Example.js │ │ │ │ │ │ │ │ │ ├── InlineRequire.js │ │ │ │ │ │ │ │ │ ├── ToDoList.js │ │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ │ └── useTheme.js │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ └── useTheme.js │ │ │ │ │ │ │ └── useTheme.js │ │ │ │ │ │ ├── inline/ │ │ │ │ │ │ │ ├── ComponentUsingHooksIndirectly.js │ │ │ │ │ │ │ ├── ComponentWithCustomHook.js │ │ │ │ │ │ │ ├── ComponentWithExternalCustomHooks.js │ │ │ │ │ │ │ ├── ComponentWithMultipleHooksPerLine.js │ │ │ │ │ │ │ ├── ComponentWithNestedHooks.js │ │ │ │ │ │ │ ├── ContainingStringSourceMappingURL.js │ │ │ │ │ │ │ ├── Example.js │ │ │ │ │ │ │ ├── InlineRequire.js │ │ │ │ │ │ │ ├── ToDoList.js │ │ │ │ │ │ │ ├── fb-sources-extended/ │ │ │ │ │ │ │ │ ├── ComponentUsingHooksIndirectly.js │ │ │ │ │ │ │ │ ├── ComponentWithCustomHook.js │ │ │ │ │ │ │ │ ├── ComponentWithExternalCustomHooks.js │ │ │ │ │ │ │ │ ├── ComponentWithMultipleHooksPerLine.js │ │ │ │ │ │ │ │ ├── ComponentWithNestedHooks.js │ │ │ │ │ │ │ │ ├── ContainingStringSourceMappingURL.js │ │ │ │ │ │ │ │ ├── Example.js │ │ │ │ │ │ │ │ ├── InlineRequire.js │ │ │ │ │ │ │ │ ├── ToDoList.js │ │ │ │ │ │ │ │ ├── index-map/ │ │ │ │ │ │ │ │ │ ├── ComponentUsingHooksIndirectly.js │ │ │ │ │ │ │ │ │ ├── ComponentWithCustomHook.js │ │ │ │ │ │ │ │ │ ├── ComponentWithExternalCustomHooks.js │ │ │ │ │ │ │ │ │ ├── ComponentWithMultipleHooksPerLine.js │ │ │ │ │ │ │ │ │ ├── ComponentWithNestedHooks.js │ │ │ │ │ │ │ │ │ ├── ContainingStringSourceMappingURL.js │ │ │ │ │ │ │ │ │ ├── Example.js │ │ │ │ │ │ │ │ │ ├── InlineRequire.js │ │ │ │ │ │ │ │ │ ├── ToDoList.js │ │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ │ └── useTheme.js │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ └── useTheme.js │ │ │ │ │ │ │ ├── index-map/ │ │ │ │ │ │ │ │ ├── ComponentUsingHooksIndirectly.js │ │ │ │ │ │ │ │ ├── ComponentWithCustomHook.js │ │ │ │ │ │ │ │ ├── ComponentWithExternalCustomHooks.js │ │ │ │ │ │ │ │ ├── ComponentWithMultipleHooksPerLine.js │ │ │ │ │ │ │ │ ├── ComponentWithNestedHooks.js │ │ │ │ │ │ │ │ ├── ContainingStringSourceMappingURL.js │ │ │ │ │ │ │ │ ├── Example.js │ │ │ │ │ │ │ │ ├── InlineRequire.js │ │ │ │ │ │ │ │ ├── ToDoList.js │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ └── useTheme.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── react-sources-extended/ │ │ │ │ │ │ │ │ ├── ComponentUsingHooksIndirectly.js │ │ │ │ │ │ │ │ ├── ComponentWithCustomHook.js │ │ │ │ │ │ │ │ ├── ComponentWithExternalCustomHooks.js │ │ │ │ │ │ │ │ ├── ComponentWithMultipleHooksPerLine.js │ │ │ │ │ │ │ │ ├── ComponentWithNestedHooks.js │ │ │ │ │ │ │ │ ├── ContainingStringSourceMappingURL.js │ │ │ │ │ │ │ │ ├── Example.js │ │ │ │ │ │ │ │ ├── InlineRequire.js │ │ │ │ │ │ │ │ ├── ToDoList.js │ │ │ │ │ │ │ │ ├── index-map/ │ │ │ │ │ │ │ │ │ ├── ComponentUsingHooksIndirectly.js │ │ │ │ │ │ │ │ │ ├── ComponentWithCustomHook.js │ │ │ │ │ │ │ │ │ ├── ComponentWithExternalCustomHooks.js │ │ │ │ │ │ │ │ │ ├── ComponentWithMultipleHooksPerLine.js │ │ │ │ │ │ │ │ │ ├── ComponentWithNestedHooks.js │ │ │ │ │ │ │ │ │ ├── ContainingStringSourceMappingURL.js │ │ │ │ │ │ │ │ │ ├── Example.js │ │ │ │ │ │ │ │ │ ├── InlineRequire.js │ │ │ │ │ │ │ │ │ ├── ToDoList.js │ │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ │ └── useTheme.js │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ └── useTheme.js │ │ │ │ │ │ │ └── useTheme.js │ │ │ │ │ │ └── no-columns/ │ │ │ │ │ │ ├── ComponentUsingHooksIndirectly.js │ │ │ │ │ │ ├── ComponentWithCustomHook.js │ │ │ │ │ │ ├── ComponentWithExternalCustomHooks.js │ │ │ │ │ │ ├── ComponentWithMultipleHooksPerLine.js │ │ │ │ │ │ ├── ComponentWithNestedHooks.js │ │ │ │ │ │ ├── ContainingStringSourceMappingURL.js │ │ │ │ │ │ ├── Example.js │ │ │ │ │ │ ├── InlineRequire.js │ │ │ │ │ │ ├── ToDoList.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── useTheme.js │ │ │ │ │ ├── __untransformed__/ │ │ │ │ │ │ ├── ComponentUsingHooksIndirectly.js │ │ │ │ │ │ ├── ComponentWithExternalUseEffect.js │ │ │ │ │ │ ├── ComponentWithNamedCustomHooks.js │ │ │ │ │ │ ├── ComponentWithNestedHooks.js │ │ │ │ │ │ ├── ComponentWithUnnamedCustomHooks.js │ │ │ │ │ │ ├── ComponentWithUseEffect.js │ │ │ │ │ │ ├── ComponentWithUseReducer.js │ │ │ │ │ │ ├── ComponentWithUseState.js │ │ │ │ │ │ ├── README.md │ │ │ │ │ │ └── useCustom.js │ │ │ │ │ ├── index.js │ │ │ │ │ └── useTheme.js │ │ │ │ ├── generateHookMap-test.js │ │ │ │ ├── getHookNameForLocation-test.js │ │ │ │ ├── parseHookNames-test.js │ │ │ │ └── updateMockSourceMaps.js │ │ │ ├── astUtils.js │ │ │ ├── generateHookMap.js │ │ │ ├── getHookNameForLocation.js │ │ │ └── parseHookNames/ │ │ │ ├── index.js │ │ │ ├── loadSourceAndMetadata.js │ │ │ ├── parseSourceAndMetadata.js │ │ │ └── parseSourceAndMetadata.worker.js │ │ ├── hydration.js │ │ ├── inspectedElementCache.js │ │ ├── inspectedElementMutableSource.js │ │ ├── isArray.js │ │ ├── registerDevToolsEventLogger.js │ │ ├── storage.js │ │ ├── symbolicateSource.js │ │ └── utils.js │ ├── react-devtools-shell/ │ │ ├── README.md │ │ ├── constants.js │ │ ├── e2e-regression.html │ │ ├── e2e.html │ │ ├── index.html │ │ ├── multi.html │ │ ├── package.json │ │ ├── perf-regression.html │ │ ├── src/ │ │ │ ├── app/ │ │ │ │ ├── ActivityTree/ │ │ │ │ │ └── index.js │ │ │ │ ├── DeeplyNestedComponents/ │ │ │ │ │ └── index.js │ │ │ │ ├── EditableProps/ │ │ │ │ │ └── index.js │ │ │ │ ├── ElementTypes/ │ │ │ │ │ └── index.js │ │ │ │ ├── ErrorBoundaries/ │ │ │ │ │ └── index.js │ │ │ │ ├── Hydration/ │ │ │ │ │ └── index.js │ │ │ │ ├── Iframe/ │ │ │ │ │ └── index.js │ │ │ │ ├── InlineWarnings/ │ │ │ │ │ └── index.js │ │ │ │ ├── InspectableElements/ │ │ │ │ │ ├── CircularReferences.js │ │ │ │ │ ├── Contexts.js │ │ │ │ │ ├── CustomHooks.js │ │ │ │ │ ├── CustomObject.js │ │ │ │ │ ├── EdgeCaseObjects.js │ │ │ │ │ ├── InspectableElements.js │ │ │ │ │ ├── NestedProps.js │ │ │ │ │ ├── SimpleValues.js │ │ │ │ │ ├── SymbolKeys.js │ │ │ │ │ ├── UnserializableProps.js │ │ │ │ │ ├── UseEffectEvent.js │ │ │ │ │ ├── UseMemoCache.js │ │ │ │ │ ├── UseSyncExternalStore.js │ │ │ │ │ └── index.js │ │ │ │ ├── PartiallyStrictApp/ │ │ │ │ │ └── index.js │ │ │ │ ├── ReactNativeWeb/ │ │ │ │ │ └── index.js │ │ │ │ ├── Segments/ │ │ │ │ │ └── index.js │ │ │ │ ├── SuspenseTree/ │ │ │ │ │ └── index.js │ │ │ │ ├── ToDoList/ │ │ │ │ │ ├── List.css │ │ │ │ │ ├── List.js │ │ │ │ │ ├── ListItem.css │ │ │ │ │ ├── ListItem.js │ │ │ │ │ └── index.js │ │ │ │ ├── Toggle/ │ │ │ │ │ └── index.js │ │ │ │ ├── TraceUpdatesTest/ │ │ │ │ │ └── index.js │ │ │ │ ├── console.js │ │ │ │ ├── devtools.js │ │ │ │ ├── index.js │ │ │ │ └── styles.css │ │ │ ├── e2e/ │ │ │ │ ├── app.js │ │ │ │ └── devtools.js │ │ │ ├── e2e-apps/ │ │ │ │ ├── ListApp.js │ │ │ │ └── ListAppLegacy.js │ │ │ ├── e2e-regression/ │ │ │ │ ├── app-legacy.js │ │ │ │ ├── app.js │ │ │ │ └── devtools.js │ │ │ ├── multi/ │ │ │ │ ├── devtools.js │ │ │ │ ├── left.js │ │ │ │ └── right.js │ │ │ └── perf-regression/ │ │ │ ├── app.js │ │ │ ├── apps/ │ │ │ │ ├── LargeSubtree.js │ │ │ │ └── index.js │ │ │ └── devtools.js │ │ └── webpack-server.js │ ├── react-devtools-timeline/ │ │ ├── README.md │ │ ├── package.json │ │ └── src/ │ │ ├── CanvasPage.css │ │ ├── CanvasPage.js │ │ ├── CanvasPageContextMenu.js │ │ ├── EventTooltip.css │ │ ├── EventTooltip.js │ │ ├── Timeline.css │ │ ├── Timeline.js │ │ ├── TimelineContext.js │ │ ├── TimelineNotSupported.css │ │ ├── TimelineNotSupported.js │ │ ├── TimelineSearchContext.js │ │ ├── TimelineSearchInput.js │ │ ├── constants.js │ │ ├── content-views/ │ │ │ ├── ComponentMeasuresView.js │ │ │ ├── FlamechartView.js │ │ │ ├── NativeEventsView.js │ │ │ ├── NetworkMeasuresView.js │ │ │ ├── ReactMeasuresView.js │ │ │ ├── SchedulingEventsView.js │ │ │ ├── SnapshotsView.js │ │ │ ├── SuspenseEventsView.js │ │ │ ├── ThrownErrorsView.js │ │ │ ├── TimeAxisMarkersView.js │ │ │ ├── UserTimingMarksView.js │ │ │ ├── constants.js │ │ │ ├── index.js │ │ │ └── utils/ │ │ │ ├── __tests__/ │ │ │ │ ├── __modules__/ │ │ │ │ │ ├── module-one.js │ │ │ │ │ └── module-two.js │ │ │ │ ├── colors-test.js │ │ │ │ └── moduleFilters-test.js │ │ │ ├── colors.js │ │ │ ├── moduleFilters.js │ │ │ ├── positioning.js │ │ │ └── text.js │ │ ├── createDataResourceFromImportedFile.js │ │ ├── import-worker/ │ │ │ ├── InvalidProfileError.js │ │ │ ├── importFile.js │ │ │ ├── importFile.worker.js │ │ │ ├── index.js │ │ │ ├── preprocessData.js │ │ │ └── readInputData.js │ │ ├── timelineCache.js │ │ ├── types.js │ │ ├── utils/ │ │ │ ├── flow.js │ │ │ ├── formatting.js │ │ │ ├── getBatchRange.js │ │ │ └── useSmartTooltip.js │ │ └── view-base/ │ │ ├── BackgroundColorView.js │ │ ├── HorizontalPanAndZoomView.js │ │ ├── Surface.js │ │ ├── VerticalScrollView.js │ │ ├── View.js │ │ ├── __tests__/ │ │ │ └── geometry-test.js │ │ ├── constants.js │ │ ├── geometry.js │ │ ├── index.js │ │ ├── layouter.js │ │ ├── resizable/ │ │ │ ├── ResizableView.js │ │ │ ├── ResizeBarView.js │ │ │ └── index.js │ │ ├── useCanvasInteraction.js │ │ ├── utils/ │ │ │ ├── __tests__/ │ │ │ │ ├── clamp-test.js │ │ │ │ └── scrollState-test.js │ │ │ ├── clamp.js │ │ │ ├── normalizeWheel.js │ │ │ └── scrollState.js │ │ └── vertical-scroll-overflow/ │ │ ├── VerticalScrollBarView.js │ │ ├── VerticalScrollOverflowView.js │ │ ├── index.js │ │ └── withVerticalScrollbarLayout.js │ ├── react-dom/ │ │ ├── README.md │ │ ├── client.js │ │ ├── index.js │ │ ├── npm/ │ │ │ ├── client.js │ │ │ ├── client.react-server.js │ │ │ ├── index.js │ │ │ ├── profiling.js │ │ │ ├── profiling.react-server.js │ │ │ ├── react-dom.react-server.js │ │ │ ├── server.browser.js │ │ │ ├── server.bun.js │ │ │ ├── server.edge.js │ │ │ ├── server.js │ │ │ ├── server.node.js │ │ │ ├── server.react-server.js │ │ │ ├── static.browser.js │ │ │ ├── static.edge.js │ │ │ ├── static.js │ │ │ ├── static.node.js │ │ │ ├── static.react-server.js │ │ │ ├── test-utils.js │ │ │ ├── unstable_testing.js │ │ │ └── unstable_testing.react-server.js │ │ ├── package.json │ │ ├── profiling.js │ │ ├── server.browser.js │ │ ├── server.bun.js │ │ ├── server.edge.js │ │ ├── server.js │ │ ├── server.node.js │ │ ├── src/ │ │ │ ├── ReactDOMFB.js │ │ │ ├── ReactDOMFB.modern.js │ │ │ ├── ReactDOMReactServer.js │ │ │ ├── ReactDOMSharedInternals.js │ │ │ ├── ReactDOMSharedInternalsFB.js │ │ │ ├── ReactDOMTestingFB.js │ │ │ ├── ReactDOMTestingFB.modern.js │ │ │ ├── __tests__/ │ │ │ │ ├── CSSPropertyOperations-test.js │ │ │ │ ├── DOMPropertyOperations-test.js │ │ │ │ ├── InvalidEventListeners-test.js │ │ │ │ ├── ReactBrowserEventEmitter-test.js │ │ │ │ ├── ReactChildReconciler-test.js │ │ │ │ ├── ReactClassComponentPropResolutionFizz-test.js │ │ │ │ ├── ReactComponent-test.js │ │ │ │ ├── ReactComponentLifeCycle-test.js │ │ │ │ ├── ReactCompositeComponent-test.js │ │ │ │ ├── ReactCompositeComponentDOMMinimalism-test.js │ │ │ │ ├── ReactCompositeComponentNestedState-test.js │ │ │ │ ├── ReactCompositeComponentState-test.js │ │ │ │ ├── ReactDOM-test.js │ │ │ │ ├── ReactDOMActivity-test.js │ │ │ │ ├── ReactDOMAttribute-test.js │ │ │ │ ├── ReactDOMComponent-test.js │ │ │ │ ├── ReactDOMComponentTree-test.js │ │ │ │ ├── ReactDOMConsoleErrorReporting-test.js │ │ │ │ ├── ReactDOMConsoleErrorReportingLegacy-test.js │ │ │ │ ├── ReactDOMEventListener-test.js │ │ │ │ ├── ReactDOMEventPropagation-test.js │ │ │ │ ├── ReactDOMFiber-test.js │ │ │ │ ├── ReactDOMFiberAsync-test.js │ │ │ │ ├── ReactDOMFizzDeferredValue-test.js │ │ │ │ ├── ReactDOMFizzForm-test.js │ │ │ │ ├── ReactDOMFizzServer-test.js │ │ │ │ ├── ReactDOMFizzServerBrowser-test.js │ │ │ │ ├── ReactDOMFizzServerEdge-test.js │ │ │ │ ├── ReactDOMFizzServerNode-test.js │ │ │ │ ├── ReactDOMFizzShellHydration-test.js │ │ │ │ ├── ReactDOMFizzStatic-test.js │ │ │ │ ├── ReactDOMFizzStaticBrowser-test.js │ │ │ │ ├── ReactDOMFizzStaticNode-test.js │ │ │ │ ├── ReactDOMFizzSuppressHydrationWarning-test.js │ │ │ │ ├── ReactDOMFizzSuspenseList-test.js │ │ │ │ ├── ReactDOMFizzViewTransition-test.js │ │ │ │ ├── ReactDOMFloat-test.js │ │ │ │ ├── ReactDOMForm-test.js │ │ │ │ ├── ReactDOMFragmentRefs-test.js │ │ │ │ ├── ReactDOMHooks-test.js │ │ │ │ ├── ReactDOMHostComponentTransitions-test.js │ │ │ │ ├── ReactDOMHydrationDiff-test.js │ │ │ │ ├── ReactDOMIframe-test.js │ │ │ │ ├── ReactDOMImageLoad-test.internal.js │ │ │ │ ├── ReactDOMInReactServer-test.js │ │ │ │ ├── ReactDOMInput-test.js │ │ │ │ ├── ReactDOMInvalidARIAHook-test.js │ │ │ │ ├── ReactDOMLegacyComponentTree-test.internal.js │ │ │ │ ├── ReactDOMLegacyFiber-test.js │ │ │ │ ├── ReactDOMLegacyFloat-test.js │ │ │ │ ├── ReactDOMNativeEventHeuristic-test.js │ │ │ │ ├── ReactDOMNestedEvents-test.js │ │ │ │ ├── ReactDOMOption-test.js │ │ │ │ ├── ReactDOMRoot-test.js │ │ │ │ ├── ReactDOMSVG-test.js │ │ │ │ ├── ReactDOMSafariMicrotaskBug-test.js │ │ │ │ ├── ReactDOMSelect-test.js │ │ │ │ ├── ReactDOMSelection-test.internal.js │ │ │ │ ├── ReactDOMServerIntegrationAttributes-test.js │ │ │ │ ├── ReactDOMServerIntegrationBasic-test.js │ │ │ │ ├── ReactDOMServerIntegrationCheckbox-test.js │ │ │ │ ├── ReactDOMServerIntegrationClassContextType-test.js │ │ │ │ ├── ReactDOMServerIntegrationElements-test.js │ │ │ │ ├── ReactDOMServerIntegrationFragment-test.js │ │ │ │ ├── ReactDOMServerIntegrationHooks-test.js │ │ │ │ ├── ReactDOMServerIntegrationInput-test.js │ │ │ │ ├── ReactDOMServerIntegrationLegacyContext-test.js │ │ │ │ ├── ReactDOMServerIntegrationLegacyContextDisabled-test.internal.js │ │ │ │ ├── ReactDOMServerIntegrationModes-test.js │ │ │ │ ├── ReactDOMServerIntegrationNewContext-test.js │ │ │ │ ├── ReactDOMServerIntegrationObject-test.js │ │ │ │ ├── ReactDOMServerIntegrationReconnecting-test.js │ │ │ │ ├── ReactDOMServerIntegrationRefs-test.js │ │ │ │ ├── ReactDOMServerIntegrationSelect-test.js │ │ │ │ ├── ReactDOMServerIntegrationSpecialTypes-test.js │ │ │ │ ├── ReactDOMServerIntegrationTextarea-test.js │ │ │ │ ├── ReactDOMServerIntegrationUntrustedURL-test.js │ │ │ │ ├── ReactDOMServerIntegrationUserInteraction-test.js │ │ │ │ ├── ReactDOMServerLifecycles-test.js │ │ │ │ ├── ReactDOMServerPartialHydration-test.internal.js │ │ │ │ ├── ReactDOMServerPartialHydrationActivity-test.internal.js │ │ │ │ ├── ReactDOMServerSelectiveHydration-test.internal.js │ │ │ │ ├── ReactDOMServerSelectiveHydrationActivity-test.internal.js │ │ │ │ ├── ReactDOMServerSuspense-test.internal.js │ │ │ │ ├── ReactDOMShorthandCSSPropertyCollision-test.js │ │ │ │ ├── ReactDOMSingletonComponents-test.js │ │ │ │ ├── ReactDOMSrcObject-test.js │ │ │ │ ├── ReactDOMSuspensePlaceholder-test.js │ │ │ │ ├── ReactDOMTestSelectors-test.js │ │ │ │ ├── ReactDOMTextComponent-test.js │ │ │ │ ├── ReactDOMTextarea-test.js │ │ │ │ ├── ReactDOMUseId-test.js │ │ │ │ ├── ReactDOMViewTransition-test.js │ │ │ │ ├── ReactDOMserverIntegrationProgress-test.js │ │ │ │ ├── ReactEmptyComponent-test.js │ │ │ │ ├── ReactErrorBoundaries-test.internal.js │ │ │ │ ├── ReactErrorBoundariesHooks-test.internal.js │ │ │ │ ├── ReactErrorLoggingRecovery-test.js │ │ │ │ ├── ReactEventIndependence-test.js │ │ │ │ ├── ReactFunctionComponent-test.js │ │ │ │ ├── ReactIdentity-test.js │ │ │ │ ├── ReactLegacyCompositeComponent-test.js │ │ │ │ ├── ReactLegacyContextDisabled-test.internal.js │ │ │ │ ├── ReactLegacyErrorBoundaries-test.internal.js │ │ │ │ ├── ReactLegacyMount-test.js │ │ │ │ ├── ReactLegacyRootWarnings-test.js │ │ │ │ ├── ReactLegacyUpdates-test.js │ │ │ │ ├── ReactMockedComponent-test.js │ │ │ │ ├── ReactMountDestruction-test.js │ │ │ │ ├── ReactMultiChild-test.js │ │ │ │ ├── ReactMultiChildReconcile-test.js │ │ │ │ ├── ReactMultiChildText-test.js │ │ │ │ ├── ReactRenderDocument-test.js │ │ │ │ ├── ReactServerRendering-test.js │ │ │ │ ├── ReactServerRenderingBrowser-test.js │ │ │ │ ├── ReactServerRenderingHydration-test.js │ │ │ │ ├── ReactStartTransitionMultipleRenderers-test.js │ │ │ │ ├── ReactTestUtilsAct-test.js │ │ │ │ ├── ReactTestUtilsActUnmockedScheduler-test.js │ │ │ │ ├── ReactTreeTraversal-test.js │ │ │ │ ├── ReactUpdates-test.js │ │ │ │ ├── ReactWrongReturnPointer-test.js │ │ │ │ ├── escapeTextForBrowser-test.js │ │ │ │ ├── findDOMNodeFB-test.js │ │ │ │ ├── quoteAttributeValueForBrowser-test.js │ │ │ │ ├── refs-destruction-test.js │ │ │ │ ├── refs-test.js │ │ │ │ ├── refsLegacy-test.js │ │ │ │ ├── utils/ │ │ │ │ │ ├── IntersectionMocks.js │ │ │ │ │ └── ReactDOMServerIntegrationTestUtils.js │ │ │ │ └── validateDOMNesting-test.js │ │ │ ├── client/ │ │ │ │ ├── ReactDOMClient.js │ │ │ │ ├── ReactDOMClientFB.js │ │ │ │ ├── ReactDOMDefaultTransitionIndicator.js │ │ │ │ ├── ReactDOMRoot.js │ │ │ │ ├── ReactDOMRootFB.js │ │ │ │ ├── __mocks__/ │ │ │ │ │ └── ReactFiberErrorDialog.js │ │ │ │ └── __tests__/ │ │ │ │ ├── dangerouslySetInnerHTML-test.js │ │ │ │ ├── getNodeForCharacterOffset-test.js │ │ │ │ └── trustedTypes-test.internal.js │ │ │ ├── events/ │ │ │ │ ├── __tests__/ │ │ │ │ │ ├── DOMPluginEventSystem-test.internal.js │ │ │ │ │ ├── SyntheticClipboardEvent-test.js │ │ │ │ │ ├── SyntheticEvent-test.js │ │ │ │ │ ├── SyntheticFocusEvent-test.js │ │ │ │ │ ├── SyntheticKeyboardEvent-test.js │ │ │ │ │ ├── SyntheticMouseEvent-test.js │ │ │ │ │ ├── SyntheticWheelEvent-test.js │ │ │ │ │ └── getEventKey-test.js │ │ │ │ └── plugins/ │ │ │ │ └── __tests__/ │ │ │ │ ├── BeforeInputEventPlugin-test.js │ │ │ │ ├── ChangeEventPlugin-test.js │ │ │ │ ├── EnterLeaveEventPlugin-test.js │ │ │ │ ├── SelectEventPlugin-test.js │ │ │ │ └── SimpleEventPlugin-test.js │ │ │ ├── server/ │ │ │ │ ├── ReactDOMFizzServerBrowser.js │ │ │ │ ├── ReactDOMFizzServerBun.js │ │ │ │ ├── ReactDOMFizzServerEdge.js │ │ │ │ ├── ReactDOMFizzServerNode.js │ │ │ │ ├── ReactDOMFizzStaticBrowser.js │ │ │ │ ├── ReactDOMFizzStaticEdge.js │ │ │ │ ├── ReactDOMFizzStaticNode.js │ │ │ │ ├── ReactDOMLegacyServerBrowser.js │ │ │ │ ├── ReactDOMLegacyServerImpl.js │ │ │ │ ├── ReactDOMLegacyServerNode.js │ │ │ │ ├── react-dom-server.browser.js │ │ │ │ ├── react-dom-server.browser.stable.js │ │ │ │ ├── react-dom-server.bun.js │ │ │ │ ├── react-dom-server.bun.stable.js │ │ │ │ ├── react-dom-server.edge.js │ │ │ │ ├── react-dom-server.edge.stable.js │ │ │ │ ├── react-dom-server.node.js │ │ │ │ └── react-dom-server.node.stable.js │ │ │ ├── shared/ │ │ │ │ ├── ReactDOM.js │ │ │ │ ├── ReactDOMFloat.js │ │ │ │ ├── ReactDOMFlushSync.js │ │ │ │ ├── ReactDOMTypes.js │ │ │ │ └── ensureCorrectIsomorphicReactVersion.js │ │ │ └── test-utils/ │ │ │ ├── FizzTestUtils.js │ │ │ └── ReactTestUtils.js │ │ ├── static.browser.js │ │ ├── static.edge.js │ │ ├── static.js │ │ ├── static.node.js │ │ ├── test-utils.js │ │ ├── unstable_server-external-runtime.js │ │ ├── unstable_testing.experimental.js │ │ └── unstable_testing.js │ ├── react-dom-bindings/ │ │ ├── package.json │ │ └── src/ │ │ ├── client/ │ │ │ ├── CSSPropertyOperations.js │ │ │ ├── CSSShorthandProperty.js │ │ │ ├── DOMAccessibilityRoles.js │ │ │ ├── DOMNamespaces.js │ │ │ ├── DOMPropertyOperations.js │ │ │ ├── HTMLNodeType.js │ │ │ ├── ReactDOMComponent.js │ │ │ ├── ReactDOMComponentTree.js │ │ │ ├── ReactDOMContainer.js │ │ │ ├── ReactDOMEventHandle.js │ │ │ ├── ReactDOMEventHandleTypes.js │ │ │ ├── ReactDOMInput.js │ │ │ ├── ReactDOMOption.js │ │ │ ├── ReactDOMSelect.js │ │ │ ├── ReactDOMSelection.js │ │ │ ├── ReactDOMSrcObject.js │ │ │ ├── ReactDOMTextarea.js │ │ │ ├── ReactDOMUpdatePriority.js │ │ │ ├── ReactFiberConfigDOM.js │ │ │ ├── ReactInputSelection.js │ │ │ ├── ToStringValue.js │ │ │ ├── escapeSelectorAttributeValueInsideDoubleQuotes.js │ │ │ ├── estimateBandwidth.js │ │ │ ├── getActiveElement.js │ │ │ ├── getNodeForCharacterOffset.js │ │ │ ├── inputValueTracking.js │ │ │ ├── setTextContent.js │ │ │ └── validateDOMNesting.js │ │ ├── events/ │ │ │ ├── CurrentReplayingEvent.js │ │ │ ├── DOMEventNames.js │ │ │ ├── DOMEventProperties.js │ │ │ ├── DOMPluginEventSystem.js │ │ │ ├── EventListener.js │ │ │ ├── EventRegistry.js │ │ │ ├── EventSystemFlags.js │ │ │ ├── FallbackCompositionState.js │ │ │ ├── PluginModuleType.js │ │ │ ├── ReactDOMControlledComponent.js │ │ │ ├── ReactDOMEventListener.js │ │ │ ├── ReactDOMEventReplaying.js │ │ │ ├── ReactDOMUpdateBatching.js │ │ │ ├── ReactSyntheticEventType.js │ │ │ ├── SyntheticEvent.js │ │ │ ├── TopLevelEventTypes.js │ │ │ ├── checkPassiveEvents.js │ │ │ ├── forks/ │ │ │ │ └── EventListener-www.js │ │ │ ├── getEventCharCode.js │ │ │ ├── getEventTarget.js │ │ │ ├── getListener.js │ │ │ ├── getVendorPrefixedEventName.js │ │ │ ├── isEventSupported.js │ │ │ ├── isTextInputElement.js │ │ │ └── plugins/ │ │ │ ├── BeforeInputEventPlugin.js │ │ │ ├── ChangeEventPlugin.js │ │ │ ├── EnterLeaveEventPlugin.js │ │ │ ├── FormActionEventPlugin.js │ │ │ ├── ScrollEndEventPlugin.js │ │ │ ├── SelectEventPlugin.js │ │ │ └── SimpleEventPlugin.js │ │ ├── server/ │ │ │ ├── ReactDOMFlightServerHostDispatcher.js │ │ │ ├── ReactDOMLegacyServerStreamConfig.js │ │ │ ├── ReactDOMServerExternalRuntime.js │ │ │ ├── ReactFizzConfigDOM.js │ │ │ ├── ReactFizzConfigDOMLegacy.js │ │ │ ├── ReactFlightServerConfigDOM.js │ │ │ ├── escapeTextForBrowser.js │ │ │ └── fizz-instruction-set/ │ │ │ ├── ReactDOMFizzInlineClientRenderBoundary.js │ │ │ ├── ReactDOMFizzInlineCompleteBoundary.js │ │ │ ├── ReactDOMFizzInlineCompleteBoundaryUpgradeToViewTransitions.js │ │ │ ├── ReactDOMFizzInlineCompleteBoundaryWithStyles.js │ │ │ ├── ReactDOMFizzInlineCompleteSegment.js │ │ │ ├── ReactDOMFizzInlineFormReplaying.js │ │ │ ├── ReactDOMFizzInlineShellTime.js │ │ │ ├── ReactDOMFizzInstructionSetExternalRuntime.js │ │ │ ├── ReactDOMFizzInstructionSetInlineCodeStrings.js │ │ │ └── ReactDOMFizzInstructionSetShared.js │ │ └── shared/ │ │ ├── ReactControlledValuePropTypes.js │ │ ├── ReactDOMFormActions.js │ │ ├── ReactDOMInvalidARIAHook.js │ │ ├── ReactDOMNullInputValuePropHook.js │ │ ├── ReactDOMResourceValidation.js │ │ ├── ReactDOMUnknownPropertyHook.js │ │ ├── ReactFlightClientConfigDOM.js │ │ ├── crossOriginStrings.js │ │ ├── getAttributeAlias.js │ │ ├── hyphenateStyleName.js │ │ ├── isAttributeNameSafe.js │ │ ├── isCustomElement.js │ │ ├── isUnitlessNumber.js │ │ ├── possibleStandardNames.js │ │ ├── sanitizeURL.js │ │ ├── validAriaProperties.js │ │ └── warnValidStyle.js │ ├── react-is/ │ │ ├── README.md │ │ ├── index.experimental.js │ │ ├── index.js │ │ ├── index.stable.js │ │ ├── npm/ │ │ │ └── index.js │ │ ├── package.json │ │ └── src/ │ │ ├── ReactIs.js │ │ └── __tests__/ │ │ └── ReactIs-test.js │ ├── react-markup/ │ │ ├── README.md │ │ ├── index.js │ │ ├── npm/ │ │ │ ├── index.js │ │ │ └── react-markup.react-server.js │ │ ├── package.json │ │ ├── react-markup.react-server.js │ │ └── src/ │ │ ├── ReactFizzConfigMarkup.js │ │ ├── ReactMarkupClient.js │ │ ├── ReactMarkupClient.stable.js │ │ ├── ReactMarkupLegacyClientStreamConfig.js │ │ ├── ReactMarkupServer.js │ │ ├── ReactMarkupServer.stable.js │ │ └── __tests__/ │ │ ├── ReactMarkupClient-test.js │ │ └── ReactMarkupServer-test.js │ ├── react-native-renderer/ │ │ ├── fabric.js │ │ ├── index.js │ │ ├── package.json │ │ └── src/ │ │ ├── NativeMethodsMixinUtils.js │ │ ├── ReactFabric.js │ │ ├── ReactFabricComponentTree.js │ │ ├── ReactFabricEventEmitter.js │ │ ├── ReactFabricGlobalResponderHandler.js │ │ ├── ReactFabricInjection.js │ │ ├── ReactFiberConfigFabric.js │ │ ├── ReactFiberConfigFabricWithViewTransition.js │ │ ├── ReactFiberConfigNative.js │ │ ├── ReactNativeAttributePayload.js │ │ ├── ReactNativeBridgeEventPlugin.js │ │ ├── ReactNativeComponentTree.js │ │ ├── ReactNativeEventEmitter.js │ │ ├── ReactNativeEventPluginOrder.js │ │ ├── ReactNativeFiberHostComponent.js │ │ ├── ReactNativeFiberInspector.js │ │ ├── ReactNativeGetListener.js │ │ ├── ReactNativeGlobalResponderHandler.js │ │ ├── ReactNativeInjection.js │ │ ├── ReactNativeInjectionShared.js │ │ ├── ReactNativePublicCompat.js │ │ ├── ReactNativeRenderer.js │ │ ├── ReactNativeTypes.js │ │ ├── __mocks__/ │ │ │ └── react-native/ │ │ │ └── Libraries/ │ │ │ └── ReactPrivate/ │ │ │ ├── BatchedBridge.js │ │ │ ├── ExceptionsManager.js │ │ │ ├── InitializeNativeFabricUIManager.js │ │ │ ├── Platform.js │ │ │ ├── RCTEventEmitter.js │ │ │ ├── RawEventEmitter.js │ │ │ ├── ReactFiberErrorDialog.js │ │ │ ├── ReactNativePrivateInitializeCore.js │ │ │ ├── ReactNativePrivateInterface.js │ │ │ ├── ReactNativeViewConfigRegistry.js │ │ │ ├── TextInputState.js │ │ │ ├── UIManager.js │ │ │ ├── createAttributePayload.js │ │ │ ├── createPublicInstance.js │ │ │ ├── createPublicRootInstance.js │ │ │ ├── createPublicTextInstance.js │ │ │ ├── deepDiffer.js │ │ │ ├── deepFreezeAndThrowOnMutationInDev.js │ │ │ ├── diffAttributePayloads.js │ │ │ ├── flattenStyle.js │ │ │ ├── getNativeTagFromPublicInstance.js │ │ │ ├── getNodeFromPublicInstance.js │ │ │ └── legacySendAccessibilityEvent.js │ │ ├── __tests__/ │ │ │ ├── EventPluginRegistry-test.internal.js │ │ │ ├── ReactFabric-test.internal.js │ │ │ ├── ReactFabricAndNative-test.internal.js │ │ │ ├── ReactFabricFragmentRefs-test.internal.js │ │ │ ├── ReactNativeAttributePayload-test.internal.js │ │ │ ├── ReactNativeError-test.internal.js │ │ │ ├── ReactNativeEvents-test.internal.js │ │ │ ├── ReactNativeMount-test.internal.js │ │ │ ├── ResponderEventPlugin-test.internal.js │ │ │ └── createReactNativeComponentClass-test.internal.js │ │ └── legacy-events/ │ │ ├── EventBatching.js │ │ ├── EventPluginRegistry.js │ │ ├── EventPluginUtils.js │ │ ├── PluginModuleType.js │ │ ├── ReactGenericBatching.js │ │ ├── ReactSyntheticEventType.js │ │ ├── ResponderEventPlugin.js │ │ ├── ResponderSyntheticEvent.js │ │ ├── ResponderTopLevelEventTypes.js │ │ ├── ResponderTouchHistoryStore.js │ │ ├── SyntheticEvent.js │ │ ├── TopLevelEventTypes.js │ │ ├── accumulate.js │ │ ├── accumulateInto.js │ │ └── forEachAccumulated.js │ ├── react-noop-renderer/ │ │ ├── README.md │ │ ├── flight-client.js │ │ ├── flight-modules.js │ │ ├── flight-server.js │ │ ├── index.js │ │ ├── npm/ │ │ │ ├── flight-client.js │ │ │ ├── flight-modules.js │ │ │ ├── flight-server.js │ │ │ ├── index.js │ │ │ ├── persistent.js │ │ │ └── server.js │ │ ├── package.json │ │ ├── persistent.js │ │ ├── server.js │ │ └── src/ │ │ ├── ReactFiberConfigNoop.js │ │ ├── ReactFiberConfigNoopHydration.js │ │ ├── ReactFiberConfigNoopNoMutation.js │ │ ├── ReactFiberConfigNoopNoPersistence.js │ │ ├── ReactFiberConfigNoopResources.js │ │ ├── ReactFiberConfigNoopScopes.js │ │ ├── ReactFiberConfigNoopSingletons.js │ │ ├── ReactFiberConfigNoopTestSelectors.js │ │ ├── ReactNoop.js │ │ ├── ReactNoopFlightClient.js │ │ ├── ReactNoopFlightServer.js │ │ ├── ReactNoopPersistent.js │ │ ├── ReactNoopServer.js │ │ └── createReactNoop.js │ ├── react-reconciler/ │ │ ├── README.md │ │ ├── constants.js │ │ ├── index.js │ │ ├── npm/ │ │ │ ├── constants.js │ │ │ ├── index.js │ │ │ └── reflection.js │ │ ├── package.json │ │ ├── reflection.js │ │ └── src/ │ │ ├── ReactCapturedValue.js │ │ ├── ReactChildFiber.js │ │ ├── ReactCurrentFiber.js │ │ ├── ReactEventPriorities.js │ │ ├── ReactFiber.js │ │ ├── ReactFiberAct.js │ │ ├── ReactFiberActivityComponent.js │ │ ├── ReactFiberApplyGesture.js │ │ ├── ReactFiberAsyncAction.js │ │ ├── ReactFiberAsyncDispatcher.js │ │ ├── ReactFiberBeginWork.js │ │ ├── ReactFiberCacheComponent.js │ │ ├── ReactFiberCallUserSpace.js │ │ ├── ReactFiberClassComponent.js │ │ ├── ReactFiberClassUpdateQueue.js │ │ ├── ReactFiberCommitEffects.js │ │ ├── ReactFiberCommitHostEffects.js │ │ ├── ReactFiberCommitViewTransitions.js │ │ ├── ReactFiberCommitWork.js │ │ ├── ReactFiberCompleteWork.js │ │ ├── ReactFiberComponentStack.js │ │ ├── ReactFiberConcurrentUpdates.js │ │ ├── ReactFiberConfig.js │ │ ├── ReactFiberConfigWithNoHydration.js │ │ ├── ReactFiberConfigWithNoMicrotasks.js │ │ ├── ReactFiberConfigWithNoMutation.js │ │ ├── ReactFiberConfigWithNoPersistence.js │ │ ├── ReactFiberConfigWithNoResources.js │ │ ├── ReactFiberConfigWithNoScopes.js │ │ ├── ReactFiberConfigWithNoSingletons.js │ │ ├── ReactFiberConfigWithNoTestSelectors.js │ │ ├── ReactFiberConfigWithNoViewTransition.js │ │ ├── ReactFiberDevToolsHook.js │ │ ├── ReactFiberDuplicateViewTransitions.js │ │ ├── ReactFiberErrorLogger.js │ │ ├── ReactFiberFlags.js │ │ ├── ReactFiberGestureScheduler.js │ │ ├── ReactFiberHiddenContext.js │ │ ├── ReactFiberHooks.js │ │ ├── ReactFiberHostContext.js │ │ ├── ReactFiberHotReloading.js │ │ ├── ReactFiberHydrationContext.js │ │ ├── ReactFiberHydrationDiffs.js │ │ ├── ReactFiberLane.js │ │ ├── ReactFiberLegacyContext.js │ │ ├── ReactFiberMutationTracking.js │ │ ├── ReactFiberNewContext.js │ │ ├── ReactFiberOffscreenComponent.js │ │ ├── ReactFiberPerformanceTrack.js │ │ ├── ReactFiberReconciler.js │ │ ├── ReactFiberRoot.js │ │ ├── ReactFiberRootScheduler.js │ │ ├── ReactFiberScope.js │ │ ├── ReactFiberShellHydration.js │ │ ├── ReactFiberStack.js │ │ ├── ReactFiberSuspenseComponent.js │ │ ├── ReactFiberSuspenseContext.js │ │ ├── ReactFiberThenable.js │ │ ├── ReactFiberThrow.js │ │ ├── ReactFiberTracingMarkerComponent.js │ │ ├── ReactFiberTransition.js │ │ ├── ReactFiberTransitionTypes.js │ │ ├── ReactFiberTreeContext.js │ │ ├── ReactFiberTreeReflection.js │ │ ├── ReactFiberUnwindWork.js │ │ ├── ReactFiberViewTransitionComponent.js │ │ ├── ReactFiberWorkLoop.js │ │ ├── ReactHookEffectTags.js │ │ ├── ReactInternalTypes.js │ │ ├── ReactPortal.js │ │ ├── ReactPostPaintCallback.js │ │ ├── ReactProfilerTimer.js │ │ ├── ReactReconcilerConstants.js │ │ ├── ReactRootTags.js │ │ ├── ReactStrictModeWarnings.js │ │ ├── ReactTestSelectors.js │ │ ├── ReactTypeOfMode.js │ │ ├── ReactWorkTags.js │ │ ├── Scheduler.js │ │ ├── __mocks__/ │ │ │ └── scheduler/ │ │ │ └── tracing.js │ │ ├── __tests__/ │ │ │ ├── Activity-test.js │ │ │ ├── ActivityErrorHandling-test.js │ │ │ ├── ActivityLegacySuspense-test.js │ │ │ ├── ActivityReactServer-test.js │ │ │ ├── ActivityStrictMode-test.js │ │ │ ├── ActivitySuspense-test.js │ │ │ ├── ErrorBoundaryReconciliation-test.internal.js │ │ │ ├── ReactActWarnings-test.js │ │ │ ├── ReactAsyncActions-test.js │ │ │ ├── ReactBatching-test.internal.js │ │ │ ├── ReactCPUSuspense-test.js │ │ │ ├── ReactCache-test.js │ │ │ ├── ReactClassComponentPropResolution-test.js │ │ │ ├── ReactClassSetStateCallback-test.js │ │ │ ├── ReactConcurrentErrorRecovery-test.js │ │ │ ├── ReactConfigurableErrorLogging-test.js │ │ │ ├── ReactContextPropagation-test.js │ │ │ ├── ReactDefaultTransitionIndicator-test.js │ │ │ ├── ReactDeferredValue-test.js │ │ │ ├── ReactEffectOrdering-test.js │ │ │ ├── ReactErrorStacks-test.js │ │ │ ├── ReactExpiration-test.js │ │ │ ├── ReactFiberHostContext-test.internal.js │ │ │ ├── ReactFiberRefs-test.js │ │ │ ├── ReactFlushSync-test.js │ │ │ ├── ReactFlushSyncNoAggregateError-test.js │ │ │ ├── ReactFragment-test.js │ │ │ ├── ReactHooks-test.internal.js │ │ │ ├── ReactHooksWithNoopRenderer-test.js │ │ │ ├── ReactIncremental-test.js │ │ │ ├── ReactIncrementalErrorHandling-test.internal.js │ │ │ ├── ReactIncrementalErrorLogging-test.js │ │ │ ├── ReactIncrementalErrorReplay-test.js │ │ │ ├── ReactIncrementalReflection-test.js │ │ │ ├── ReactIncrementalScheduling-test.js │ │ │ ├── ReactIncrementalSideEffects-test.js │ │ │ ├── ReactIncrementalUpdates-test.js │ │ │ ├── ReactIncrementalUpdatesMinimalism-test.js │ │ │ ├── ReactInterleavedUpdates-test.js │ │ │ ├── ReactIsomorphicAct-test.js │ │ │ ├── ReactLazy-test.internal.js │ │ │ ├── ReactMemo-test.js │ │ │ ├── ReactNewContext-test.js │ │ │ ├── ReactNoopRendererAct-test.js │ │ │ ├── ReactOwnerStacks-test.js │ │ │ ├── ReactPerformanceTrack-test.js │ │ │ ├── ReactPersistent-test.js │ │ │ ├── ReactPersistentUpdatesMinimalism-test.js │ │ │ ├── ReactSchedulerIntegration-test.js │ │ │ ├── ReactScope-test.internal.js │ │ │ ├── ReactSiblingPrerendering-test.js │ │ │ ├── ReactSubtreeFlagsWarning-test.js │ │ │ ├── ReactSuspense-test.internal.js │ │ │ ├── ReactSuspenseCallback-test.js │ │ │ ├── ReactSuspenseEffectsSemantics-test.js │ │ │ ├── ReactSuspenseEffectsSemanticsDOM-test.js │ │ │ ├── ReactSuspenseFallback-test.js │ │ │ ├── ReactSuspenseFuzz-test.internal.js │ │ │ ├── ReactSuspenseList-test.js │ │ │ ├── ReactSuspensePlaceholder-test.internal.js │ │ │ ├── ReactSuspenseWithNoopRenderer-test.js │ │ │ ├── ReactSuspenseyCommitPhase-test.js │ │ │ ├── ReactTopLevelFragment-test.js │ │ │ ├── ReactTopLevelText-test.js │ │ │ ├── ReactTransition-test.js │ │ │ ├── ReactTransitionTracing-test.js │ │ │ ├── ReactUpdatePriority-test.js │ │ │ ├── ReactUpdaters-test.internal.js │ │ │ ├── ReactUse-test.js │ │ │ ├── StrictEffectsMode-test.js │ │ │ ├── StrictEffectsModeDefaults-test.internal.js │ │ │ ├── ViewTransitionReactServer-test.js │ │ │ ├── __snapshots__/ │ │ │ │ └── ReactHooks-test.internal.js.snap │ │ │ ├── useEffectEvent-test.js │ │ │ ├── useMemoCache-test.js │ │ │ ├── useRef-test.internal.js │ │ │ └── useSyncExternalStore-test.js │ │ ├── clz32.js │ │ ├── forks/ │ │ │ ├── ReactFiberConfig.art.js │ │ │ ├── ReactFiberConfig.custom.js │ │ │ ├── ReactFiberConfig.dom.js │ │ │ ├── ReactFiberConfig.fabric.js │ │ │ ├── ReactFiberConfig.markup.js │ │ │ ├── ReactFiberConfig.native.js │ │ │ ├── ReactFiberConfig.noop.js │ │ │ └── ReactFiberConfig.test.js │ │ └── getComponentNameFromFiber.js │ ├── react-refresh/ │ │ ├── README.md │ │ ├── babel.js │ │ ├── npm/ │ │ │ ├── babel.js │ │ │ └── runtime.js │ │ ├── package.json │ │ ├── runtime.js │ │ └── src/ │ │ ├── ReactFreshBabelPlugin.js │ │ ├── ReactFreshRuntime.js │ │ └── __tests__/ │ │ ├── ReactFresh-test.js │ │ ├── ReactFreshBabelPlugin-test.js │ │ ├── ReactFreshIntegration-test.js │ │ ├── ReactFreshMultipleRenderer-test.internal.js │ │ └── __snapshots__/ │ │ └── ReactFreshBabelPlugin-test.js.snap │ ├── react-server/ │ │ ├── README.md │ │ ├── flight.js │ │ ├── index.js │ │ ├── npm/ │ │ │ ├── flight.js │ │ │ └── index.js │ │ ├── package.json │ │ └── src/ │ │ ├── ReactFizzAsyncDispatcher.js │ │ ├── ReactFizzCallUserSpace.js │ │ ├── ReactFizzClassComponent.js │ │ ├── ReactFizzComponentStack.js │ │ ├── ReactFizzConfig.js │ │ ├── ReactFizzCurrentTask.js │ │ ├── ReactFizzHooks.js │ │ ├── ReactFizzLegacyContext.js │ │ ├── ReactFizzNewContext.js │ │ ├── ReactFizzServer.js │ │ ├── ReactFizzThenable.js │ │ ├── ReactFizzTreeContext.js │ │ ├── ReactFizzViewTransitionComponent.js │ │ ├── ReactFlightActionServer.js │ │ ├── ReactFlightAsyncSequence.js │ │ ├── ReactFlightCallUserSpace.js │ │ ├── ReactFlightHooks.js │ │ ├── ReactFlightReplyServer.js │ │ ├── ReactFlightServer.js │ │ ├── ReactFlightServerConfig.js │ │ ├── ReactFlightServerConfigBundlerCustom.js │ │ ├── ReactFlightServerConfigDebugNode.js │ │ ├── ReactFlightServerConfigDebugNoop.js │ │ ├── ReactFlightServerTemporaryReferences.js │ │ ├── ReactFlightStackConfigV8.js │ │ ├── ReactFlightThenable.js │ │ ├── ReactServerConsoleConfigBrowser.js │ │ ├── ReactServerConsoleConfigPlain.js │ │ ├── ReactServerConsoleConfigServer.js │ │ ├── ReactServerStreamConfig.js │ │ ├── ReactServerStreamConfigBrowser.js │ │ ├── ReactServerStreamConfigBun.js │ │ ├── ReactServerStreamConfigEdge.js │ │ ├── ReactServerStreamConfigFB.js │ │ ├── ReactServerStreamConfigNode.js │ │ ├── ReactSharedInternalsServer.js │ │ ├── __tests__/ │ │ │ ├── ReactFlightAsyncDebugInfo-test.js │ │ │ ├── ReactFlightServer-test.js │ │ │ ├── ReactServer-test.js │ │ │ └── test-file.txt │ │ ├── createFastHashJS.js │ │ ├── flight/ │ │ │ ├── ReactFlightAsyncDispatcher.js │ │ │ └── ReactFlightCurrentOwner.js │ │ └── forks/ │ │ ├── ReactFizzConfig.custom.js │ │ ├── ReactFizzConfig.dom-edge.js │ │ ├── ReactFizzConfig.dom-legacy.js │ │ ├── ReactFizzConfig.dom-node.js │ │ ├── ReactFizzConfig.dom.js │ │ ├── ReactFizzConfig.markup.js │ │ ├── ReactFizzConfig.noop.js │ │ ├── ReactFlightServerConfig.custom.js │ │ ├── ReactFlightServerConfig.dom-browser-esm.js │ │ ├── ReactFlightServerConfig.dom-browser-parcel.js │ │ ├── ReactFlightServerConfig.dom-browser-turbopack.js │ │ ├── ReactFlightServerConfig.dom-browser.js │ │ ├── ReactFlightServerConfig.dom-bun.js │ │ ├── ReactFlightServerConfig.dom-edge-parcel.js │ │ ├── ReactFlightServerConfig.dom-edge-turbopack.js │ │ ├── ReactFlightServerConfig.dom-edge.js │ │ ├── ReactFlightServerConfig.dom-legacy.js │ │ ├── ReactFlightServerConfig.dom-node-esm.js │ │ ├── ReactFlightServerConfig.dom-node-parcel.js │ │ ├── ReactFlightServerConfig.dom-node-turbopack.js │ │ ├── ReactFlightServerConfig.dom-node-unbundled.js │ │ ├── ReactFlightServerConfig.dom-node.js │ │ ├── ReactFlightServerConfig.markup.js │ │ ├── ReactFlightServerConfig.noop.js │ │ ├── ReactServerStreamConfig.custom.js │ │ ├── ReactServerStreamConfig.dom-browser.js │ │ ├── ReactServerStreamConfig.dom-bun.js │ │ ├── ReactServerStreamConfig.dom-edge.js │ │ ├── ReactServerStreamConfig.dom-fb.js │ │ ├── ReactServerStreamConfig.dom-legacy.js │ │ ├── ReactServerStreamConfig.dom-node.js │ │ ├── ReactServerStreamConfig.markup.js │ │ └── ReactServerStreamConfig.noop.js │ ├── react-server-dom-esm/ │ │ ├── README.md │ │ ├── client.browser.js │ │ ├── client.js │ │ ├── client.node.js │ │ ├── esm/ │ │ │ ├── package.json │ │ │ └── react-server-dom-esm-node-loader.production.js │ │ ├── index.js │ │ ├── npm/ │ │ │ ├── client.browser.js │ │ │ ├── client.js │ │ │ ├── client.node.js │ │ │ ├── esm/ │ │ │ │ └── package.json │ │ │ ├── index.js │ │ │ ├── server.js │ │ │ ├── server.node.js │ │ │ ├── static.js │ │ │ └── static.node.js │ │ ├── package.json │ │ ├── server.js │ │ ├── server.node.js │ │ ├── src/ │ │ │ ├── ReactFlightESMNodeLoader.js │ │ │ ├── ReactFlightESMReferences.js │ │ │ ├── client/ │ │ │ │ ├── ReactFlightClientConfigBundlerESM.js │ │ │ │ ├── ReactFlightClientConfigTargetESMBrowser.js │ │ │ │ ├── ReactFlightClientConfigTargetESMServer.js │ │ │ │ ├── ReactFlightDOMClientBrowser.js │ │ │ │ └── ReactFlightDOMClientNode.js │ │ │ └── server/ │ │ │ ├── ReactFlightDOMServerNode.js │ │ │ ├── ReactFlightServerConfigESMBundler.js │ │ │ └── react-flight-dom-server.node.js │ │ ├── static.js │ │ └── static.node.js │ ├── react-server-dom-fb/ │ │ ├── package.json │ │ └── src/ │ │ ├── ReactDOMServerFB.js │ │ └── __tests__/ │ │ └── ReactDOMServerFB-test.internal.js │ ├── react-server-dom-parcel/ │ │ ├── README.md │ │ ├── client.browser.js │ │ ├── client.edge.js │ │ ├── client.js │ │ ├── client.node.js │ │ ├── index.js │ │ ├── npm/ │ │ │ ├── client.browser.js │ │ │ ├── client.edge.js │ │ │ ├── client.js │ │ │ ├── client.node.js │ │ │ ├── index.js │ │ │ ├── server.browser.js │ │ │ ├── server.edge.js │ │ │ ├── server.js │ │ │ ├── server.node.js │ │ │ ├── static.browser.js │ │ │ ├── static.edge.js │ │ │ ├── static.js │ │ │ └── static.node.js │ │ ├── package.json │ │ ├── server.browser.js │ │ ├── server.edge.js │ │ ├── server.js │ │ ├── server.node.js │ │ ├── src/ │ │ │ ├── ReactFlightParcelReferences.js │ │ │ ├── client/ │ │ │ │ ├── ReactFlightClientConfigBundlerParcel.js │ │ │ │ ├── ReactFlightClientConfigTargetParcelBrowser.js │ │ │ │ ├── ReactFlightClientConfigTargetParcelServer.js │ │ │ │ ├── ReactFlightDOMClientBrowser.js │ │ │ │ ├── ReactFlightDOMClientEdge.js │ │ │ │ ├── ReactFlightDOMClientNode.js │ │ │ │ ├── react-flight-dom-client.browser.js │ │ │ │ ├── react-flight-dom-client.edge.js │ │ │ │ └── react-flight-dom-client.node.js │ │ │ ├── server/ │ │ │ │ ├── ReactFlightDOMServerBrowser.js │ │ │ │ ├── ReactFlightDOMServerEdge.js │ │ │ │ ├── ReactFlightDOMServerNode.js │ │ │ │ ├── ReactFlightServerConfigParcelBundler.js │ │ │ │ ├── react-flight-dom-server.browser.js │ │ │ │ ├── react-flight-dom-server.edge.js │ │ │ │ └── react-flight-dom-server.node.js │ │ │ └── shared/ │ │ │ └── ReactFlightImportMetadata.js │ │ ├── static.browser.js │ │ ├── static.edge.js │ │ ├── static.js │ │ └── static.node.js │ ├── react-server-dom-turbopack/ │ │ ├── README.md │ │ ├── client.browser.js │ │ ├── client.edge.js │ │ ├── client.js │ │ ├── client.node.js │ │ ├── index.js │ │ ├── npm/ │ │ │ ├── client.browser.js │ │ │ ├── client.edge.js │ │ │ ├── client.js │ │ │ ├── client.node.js │ │ │ ├── index.js │ │ │ ├── server.browser.js │ │ │ ├── server.edge.js │ │ │ ├── server.js │ │ │ ├── server.node.js │ │ │ ├── static.browser.js │ │ │ ├── static.edge.js │ │ │ ├── static.js │ │ │ └── static.node.js │ │ ├── package.json │ │ ├── server.browser.js │ │ ├── server.edge.js │ │ ├── server.js │ │ ├── server.node.js │ │ ├── src/ │ │ │ ├── ReactFlightTurbopackReferences.js │ │ │ ├── __tests__/ │ │ │ │ ├── ReactFlightTurbopackDOM-test.js │ │ │ │ ├── ReactFlightTurbopackDOMBrowser-test.js │ │ │ │ ├── ReactFlightTurbopackDOMEdge-test.js │ │ │ │ ├── ReactFlightTurbopackDOMNode-test.js │ │ │ │ ├── ReactFlightTurbopackDOMReply-test.js │ │ │ │ ├── ReactFlightTurbopackDOMReplyEdge-test.js │ │ │ │ └── utils/ │ │ │ │ └── TurbopackMock.js │ │ │ ├── client/ │ │ │ │ ├── ReactFlightClientConfigBundlerTurbopack.js │ │ │ │ ├── ReactFlightClientConfigBundlerTurbopackBrowser.js │ │ │ │ ├── ReactFlightClientConfigBundlerTurbopackServer.js │ │ │ │ ├── ReactFlightClientConfigTargetTurbopackBrowser.js │ │ │ │ ├── ReactFlightClientConfigTargetTurbopackServer.js │ │ │ │ ├── ReactFlightDOMClientBrowser.js │ │ │ │ ├── ReactFlightDOMClientEdge.js │ │ │ │ ├── ReactFlightDOMClientNode.js │ │ │ │ ├── react-flight-dom-client.browser.js │ │ │ │ ├── react-flight-dom-client.edge.js │ │ │ │ └── react-flight-dom-client.node.js │ │ │ ├── server/ │ │ │ │ ├── ReactFlightDOMServerBrowser.js │ │ │ │ ├── ReactFlightDOMServerEdge.js │ │ │ │ ├── ReactFlightDOMServerNode.js │ │ │ │ ├── ReactFlightServerConfigTurbopackBundler.js │ │ │ │ ├── react-flight-dom-server.browser.js │ │ │ │ ├── react-flight-dom-server.edge.js │ │ │ │ └── react-flight-dom-server.node.js │ │ │ └── shared/ │ │ │ └── ReactFlightImportMetadata.js │ │ ├── static.browser.js │ │ ├── static.edge.js │ │ ├── static.js │ │ └── static.node.js │ ├── react-server-dom-unbundled/ │ │ ├── README.md │ │ ├── client.js │ │ ├── esm/ │ │ │ ├── package.json │ │ │ └── react-server-dom-unbundled-node-loader.production.js │ │ ├── index.js │ │ ├── node-register.js │ │ ├── npm/ │ │ │ ├── client.js │ │ │ ├── esm/ │ │ │ │ └── package.json │ │ │ ├── index.js │ │ │ ├── node-register.js │ │ │ ├── server.js │ │ │ ├── server.node.js │ │ │ ├── static.js │ │ │ └── static.node.js │ │ ├── package.json │ │ ├── server.js │ │ ├── server.node.js │ │ ├── src/ │ │ │ ├── ReactFlightUnbundledNodeLoader.js │ │ │ ├── ReactFlightUnbundledNodeRegister.js │ │ │ ├── ReactFlightUnbundledReferences.js │ │ │ ├── client/ │ │ │ │ ├── ReactFlightClientConfigBundlerNode.js │ │ │ │ ├── ReactFlightClientConfigTargetNodeServer.js │ │ │ │ ├── ReactFlightDOMClientEdge.js │ │ │ │ ├── ReactFlightDOMClientNode.js │ │ │ │ └── react-flight-dom-client.node.js │ │ │ ├── server/ │ │ │ │ ├── ReactFlightDOMServerNode.js │ │ │ │ ├── ReactFlightServerConfigUnbundledBundler.js │ │ │ │ └── react-flight-dom-server.node.js │ │ │ └── shared/ │ │ │ └── ReactFlightImportMetadata.js │ │ ├── static.js │ │ └── static.node.js │ ├── react-server-dom-webpack/ │ │ ├── README.md │ │ ├── client.browser.js │ │ ├── client.edge.js │ │ ├── client.js │ │ ├── client.node.js │ │ ├── esm/ │ │ │ ├── package.json │ │ │ └── react-server-dom-webpack-node-loader.production.js │ │ ├── index.js │ │ ├── node-register.js │ │ ├── npm/ │ │ │ ├── client.browser.js │ │ │ ├── client.edge.js │ │ │ ├── client.js │ │ │ ├── client.node.js │ │ │ ├── client.node.unbundled.js │ │ │ ├── esm/ │ │ │ │ └── package.json │ │ │ ├── index.js │ │ │ ├── node-register.js │ │ │ ├── plugin.js │ │ │ ├── server.browser.js │ │ │ ├── server.edge.js │ │ │ ├── server.js │ │ │ ├── server.node.js │ │ │ ├── server.node.unbundled.js │ │ │ ├── static.browser.js │ │ │ ├── static.edge.js │ │ │ ├── static.js │ │ │ ├── static.node.js │ │ │ └── static.node.unbundled.js │ │ ├── package.json │ │ ├── plugin.js │ │ ├── server.browser.js │ │ ├── server.edge.js │ │ ├── server.js │ │ ├── server.node.js │ │ ├── src/ │ │ │ ├── ReactFlightWebpackNodeLoader.js │ │ │ ├── ReactFlightWebpackNodeRegister.js │ │ │ ├── ReactFlightWebpackPlugin.js │ │ │ ├── ReactFlightWebpackReferences.js │ │ │ ├── __tests__/ │ │ │ │ ├── ReactFlightDOM-test.js │ │ │ │ ├── ReactFlightDOMBrowser-test.js │ │ │ │ ├── ReactFlightDOMEdge-test.js │ │ │ │ ├── ReactFlightDOMForm-test.js │ │ │ │ ├── ReactFlightDOMNode-test.js │ │ │ │ ├── ReactFlightDOMReply-test.js │ │ │ │ ├── ReactFlightDOMReplyEdge-test.js │ │ │ │ └── utils/ │ │ │ │ └── WebpackMock.js │ │ │ ├── client/ │ │ │ │ ├── ReactFlightClientConfigBundlerWebpack.js │ │ │ │ ├── ReactFlightClientConfigBundlerWebpackBrowser.js │ │ │ │ ├── ReactFlightClientConfigBundlerWebpackServer.js │ │ │ │ ├── ReactFlightClientConfigTargetWebpackBrowser.js │ │ │ │ ├── ReactFlightClientConfigTargetWebpackServer.js │ │ │ │ ├── ReactFlightDOMClientBrowser.js │ │ │ │ ├── ReactFlightDOMClientEdge.js │ │ │ │ ├── ReactFlightDOMClientNode.js │ │ │ │ ├── react-flight-dom-client.browser.js │ │ │ │ ├── react-flight-dom-client.edge.js │ │ │ │ └── react-flight-dom-client.node.js │ │ │ ├── server/ │ │ │ │ ├── ReactFlightDOMServerBrowser.js │ │ │ │ ├── ReactFlightDOMServerEdge.js │ │ │ │ ├── ReactFlightDOMServerNode.js │ │ │ │ ├── ReactFlightServerConfigWebpackBundler.js │ │ │ │ ├── react-flight-dom-server.browser.js │ │ │ │ ├── react-flight-dom-server.edge.js │ │ │ │ └── react-flight-dom-server.node.js │ │ │ └── shared/ │ │ │ └── ReactFlightImportMetadata.js │ │ ├── static.browser.js │ │ ├── static.edge.js │ │ ├── static.js │ │ └── static.node.js │ ├── react-suspense-test-utils/ │ │ ├── README.md │ │ ├── index.js │ │ ├── npm/ │ │ │ └── index.js │ │ ├── package.json │ │ └── src/ │ │ └── ReactSuspenseTestUtils.js │ ├── react-test-renderer/ │ │ ├── README.md │ │ ├── __tests__/ │ │ │ └── shallow-test.js │ │ ├── index.js │ │ ├── npm/ │ │ │ ├── index.js │ │ │ └── shallow.js │ │ ├── package.json │ │ ├── shallow.js │ │ └── src/ │ │ ├── ReactFiberConfigTestHost.js │ │ ├── ReactTestRenderer.js │ │ └── __tests__/ │ │ ├── ReactTestRenderer-test.internal.js │ │ ├── ReactTestRenderer-test.js │ │ ├── ReactTestRendererAct-test.js │ │ ├── ReactTestRendererAsync-test.js │ │ └── ReactTestRendererTraversal-test.js │ ├── scheduler/ │ │ ├── README.md │ │ ├── index.js │ │ ├── index.native.js │ │ ├── npm/ │ │ │ ├── index.js │ │ │ ├── index.native.js │ │ │ ├── umd/ │ │ │ │ └── scheduler.development.js │ │ │ ├── unstable_mock.js │ │ │ └── unstable_post_task.js │ │ ├── package.json │ │ ├── src/ │ │ │ ├── SchedulerFeatureFlags.js │ │ │ ├── SchedulerMinHeap.js │ │ │ ├── SchedulerPriorities.js │ │ │ ├── SchedulerProfiling.js │ │ │ ├── __tests__/ │ │ │ │ ├── Scheduler-test.js │ │ │ │ ├── SchedulerMock-test.js │ │ │ │ ├── SchedulerPostTask-test.js │ │ │ │ ├── SchedulerProfiling-test.js │ │ │ │ ├── SchedulerSetImmediate-test.js │ │ │ │ └── SchedulerSetTimeout-test.js │ │ │ └── forks/ │ │ │ ├── Scheduler.js │ │ │ ├── SchedulerFeatureFlags.native-fb.js │ │ │ ├── SchedulerFeatureFlags.www-dynamic.js │ │ │ ├── SchedulerFeatureFlags.www.js │ │ │ ├── SchedulerMock.js │ │ │ ├── SchedulerNative.js │ │ │ └── SchedulerPostTask.js │ │ ├── unstable_mock.js │ │ └── unstable_post_task.js │ ├── shared/ │ │ ├── CheckStringCoercion.js │ │ ├── ConsolePatchingDev.js │ │ ├── DefaultPrepareStackTrace.js │ │ ├── DefaultPrepareStackTraceV8.js │ │ ├── ExecutionEnvironment.js │ │ ├── ReactComponentInfoStack.js │ │ ├── ReactComponentStackFrame.js │ │ ├── ReactDOMFragmentRefShared.js │ │ ├── ReactDOMSharedInternals.js │ │ ├── ReactElementType.js │ │ ├── ReactFeatureFlags.js │ │ ├── ReactFlightPropertyAccess.js │ │ ├── ReactIODescription.js │ │ ├── ReactInstanceMap.js │ │ ├── ReactOwnerStackFrames.js │ │ ├── ReactOwnerStackReset.js │ │ ├── ReactPerformanceTrackProperties.js │ │ ├── ReactSerializationErrors.js │ │ ├── ReactSharedInternals.js │ │ ├── ReactSymbols.js │ │ ├── ReactTypes.js │ │ ├── ReactVersion.js │ │ ├── __tests__/ │ │ │ ├── ReactDOMFrameScheduling-test.js │ │ │ ├── ReactError-test.internal.js │ │ │ ├── ReactErrorProd-test.internal.js │ │ │ ├── ReactSymbols-test.internal.js │ │ │ └── normalizeConsoleFormat-test.internal.js │ │ ├── assign.js │ │ ├── binaryToComparableString.js │ │ ├── enqueueTask.js │ │ ├── forks/ │ │ │ ├── DefaultPrepareStackTrace.dom-edge.js │ │ │ ├── DefaultPrepareStackTrace.dom-node.js │ │ │ ├── DefaultPrepareStackTrace.markup.js │ │ │ ├── ReactFeatureFlags.native-fb-dynamic.js │ │ │ ├── ReactFeatureFlags.native-fb.js │ │ │ ├── ReactFeatureFlags.native-oss.js │ │ │ ├── ReactFeatureFlags.readonly.js │ │ │ ├── ReactFeatureFlags.test-renderer.js │ │ │ ├── ReactFeatureFlags.test-renderer.native-fb.js │ │ │ ├── ReactFeatureFlags.test-renderer.www.js │ │ │ ├── ReactFeatureFlags.www-dynamic.js │ │ │ └── ReactFeatureFlags.www.js │ │ ├── formatProdErrorMessage.js │ │ ├── getComponentNameFromType.js │ │ ├── getPrototypeOf.js │ │ ├── hasOwnProperty.js │ │ ├── isArray.js │ │ ├── noop.js │ │ ├── normalizeConsoleFormat.js │ │ ├── objectIs.js │ │ ├── package.json │ │ ├── reportGlobalError.js │ │ └── shallowEqual.js │ ├── use-subscription/ │ │ ├── README.md │ │ ├── index.js │ │ ├── npm/ │ │ │ └── index.js │ │ ├── package.json │ │ └── src/ │ │ ├── __tests__/ │ │ │ └── useSubscription-test.js │ │ └── useSubscription.js │ └── use-sync-external-store/ │ ├── README.md │ ├── index.js │ ├── npm/ │ │ ├── index.js │ │ ├── shim/ │ │ │ ├── index.js │ │ │ ├── index.native.js │ │ │ └── with-selector.js │ │ └── with-selector.js │ ├── package.json │ ├── shim/ │ │ ├── index.js │ │ ├── index.native.js │ │ └── with-selector.js │ ├── src/ │ │ ├── __tests__/ │ │ │ ├── useSyncExternalStoreNative-test.js │ │ │ ├── useSyncExternalStoreShared-test.js │ │ │ └── useSyncExternalStoreShimServer-test.js │ │ ├── forks/ │ │ │ ├── isServerEnvironment.native.js │ │ │ ├── useSyncExternalStore.forward-to-built-in.js │ │ │ └── useSyncExternalStore.forward-to-shim.js │ │ ├── isServerEnvironment.js │ │ ├── useSyncExternalStore.js │ │ ├── useSyncExternalStoreShim.js │ │ ├── useSyncExternalStoreShimClient.js │ │ ├── useSyncExternalStoreShimServer.js │ │ └── useSyncExternalStoreWithSelector.js │ └── with-selector.js ├── react.code-workspace └── scripts/ ├── babel/ │ ├── __tests__/ │ │ ├── transform-lazy-jsx-import-test.js │ │ ├── transform-prevent-infinite-loops-test.js │ │ └── transform-test-gate-pragma-test.js │ ├── getComments.js │ ├── transform-lazy-jsx-import.js │ ├── transform-object-assign.js │ ├── transform-prevent-infinite-loops.js │ ├── transform-react-version-pragma.js │ └── transform-test-gate-pragma.js ├── bench/ │ ├── .gitignore │ ├── README.md │ ├── benchmark.js │ ├── benchmarks/ │ │ ├── hacker-news/ │ │ │ ├── benchmark.js │ │ │ ├── build.js │ │ │ ├── generate.js │ │ │ ├── index.html │ │ │ ├── style.css │ │ │ └── top-stories.js │ │ ├── pe-class-components/ │ │ │ ├── benchmark.js │ │ │ ├── build.js │ │ │ └── index.html │ │ ├── pe-functional-components/ │ │ │ ├── benchmark.js │ │ │ ├── build.js │ │ │ └── index.html │ │ └── pe-no-components/ │ │ ├── benchmark.js │ │ ├── build.js │ │ └── index.html │ ├── build.js │ ├── package.json │ ├── runner.js │ ├── server.js │ └── stats.js ├── ci/ │ ├── check_license.sh │ ├── download_devtools_regression_build.js │ ├── pack_and_store_devtools_artifacts.sh │ ├── run_devtools_e2e_tests.js │ └── test_print_warnings.sh ├── devtools/ │ ├── .gitignore │ ├── README.md │ ├── build-and-test.js │ ├── configuration.js │ ├── package.json │ ├── prepare-release.js │ ├── publish-release.js │ └── utils.js ├── error-codes/ │ ├── README.md │ ├── Types.js │ ├── __tests__/ │ │ ├── __snapshots__/ │ │ │ └── transform-error-messages.js.snap │ │ ├── invertObject-test.js │ │ └── transform-error-messages.js │ ├── codes.json │ ├── extract-errors.js │ ├── invertObject.js │ └── transform-error-messages.js ├── eslint/ │ └── index.js ├── eslint-rules/ │ ├── README.md │ ├── __tests__/ │ │ ├── no-primitive-constructors-test.internal.js │ │ ├── no-production-logging-test.internal.js │ │ ├── prod-error-codes-test.internal.js │ │ ├── safe-string-coercion-test.internal.js │ │ └── warning-args-test.internal.js │ ├── index.js │ ├── no-primitive-constructors.js │ ├── no-production-logging.js │ ├── package.json │ ├── prod-error-codes.js │ ├── safe-string-coercion.js │ └── warning-args.js ├── flags/ │ └── flags.js ├── flow/ │ ├── config/ │ │ └── flowconfig │ ├── createFlowConfigs.js │ ├── environment.js │ ├── react-devtools.js │ ├── react-native-host-hooks.js │ ├── runFlow.js │ └── xplat.js ├── git/ │ └── pre-commit ├── jest/ │ ├── ReactDOMServerIntegrationEnvironment.js │ ├── ReactJSDOMEnvironment.js │ ├── TestFlags.js │ ├── config.base.js │ ├── config.build-devtools.js │ ├── config.build.js │ ├── config.source-persistent.js │ ├── config.source-www.js │ ├── config.source-xplat.js │ ├── config.source.js │ ├── devtools/ │ │ ├── config.build-devtools-regression.js │ │ ├── setupEnv.js │ │ └── setupTests.build-devtools-regression.js │ ├── dont-run-jest-directly.js │ ├── jest-cli.js │ ├── jest.js │ ├── matchers/ │ │ ├── reactTestMatchers.js │ │ └── toThrow.js │ ├── patchMessageChannel.js │ ├── patchSetImmediate.js │ ├── preprocessor.js │ ├── setupEnvironment.js │ ├── setupGlobal.js │ ├── setupHostConfigs.js │ ├── setupTests.build.js │ ├── setupTests.js │ ├── setupTests.persistent.js │ ├── setupTests.www.js │ ├── setupTests.xplat.js │ ├── sizeBalancedSequencer.js │ ├── spec-equivalence-reporter/ │ │ ├── equivalenceReporter.js │ │ └── setupTests.js │ └── typescript/ │ ├── jest.d.ts │ └── preprocessor.js ├── prettier/ │ └── index.js ├── print-warnings/ │ ├── README.md │ └── print-warnings.js ├── react-compiler/ │ ├── build-compiler.sh │ └── link-compiler.sh ├── release/ │ ├── .gitignore │ ├── README.md │ ├── build-release-locally-commands/ │ │ ├── add-build-info-json.js │ │ ├── build-artifacts.js │ │ ├── confirm-automated-testing.js │ │ ├── copy-repo-to-temp-directory.js │ │ ├── npm-pack-and-unpack.js │ │ └── update-version-numbers.js │ ├── build-release-locally.js │ ├── build-release.js │ ├── check-release-dependencies.js │ ├── ci-npmrc │ ├── download-experimental-build-commands/ │ │ └── print-summary.js │ ├── download-experimental-build.js │ ├── package.json │ ├── prepare-release-from-ci.js │ ├── prepare-release-from-npm-commands/ │ │ ├── check-out-packages.js │ │ ├── confirm-stable-version-numbers.js │ │ ├── get-latest-next-version.js │ │ ├── guess-stable-version-numbers.js │ │ ├── parse-params.js │ │ └── update-stable-version-numbers.js │ ├── prepare-release-from-npm.js │ ├── publish-commands/ │ │ ├── check-npm-permissions.js │ │ ├── confirm-skipped-packages.js │ │ ├── confirm-version-and-tags.js │ │ ├── parse-params.js │ │ ├── print-follow-up-instructions.js │ │ ├── prompt-for-otp.js │ │ ├── publish-to-npm.js │ │ ├── update-stable-version-numbers.js │ │ ├── validate-skip-packages.js │ │ └── validate-tags.js │ ├── publish-using-ci-workflow.js │ ├── publish.js │ ├── shared-commands/ │ │ ├── download-build-artifacts.js │ │ ├── parse-params.js │ │ ├── print-prerelease-summary.js │ │ └── test-packaging-fixture.js │ ├── snapshot-test.js │ ├── snapshot-test.snapshot │ ├── theme.js │ └── utils.js ├── rollup/ │ ├── build-all-release-channels.js │ ├── build.js │ ├── bundles.js │ ├── externs/ │ │ └── closure-externs.js │ ├── forks.js │ ├── generate-inline-fizz-runtime.js │ ├── modules.js │ ├── packaging.js │ ├── plugins/ │ │ ├── closure-plugin.js │ │ ├── dynamic-imports.js │ │ ├── external-runtime-plugin.js │ │ ├── sizes-plugin.js │ │ └── use-forks-plugin.js │ ├── shims/ │ │ ├── facebook-www/ │ │ │ └── ReactBrowserEventEmitter_DO_NOT_USE.js │ │ └── react-native/ │ │ ├── ReactFabric.js │ │ ├── ReactFeatureFlags.js │ │ ├── ReactNative.js │ │ ├── ReactNativeViewConfigRegistry.js │ │ └── createReactNativeComponentClass.js │ ├── stats.js │ ├── sync.js │ ├── utils.js │ ├── validate/ │ │ ├── eslintrc.cjs.js │ │ ├── eslintrc.cjs2015.js │ │ ├── eslintrc.esm.js │ │ ├── eslintrc.fb.js │ │ ├── eslintrc.rn.js │ │ └── index.js │ └── wrappers.js ├── shared/ │ ├── __tests__/ │ │ └── evalToString-test.js │ ├── evalToString.js │ ├── inlinedHostConfigs.js │ ├── listChangedFiles.js │ └── pathsByLanguageVersion.js ├── tasks/ │ ├── danger.js │ ├── eslint.js │ ├── flow-ci.js │ ├── flow.js │ ├── generate-changelog/ │ │ ├── args.js │ │ ├── data.js │ │ ├── formatters.js │ │ ├── index.js │ │ ├── summaries.js │ │ └── utils.js │ ├── linc.js │ └── version-check.js └── worktree.sh ================================================ FILE CONTENTS ================================================ ================================================ FILE: .claude/instructions.md ================================================ # React **Scope**: All code EXCEPT `/compiler/` (compiler has its own instructions). ## Project Structure | Directory | Purpose | |-----------|---------| | `/packages/` | Publishable packages (react, react-dom, scheduler, etc.) | | `/scripts/` | Build, test, and development scripts | | `/fixtures/` | Test applications for manual testing | | `/compiler/` | React Compiler (separate sub-project) | ## Key Packages | Package | Purpose | |---------|---------| | `react` | Core React library | | `react-dom` | DOM renderer | | `react-reconciler` | Core reconciliation algorithm | | `scheduler` | Cooperative scheduling | | `react-server-dom-*` | Server Components | | `react-devtools-*` | Developer Tools | | `react-refresh` | Fast Refresh runtime | ## Requirements - **Node**: Must be installed. Stop and prompt user if missing. - **Package Manager**: Use `yarn` only. ## Verification **IMPORTANT**: Use `/verify` to validate all changes before committing. ## Commands | Command | Purpose | |----------|----------------------| | `/fix` | Lint and format code | | `/test` | Run tests | | `/flow` | Type check with Flow | | `/flags` | Check feature flags | ## Building Builds are handled by CI. Do not run locally unless instructed. ================================================ FILE: .claude/settings.json ================================================ { "hooks": { "SessionStart": [ { "hooks": [ { "type": "command", "command": "if [[ \"$PWD\" != */compiler* ]]; then cat .claude/instructions.md 2>/dev/null || true; fi" } ] } ] }, "permissions": { "allow": [ "Skill(extract-errors)", "Skill(feature-flags)", "Skill(fix)", "Skill(flags)", "Skill(flow)", "Skill(test)", "Skill(verify)", "Bash(yarn test:*)", "Bash(yarn test-www:*)", "Bash(yarn test-classic:*)", "Bash(yarn test-stable:*)", "Bash(yarn linc:*)", "Bash(yarn lint:*)", "Bash(yarn flow:*)", "Bash(yarn prettier:*)", "Bash(yarn build:*)", "Bash(yarn extract-errors:*)", "Bash(yarn flags:*)" ], "deny": [ "Bash(yarn download-build:*)", "Bash(yarn download-build-for-head:*)", "Bash(npm:*)", "Bash(pnpm:*)", "Bash(bun:*)", "Bash(npx:*)" ] } } ================================================ FILE: .claude/skills/extract-errors/SKILL.md ================================================ --- name: extract-errors description: Use when adding new error messages to React, or seeing "unknown error code" warnings. --- # Extract Error Codes ## Instructions 1. Run `yarn extract-errors` 2. Report if any new errors need codes assigned 3. Check if error codes are up to date ================================================ FILE: .claude/skills/feature-flags/SKILL.md ================================================ --- name: feature-flags description: Use when feature flag tests fail, flags need updating, understanding @gate pragmas, debugging channel-specific test failures, or adding new flags to React. --- # React Feature Flags ## Flag Files | File | Purpose | |------|---------| | `packages/shared/ReactFeatureFlags.js` | Default flags (canary), `__EXPERIMENTAL__` overrides | | `packages/shared/forks/ReactFeatureFlags.www.js` | www channel, `__VARIANT__` overrides | | `packages/shared/forks/ReactFeatureFlags.native-fb.js` | React Native, `__VARIANT__` overrides | | `packages/shared/forks/ReactFeatureFlags.test-renderer.js` | Test renderer | ## Gating Tests ### `@gate` pragma (test-level) Use when the feature is completely unavailable without the flag: ```javascript // @gate enableViewTransition it('supports view transitions', () => { // This test only runs when enableViewTransition is true // and is SKIPPED (not failed) when false }); ``` ### `gate()` inline (assertion-level) Use when the feature exists but behavior differs based on flag: ```javascript it('renders component', async () => { await act(() => root.render()); if (gate(flags => flags.enableNewBehavior)) { expect(container.textContent).toBe('new output'); } else { expect(container.textContent).toBe('legacy output'); } }); ``` ## Adding a New Flag 1. Add to `ReactFeatureFlags.js` with default value 2. Add to each fork file (`*.www.js`, `*.native-fb.js`, etc.) 3. If it should vary in www/RN, set to `__VARIANT__` in the fork file 4. Gate tests with `@gate flagName` or inline `gate()` ## Checking Flag States Use `/flags` to view states across channels. See the `flags` skill for full command options. ## `__VARIANT__` Flags (GKs) Flags set to `__VARIANT__` simulate gatekeepers - tested twice (true and false): ```bash /test www # __VARIANT__ = true /test www variant false # __VARIANT__ = false ``` ## Debugging Channel-Specific Failures 1. Run `/flags --diff ` to compare values 2. Check `@gate` conditions - test may be gated to specific channels 3. Run `/test ` to isolate the failure 4. Verify flag exists in all fork files if newly added ## Common Mistakes - **Forgetting both variants** - Always test `www` AND `www variant false` for `__VARIANT__` flags - **Using @gate for behavior differences** - Use inline `gate()` if both paths should run - **Missing fork files** - New flags must be added to ALL fork files, not just the main one - **Wrong gate syntax** - It's `gate(flags => flags.name)`, not `gate('name')` ================================================ FILE: .claude/skills/fix/SKILL.md ================================================ --- name: fix description: Use when you have lint errors, formatting issues, or before committing code to ensure it passes CI. --- # Fix Lint and Formatting ## Instructions 1. Run `yarn prettier` to fix formatting 2. Run `yarn linc` to check for remaining lint issues 3. Report any remaining manual fixes needed ## Common Mistakes - **Running prettier on wrong files** - `yarn prettier` only formats changed files - **Ignoring linc errors** - These will fail CI, fix them before committing ================================================ FILE: .claude/skills/flags/SKILL.md ================================================ --- name: flags description: Use when you need to check feature flag states, compare channels, or debug why a feature behaves differently across release channels. --- # Feature Flags Arguments: - $ARGUMENTS: Optional flags ## Options | Option | Purpose | |--------|---------| | (none) | Show all flags across all channels | | `--diff ` | Compare flags between channels | | `--cleanup` | Show flags grouped by cleanup status | | `--csv` | Output in CSV format | ## Channels - `www`, `www-modern` - Meta internal - `canary`, `next`, `experimental` - OSS channels - `rn`, `rn-fb`, `rn-next` - React Native ## Legend ✅ enabled, ❌ disabled, 🧪 `__VARIANT__`, 📊 profiling-only ## Instructions 1. Run `yarn flags $ARGUMENTS` 2. Explain the output to the user 3. For --diff, highlight meaningful differences ## Common Mistakes - **Forgetting `__VARIANT__` flags** - These are tested both ways in www; check both variants - **Comparing wrong channels** - Use `--diff` to see exact differences ================================================ FILE: .claude/skills/flow/SKILL.md ================================================ --- name: flow description: Use when you need to run Flow type checking, or when seeing Flow type errors in React code. --- # Flow Type Checking Arguments: - $ARGUMENTS: Renderer to check (default: dom-node) ## Renderers | Renderer | When to Use | |----------|-------------| | `dom-node` | Default, recommended for most changes | | `dom-browser` | Browser-specific DOM code | | `native` | React Native | | `fabric` | React Native Fabric | ## Instructions 1. Run `yarn flow $ARGUMENTS` (use `dom-node` if no argument) 2. Report type errors with file locations 3. For comprehensive checking (slow), use `yarn flow-ci` ## Common Mistakes - **Running without a renderer** - Always specify or use default `dom-node` - **Ignoring suppressions** - Check if `$FlowFixMe` comments are masking real issues - **Missing type imports** - Ensure types are imported from the correct package ================================================ FILE: .claude/skills/test/SKILL.md ================================================ --- name: test description: Use when you need to run tests for React core. Supports source, www, stable, and experimental channels. --- Run tests for the React codebase. Arguments: - $ARGUMENTS: Channel, flags, and test pattern Usage Examples: - `/test ReactFiberHooks` - Run with source channel (default) - `/test experimental ReactFiberHooks` - Run with experimental channel - `/test www ReactFiberHooks` - Run with www-modern channel - `/test www variant false ReactFiberHooks` - Test __VARIANT__=false - `/test stable ReactFiberHooks` - Run with stable channel - `/test classic ReactFiberHooks` - Run with www-classic channel - `/test watch ReactFiberHooks` - Run in watch mode (TDD) Release Channels: - `(default)` - Source/canary channel, uses ReactFeatureFlags.js defaults - `experimental` - Source/experimental channel with __EXPERIMENTAL__ flags = true - `www` - www-modern channel with __VARIANT__ flags = true - `www variant false` - www channel with __VARIANT__ flags = false - `stable` - What ships to npm - `classic` - Legacy www-classic (rarely needed) Instructions: 1. Parse channel from arguments (default: source) 2. Map to yarn command: - (default) → `yarn test --silent --no-watchman ` - experimental → `yarn test -r=experimental --silent --no-watchman ` - stable → `yarn test-stable --silent --no-watchman ` - classic → `yarn test-classic --silent --no-watchman ` - www → `yarn test-www --silent --no-watchman ` - www variant false → `yarn test-www --variant=false --silent --no-watchman ` 3. Report test results and any failures Hard Rules: 1. **Use --silent to see failures** - This limits the test output to only failures. 2. **Use --no-watchman** - This is a common failure in sandboxing. Common Mistakes: - **Running without a pattern** - Runs ALL tests, very slow. Always specify a pattern. - **Forgetting both www variants** - Test `www` AND `www variant false` for `__VARIANT__` flags. - **Test skipped unexpectedly** - Check for `@gate` pragma; see `feature-flags` skill. ================================================ FILE: .claude/skills/verify/SKILL.md ================================================ --- name: verify description: Use when you want to validate changes before committing, or when you need to check all React contribution requirements. --- # Verification Run all verification steps. Arguments: - $ARGUMENTS: Test pattern for the test step ## Instructions Run these first in sequence: 1. Run `yarn prettier` - format code (stop if fails) 2. Run `yarn linc` - lint changed files (stop if fails) Then run these with subagents in parallel: 1. Use `/flow` to type check (stop if fails) 2. Use `/test` to test changes in source (stop if fails) 3. Use `/test www` to test changes in www (stop if fails) If all pass, show success summary. On failure, stop immediately and report the issue with suggested fixes. ================================================ FILE: .codesandbox/ci.json ================================================ { "packages": ["packages/react", "packages/react-dom", "packages/react-server-dom-webpack", "packages/scheduler"], "buildCommand": "download-build-in-codesandbox-ci", "node": "20", "publishDirectory": { "react": "build/oss-experimental/react", "react-dom": "build/oss-experimental/react-dom", "react-server-dom-webpack": "build/oss-experimental/react-server-dom-webpack", "scheduler": "build/oss-experimental/scheduler" }, "sandboxes": ["new"], "silent": true } ================================================ FILE: .editorconfig ================================================ # https://editorconfig.org root = true [*] charset = utf-8 end_of_line = lf indent_size = 2 indent_style = space insert_final_newline = true max_line_length = 80 [*.md] max_line_length = 0 [COMMIT_EDITMSG] max_line_length = 0 ================================================ FILE: .eslintignore ================================================ # Third party **/node_modules # Not written by hand packages/react-art/npm/lib # Build products build/ coverage/ fixtures/ scripts/bench/benchmarks/**/*.js # React repository clone scripts/bench/remote-repo/ # Compiler uses its own lint setup compiler/ packages/react-devtools-core/dist packages/react-devtools-extensions/chrome/build packages/react-devtools-extensions/firefox/build packages/react-devtools-extensions/shared/build packages/react-devtools-extensions/src/ErrorTesterCompiled.js packages/react-devtools-fusebox/dist packages/react-devtools-inline/dist packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/ packages/react-devtools-shared/src/hooks/__tests__/__source__/__untransformed__/ packages/react-devtools-shell/dist packages/react-devtools-timeline/dist packages/react-devtools-timeline/static # Imported third-party Flow types flow-typed/ ================================================ FILE: .eslintrc.js ================================================ 'use strict'; const { es5Paths, esNextPaths, } = require('./scripts/shared/pathsByLanguageVersion'); const restrictedGlobals = require('confusing-browser-globals'); const OFF = 0; const WARNING = 1; const ERROR = 2; module.exports = { extends: ['prettier', 'plugin:jest/recommended'], // Stop ESLint from looking for a configuration file in parent folders root: true, reportUnusedDisableDirectives: true, plugins: [ 'babel', 'ft-flow', 'jest', 'es', 'no-for-of-loops', 'no-function-declare-after-return', 'react', 'react-internal', ], parser: 'hermes-eslint', parserOptions: { ecmaVersion: 9, sourceType: 'script', }, // We're stricter than the default config, mostly. We'll override a few rules // and then enable some React specific ones. rules: { 'ft-flow/array-style-complex-type': [OFF, 'verbose'], 'ft-flow/array-style-simple-type': [OFF, 'verbose'], // TODO should be WARNING 'ft-flow/boolean-style': ERROR, 'ft-flow/no-dupe-keys': ERROR, 'ft-flow/no-primitive-constructor-types': ERROR, 'ft-flow/no-types-missing-file-annotation': OFF, // TODO should be ERROR 'ft-flow/no-unused-expressions': ERROR, // 'ft-flow/no-weak-types': WARNING, // 'ft-flow/require-valid-file-annotation': ERROR, 'es/no-optional-chaining': ERROR, 'no-cond-assign': OFF, 'no-constant-condition': OFF, 'no-control-regex': OFF, 'no-debugger': ERROR, 'no-dupe-args': ERROR, 'no-dupe-keys': ERROR, 'no-duplicate-case': WARNING, 'no-empty-character-class': WARNING, 'no-empty': OFF, 'no-ex-assign': WARNING, 'no-extra-boolean-cast': WARNING, 'no-func-assign': ERROR, 'no-invalid-regexp': WARNING, 'no-irregular-whitespace': WARNING, 'no-negated-in-lhs': ERROR, 'no-obj-calls': ERROR, 'no-regex-spaces': WARNING, 'no-sparse-arrays': ERROR, 'no-unreachable': ERROR, 'use-isnan': ERROR, 'valid-jsdoc': OFF, 'block-scoped-var': OFF, complexity: OFF, 'default-case': OFF, 'guard-for-in': OFF, 'no-alert': OFF, 'no-caller': ERROR, 'no-case-declarations': OFF, 'no-div-regex': OFF, 'no-else-return': OFF, 'no-empty-pattern': WARNING, 'no-eq-null': OFF, 'no-eval': ERROR, 'no-extend-native': WARNING, 'no-extra-bind': WARNING, 'no-fallthrough': WARNING, 'no-implicit-coercion': OFF, 'no-implied-eval': ERROR, 'no-invalid-this': OFF, 'no-iterator': OFF, 'no-labels': [ERROR, {allowLoop: true, allowSwitch: true}], 'no-lone-blocks': WARNING, 'no-loop-func': OFF, 'no-magic-numbers': OFF, 'no-multi-str': ERROR, 'no-native-reassign': [ERROR, {exceptions: ['Map', 'Set']}], 'no-new-func': ERROR, 'no-new': WARNING, 'no-new-wrappers': WARNING, 'no-octal-escape': WARNING, 'no-octal': WARNING, 'no-param-reassign': OFF, 'no-process-env': OFF, 'no-proto': ERROR, 'no-redeclare': OFF, // TODO should be WARNING? 'no-return-assign': OFF, 'no-script-url': ERROR, 'no-self-compare': WARNING, 'no-sequences': WARNING, 'no-throw-literal': ERROR, 'no-useless-call': WARNING, 'no-void': OFF, 'no-warning-comments': OFF, 'no-with': OFF, radix: WARNING, 'vars-on-top': OFF, yoda: OFF, 'init-declarations': OFF, 'no-catch-shadow': ERROR, 'no-delete-var': ERROR, 'no-label-var': WARNING, 'no-shadow-restricted-names': WARNING, 'no-undef-init': OFF, 'no-undef': ERROR, 'no-undefined': OFF, 'callback-return': OFF, 'global-require': OFF, 'handle-callback-err': OFF, 'no-mixed-requires': OFF, 'no-new-require': OFF, 'no-path-concat': OFF, 'no-process-exit': OFF, 'no-restricted-modules': OFF, 'no-sync': OFF, camelcase: [OFF, {properties: 'always'}], 'consistent-this': [OFF, 'self'], 'func-names': OFF, 'func-style': [OFF, 'declaration'], 'id-length': OFF, 'id-match': OFF, 'max-depth': OFF, 'max-nested-callbacks': OFF, 'max-params': OFF, 'max-statements': OFF, 'new-cap': OFF, 'newline-after-var': OFF, 'no-array-constructor': ERROR, 'no-continue': OFF, 'no-inline-comments': OFF, 'no-lonely-if': OFF, 'no-negated-condition': OFF, 'no-nested-ternary': OFF, 'no-new-object': WARNING, 'no-plusplus': OFF, 'no-ternary': OFF, 'no-underscore-dangle': OFF, 'no-unneeded-ternary': WARNING, 'one-var': [WARNING, {initialized: 'never'}], 'operator-assignment': [WARNING, 'always'], 'require-jsdoc': OFF, 'sort-vars': OFF, 'spaced-comment': [ OFF, 'always', {exceptions: ['jshint', 'jslint', 'eslint', 'global']}, ], 'constructor-super': ERROR, 'no-class-assign': WARNING, 'no-const-assign': ERROR, 'no-dupe-class-members': ERROR, 'no-this-before-super': ERROR, 'object-shorthand': OFF, 'prefer-const': OFF, 'prefer-spread': OFF, 'prefer-reflect': OFF, 'prefer-template': OFF, 'require-yield': OFF, 'babel/generator-star-spacing': OFF, 'babel/new-cap': OFF, 'babel/array-bracket-spacing': OFF, 'babel/object-curly-spacing': OFF, 'babel/object-shorthand': OFF, 'babel/arrow-parens': OFF, 'babel/no-await-in-loop': OFF, 'babel/flow-object-type': OFF, 'react/display-name': OFF, 'react/forbid-prop-types': OFF, 'react/jsx-closing-bracket-location': OFF, 'react/jsx-curly-spacing': OFF, 'react/jsx-equals-spacing': WARNING, 'react/jsx-filename-extension': OFF, 'react/jsx-first-prop-new-line': OFF, 'react/jsx-handler-names': OFF, 'react/jsx-indent': OFF, 'react/jsx-indent-props': OFF, 'react/jsx-key': OFF, 'react/jsx-max-props-per-line': OFF, 'react/jsx-no-bind': OFF, 'react/jsx-no-duplicate-props': ERROR, 'react/jsx-no-literals': OFF, 'react/jsx-no-target-blank': OFF, 'react/jsx-pascal-case': OFF, 'react/jsx-sort-props': OFF, 'react/jsx-uses-vars': ERROR, 'react/no-comment-textnodes': OFF, 'react/no-danger': OFF, 'react/no-deprecated': OFF, 'react/no-did-mount-set-state': OFF, 'react/no-did-update-set-state': OFF, 'react/no-direct-mutation-state': OFF, 'react/no-multi-comp': OFF, 'react/no-render-return-value': OFF, 'react/no-set-state': OFF, 'react/no-string-refs': OFF, 'react/no-unknown-property': OFF, 'react/prefer-es6-class': OFF, 'react/prefer-stateless-function': OFF, 'react/prop-types': OFF, 'react/require-extension': OFF, 'react/require-optimization': OFF, 'react/require-render-return': OFF, 'react/sort-comp': OFF, 'react/sort-prop-types': OFF, 'accessor-pairs': OFF, 'brace-style': [ERROR, '1tbs'], 'consistent-return': OFF, 'dot-location': [ERROR, 'property'], // We use console['error']() as a signal to not transform it: 'dot-notation': [ERROR, {allowPattern: '^(error|warn)$'}], 'eol-last': ERROR, eqeqeq: [ERROR, 'allow-null'], indent: OFF, 'jsx-quotes': [ERROR, 'prefer-double'], 'keyword-spacing': [ERROR, {after: true, before: true}], 'no-bitwise': OFF, 'no-console': OFF, 'no-inner-declarations': [ERROR, 'functions'], 'no-multi-spaces': ERROR, 'no-restricted-globals': [ERROR].concat(restrictedGlobals), 'no-restricted-syntax': [ ERROR, 'WithStatement', { selector: 'MemberExpression[property.name=/^(?:substring|substr)$/]', message: 'Prefer string.slice() over .substring() and .substr().', }, ], 'no-shadow': ERROR, 'no-unused-vars': [ERROR, {args: 'none', ignoreRestSiblings: true}], 'no-use-before-define': OFF, 'no-useless-concat': OFF, quotes: [ERROR, 'single', {avoidEscape: true, allowTemplateLiterals: true}], 'space-before-blocks': ERROR, 'space-before-function-paren': OFF, 'valid-typeof': [ERROR, {requireStringLiterals: true}], // Flow fails with non-string literal keys 'no-useless-computed-key': OFF, // We apply these settings to files that should run on Node. // They can't use JSX or ES6 modules, and must be in strict mode. // They can, however, use other ES6 features. // (Note these rules are overridden later for source files.) 'no-var': ERROR, strict: ERROR, // Enforced by Prettier // TODO: Prettier doesn't handle long strings or long comments. Not a big // deal. But I turned it off because loading the plugin causes some obscure // syntax error and it didn't seem worth investigating. 'max-len': OFF, // React & JSX // Our transforms set this automatically 'react/jsx-boolean-value': [ERROR, 'always'], 'react/jsx-no-undef': ERROR, // We don't care to do this 'react/jsx-sort-prop-types': OFF, 'react/jsx-space-before-closing': ERROR, 'react/jsx-uses-react': ERROR, 'react/no-is-mounted': OFF, // This isn't useful in our test code 'react/react-in-jsx-scope': ERROR, 'react/self-closing-comp': ERROR, // We don't care to do this 'react/jsx-wrap-multilines': [ ERROR, {declaration: false, assignment: false}, ], // Prevent for...of loops because they require a Symbol polyfill. // You can disable this rule for code that isn't shipped (e.g. build scripts and tests). 'no-for-of-loops/no-for-of-loops': ERROR, // Prevent function declarations after return statements 'no-function-declare-after-return/no-function-declare-after-return': ERROR, // CUSTOM RULES // the second argument of warning/invariant should be a literal string 'react-internal/no-primitive-constructors': ERROR, 'react-internal/safe-string-coercion': [ ERROR, {isProductionUserAppCode: true}, ], 'react-internal/warning-args': ERROR, 'react-internal/no-production-logging': ERROR, }, overrides: [ { // By default, anything error message that appears the packages directory // must have a corresponding error code. The exceptions are defined // in the next override entry. files: ['packages/**/*.js'], rules: { 'react-internal/prod-error-codes': ERROR, }, }, { // These are files where it's OK to have unminified error messages. These // are environments where bundle size isn't a concern, like tests // or Node. files: [ 'packages/react-dom/src/test-utils/**/*.js', 'packages/react-devtools-shared/**/*.js', 'packages/react-noop-renderer/**/*.js', 'packages/react-refresh/**/*.js', 'packages/react-server-dom-esm/**/*.js', 'packages/react-server-dom-webpack/**/*.js', 'packages/react-server-dom-turbopack/**/*.js', 'packages/react-server-dom-parcel/**/*.js', 'packages/react-server-dom-fb/**/*.js', 'packages/react-server-dom-unbundled/**/*.js', 'packages/react-test-renderer/**/*.js', 'packages/react-debug-tools/**/*.js', 'packages/react-devtools-extensions/**/*.js', 'packages/react-devtools-timeline/**/*.js', 'packages/react-native-renderer/**/*.js', 'packages/eslint-plugin-react-hooks/**/*.js', 'packages/jest-react/**/*.js', 'packages/internal-test-utils/**/*.js', 'packages/**/__tests__/*.js', 'packages/**/npm/*.js', ], rules: { 'react-internal/prod-error-codes': OFF, }, }, { // We apply these settings to files that we ship through npm. // They must be ES5. files: es5Paths, parser: 'espree', parserOptions: { ecmaVersion: 5, sourceType: 'script', }, rules: { 'no-var': OFF, strict: ERROR, }, }, { // We apply these settings to the source files that get compiled. // They can use all features including JSX (but shouldn't use `var`). files: esNextPaths, parser: 'hermes-eslint', parserOptions: { ecmaVersion: 8, sourceType: 'module', }, rules: { 'no-var': ERROR, 'prefer-const': ERROR, strict: OFF, }, }, { files: ['**/__tests__/*.js'], rules: { // https://github.com/jest-community/eslint-plugin-jest // Meh, who cares. 'jest/consistent-test-it': OFF, // Meh, we have a lot of these, who cares. 'jest/no-alias-methods': OFF, // We do conditions based on feature flags. 'jest/no-conditional-expect': OFF, // We have our own assertion helpers. 'jest/expect-expect': OFF, // Lame rule that fires in itRender helpers or in render methods. 'jest/no-standalone-expect': OFF, }, }, { // Rules specific to test setup helper files. files: [ '**/setupTests.js', '**/setupEnv.js', '**/jest/TestFlags.js', '**/dom-event-testing-library/testHelpers.js', '**/utils/ReactDOMServerIntegrationTestUtils.js', '**/babel/transform-react-version-pragma.js', '**/babel/transform-test-gate-pragma.js', ], rules: { // Some helpers intentionally focus tests. 'jest/no-focused-tests': OFF, // Test fn helpers don't use static text names. 'jest/valid-title': OFF, // We have our own assertion helpers. 'jest/expect-expect': OFF, // Some helpers intentionally disable tests. 'jest/no-disabled-tests': OFF, // Helpers export text function helpers. 'jest/no-export': OFF, // The examples in comments trigger false errors. 'jest/no-commented-out-tests': OFF, }, }, { files: ['**/jest/TestFlags.js'], rules: { // The examples in comments trigger false errors. 'jest/no-commented-out-tests': OFF, }, }, { files: [ '**/__tests__/**/*.js', 'scripts/**/*.js', 'packages/*/npm/**/*.js', 'packages/dom-event-testing-library/**/*.js', 'packages/react-devtools*/**/*.js', 'dangerfile.js', 'fixtures', 'packages/react-dom/src/test-utils/*.js', ], rules: { 'es/no-optional-chaining': OFF, 'react-internal/no-production-logging': OFF, 'react-internal/warning-args': OFF, 'react-internal/safe-string-coercion': [ ERROR, {isProductionUserAppCode: false}, ], }, }, { files: ['scripts/eslint-rules/*.js'], plugins: ['eslint-plugin'], rules: { 'eslint-plugin/prefer-object-rule': ERROR, 'eslint-plugin/require-meta-fixable': [ ERROR, {catchNoFixerButFixableProperty: true}, ], 'eslint-plugin/require-meta-has-suggestions': ERROR, }, }, { files: ['packages/react-native-renderer/**/*.js'], globals: { nativeFabricUIManager: 'readonly', RN$enableMicrotasksInReact: 'readonly', }, }, { files: ['packages/react-server-dom-webpack/**/*.js'], globals: { __webpack_chunk_load__: 'readonly', __webpack_get_script_filename__: 'readonly', __webpack_require__: 'readonly', }, }, { files: ['packages/react-server-dom-turbopack/**/*.js'], globals: { __turbopack_load_by_url__: 'readonly', __turbopack_require__: 'readonly', }, }, { files: ['packages/react-server-dom-parcel/**/*.js'], globals: { parcelRequire: 'readonly', }, }, { files: ['packages/scheduler/**/*.js'], globals: { TaskController: 'readonly', }, }, { files: [ 'packages/react-devtools-extensions/**/*.js', 'packages/react-devtools-shared/src/devtools/views/**/*.js', 'packages/react-devtools-shared/src/hook.js', 'packages/react-devtools-shared/src/backend/console.js', 'packages/react-devtools-shared/src/backend/fiber/renderer.js', 'packages/react-devtools-shared/src/backend/shared/DevToolsComponentStackFrame.js', 'packages/react-devtools-shared/src/frontend/utils/withPermissionsCheck.js', ], globals: { __IS_CHROME__: 'readonly', __IS_FIREFOX__: 'readonly', __IS_EDGE__: 'readonly', __IS_NATIVE__: 'readonly', __IS_INTERNAL_VERSION__: 'readonly', chrome: 'readonly', }, }, { files: ['packages/react-devtools-shared/**/*.js'], globals: { __IS_INTERNAL_VERSION__: 'readonly', }, }, { files: ['packages/react-devtools-*/**/*.js'], excludedFiles: '**/__tests__/**/*.js', plugins: ['eslint-plugin-react-hooks-published'], rules: { 'react-hooks-published/rules-of-hooks': ERROR, }, }, { files: ['packages/eslint-plugin-react-hooks/src/**/*'], extends: ['plugin:@typescript-eslint/recommended'], parser: '@typescript-eslint/parser', plugins: ['@typescript-eslint', 'eslint-plugin'], rules: { '@typescript-eslint/no-explicit-any': OFF, '@typescript-eslint/no-non-null-assertion': OFF, '@typescript-eslint/array-type': [ERROR, {default: 'generic'}], 'es/no-optional-chaining': OFF, 'eslint-plugin/prefer-object-rule': ERROR, 'eslint-plugin/require-meta-fixable': [ ERROR, {catchNoFixerButFixableProperty: true}, ], 'eslint-plugin/require-meta-has-suggestions': ERROR, }, }, ], env: { browser: true, es6: true, node: true, jest: true, }, globals: { $Flow$ModuleRef: 'readonly', $FlowFixMe: 'readonly', $Keys: 'readonly', $NonMaybeType: 'readonly', $ReadOnly: 'readonly', $ReadOnlyArray: 'readonly', $ArrayBufferView: 'readonly', $Shape: 'readonly', CallSite: 'readonly', ConsoleTask: 'readonly', // TOOD: Figure out what the official name of this will be. ReturnType: 'readonly', AggregateError: 'readonly', AnimationFrameID: 'readonly', WeakRef: 'readonly', // For Flow type annotation. Only `BigInt` is valid at runtime. bigint: 'readonly', BigInt: 'readonly', BigInt64Array: 'readonly', BigUint64Array: 'readonly', CacheType: 'readonly', Class: 'readonly', ClientRect: 'readonly', CopyInspectedElementPath: 'readonly', DOMHighResTimeStamp: 'readonly', EventListener: 'readonly', Iterable: 'readonly', AsyncIterable: 'readonly', $AsyncIterable: 'readonly', $AsyncIterator: 'readonly', Iterator: 'readonly', AsyncIterator: 'readonly', IntervalID: 'readonly', IteratorResult: 'readonly', JSONValue: 'readonly', JSResourceReference: 'readonly', mixin$Animatable: 'readonly', MouseEventHandler: 'readonly', NavigateEvent: 'readonly', Partial: 'readonly', PerformanceMeasureOptions: 'readonly', PropagationPhases: 'readonly', PropertyDescriptor: 'readonly', PropertyDescriptorMap: 'readonly', Proxy$traps: 'readonly', React$Component: 'readonly', React$Config: 'readonly', React$Context: 'readonly', React$Element: 'readonly', React$ElementConfig: 'readonly', React$ElementProps: 'readonly', React$ElementRef: 'readonly', React$ElementType: 'readonly', React$Key: 'readonly', React$Node: 'readonly', React$Portal: 'readonly', React$Ref: 'readonly', React$RefSetter: 'readonly', ReadableStreamController: 'readonly', ReadableStreamReader: 'readonly', RequestInfo: 'readonly', RequestOptions: 'readonly', StoreAsGlobal: 'readonly', symbol: 'readonly', SyntheticEvent: 'readonly', SyntheticMouseEvent: 'readonly', SyntheticPointerEvent: 'readonly', Thenable: 'readonly', TimeoutID: 'readonly', WheelEventHandler: 'readonly', FinalizationRegistry: 'readonly', Exclude: 'readonly', Omit: 'readonly', Pick: 'readonly', Keyframe: 'readonly', PropertyIndexedKeyframes: 'readonly', KeyframeAnimationOptions: 'readonly', GetAnimationsOptions: 'readonly', ScrollTimeline: 'readonly', EventListenerOptionsOrUseCapture: 'readonly', FocusOptions: 'readonly', OptionalEffectTiming: 'readonly', __REACT_ROOT_PATH_TEST__: 'readonly', spyOnDev: 'readonly', spyOnDevAndProd: 'readonly', spyOnProd: 'readonly', __DEV__: 'readonly', __EXPERIMENTAL__: 'readonly', __EXTENSION__: 'readonly', __PROFILE__: 'readonly', __TEST__: 'readonly', __VARIANT__: 'readonly', __unmockReact: 'readonly', gate: 'readonly', trustedTypes: 'readonly', IS_REACT_ACT_ENVIRONMENT: 'readonly', AsyncLocalStorage: 'readonly', async_hooks: 'readonly', globalThis: 'readonly', navigation: 'readonly', }, }; ================================================ FILE: .git-blame-ignore-revs ================================================ c998bb1ed4b3285398c9c7797135d3f060243c6a fd2b3e13d330a4559f5aa21462e1cb2cbbcf144b ================================================ FILE: .gitattributes ================================================ * text=auto ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: "🐛 Bug Report" about: Report a reproducible bug or regression. title: 'Bug: ' labels: 'Status: Unconfirmed' --- React version: ## Steps To Reproduce 1. 2. Link to code example: ## The current behavior ## The expected behavior ================================================ FILE: .github/ISSUE_TEMPLATE/compiler_bug_report.yml ================================================ name: "⚛️ ✨ Compiler bug report" description: "Report a problem with React Compiler. Please provide enough information that we can reproduce the problem." title: "[Compiler Bug]: " labels: ["Component: Optimizing Compiler", "Type: Bug", "Status: Unconfirmed"] body: - type: checkboxes attributes: label: What kind of issue is this? description: | Please indicate if this issue affects the following tools provided by React Compiler. options: - label: React Compiler core (the JS output is incorrect, or your app works incorrectly after optimization) - label: babel-plugin-react-compiler (build issue installing or using the Babel plugin) - label: eslint-plugin-react-hooks (build issue installing or using the eslint plugin) - label: react-compiler-healthcheck (build issue installing or using the healthcheck script) - type: input attributes: label: Link to repro description: | Please provide a repro by either sharing a [Playground link](https://playground.react.dev), or a public GitHub repo so the React team can reproduce the error being reported. Please do not share localhost links! placeholder: | e.g. public GitHub repo, or Playground link validations: required: true - type: textarea attributes: label: Repro steps description: | What were you doing when the bug happened? Detailed information helps maintainers reproduce and fix bugs. Issues filed without repro steps will be closed. placeholder: | Example bug report: 1. Log in with username/password 2. Click "Messages" on the left menu 3. Open any message in the list validations: required: true - type: dropdown attributes: label: How often does this bug happen? description: | Following the repro steps above, how easily are you able to reproduce this bug? options: - Every time - Often - Sometimes - Only once validations: required: true - type: input attributes: label: What version of React are you using? description: | Please provide your React version in the app where this issue occurred. validations: required: true - type: input attributes: label: What version of React Compiler are you using? description: | Please provide the exact React Compiler version in the app where this issue occurred. validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false contact_links: - name: 📃 Documentation Issue url: https://github.com/reactjs/react.dev/issues/new/choose about: This issue tracker is not for documentation issues. Please file documentation issues here. - name: 🤔 Questions and Help url: https://reactjs.org/community/support.html about: This issue tracker is not for support questions. Please refer to the React community's help and discussion forums. ================================================ FILE: .github/ISSUE_TEMPLATE/devtools_bug_report.yml ================================================ name: "⚛️ 🛠 DevTools bug report" description: "Report a problem with React DevTools. Please provide enough information that we can reproduce the problem." title: "[DevTools Bug]: " labels: ["Component: Developer Tools", "Type: Bug", "Status: Unconfirmed"] body: - type: input attributes: label: Website or app description: | Which website or app were you using when the bug happened? This should be a public URL, GitHub repo, or Code Sandbox app so the React team can reproduce the error being reported. (Please no localhost URLs.) placeholder: | e.g. website URL, public GitHub repo, or Code Sandbox app validations: required: true - type: textarea attributes: label: Repro steps description: | What were you doing on the website or app when the bug happened? Detailed information helps maintainers reproduce and fix bugs. Issues filed without repro steps will be closed. placeholder: | Example bug report: 1. Log in with username/password 2. Click "Messages" on the left menu 3. Open any message in the list validations: required: true - type: dropdown attributes: label: How often does this bug happen? description: | Following the repro steps above, how easily are you able to reproduce this bug? options: - Every time - Often - Sometimes - Only once validations: required: true - type: input id: automated_package attributes: label: DevTools package (automated) description: | Please do not edit this field. - type: input id: automated_version attributes: label: DevTools version (automated) description: | Please do not edit this field. - type: input id: automated_error_message attributes: label: Error message (automated) description: | Please do not edit this field. - type: textarea id: automated_call_stack attributes: label: Error call stack (automated) description: | Please do not edit this field. render: text - type: textarea id: automated_component_stack attributes: label: Error component stack (automated) description: | Please do not edit this field. render: text - type: textarea id: automated_github_query_string attributes: label: GitHub query string (automated) description: | Please do not edit this field. render: text ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ ## Summary ## How did you test this change? ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: "npm" directories: - "/fixtures/*" schedule: interval: "monthly" open-pull-requests-limit: 0 ignore: - dependency-name: "*" ================================================ FILE: .github/workflows/compiler_discord_notify.yml ================================================ name: (Compiler) Discord Notify on: pull_request_target: types: [opened, ready_for_review] paths: - compiler/** - .github/workflows/compiler_**.yml permissions: {} jobs: check_access: if: ${{ github.event.pull_request.draft == false }} runs-on: ubuntu-latest outputs: is_member_or_collaborator: ${{ steps.check_is_member_or_collaborator.outputs.is_member_or_collaborator }} steps: - run: echo ${{ github.event.pull_request.author_association }} - name: Check is member or collaborator id: check_is_member_or_collaborator if: ${{ github.event.pull_request.author_association == 'MEMBER' || github.event.pull_request.author_association == 'COLLABORATOR' }} run: echo "is_member_or_collaborator=true" >> "$GITHUB_OUTPUT" check_maintainer: if: ${{ needs.check_access.outputs.is_member_or_collaborator == 'true' || needs.check_access.outputs.is_member_or_collaborator == true }} needs: [check_access] uses: facebook/react/.github/workflows/shared_check_maintainer.yml@main permissions: # Used by check_maintainer contents: read with: actor: ${{ github.event.pull_request.user.login }} notify: if: ${{ needs.check_maintainer.outputs.is_core_team == 'true' }} needs: check_maintainer runs-on: ubuntu-latest steps: - name: Discord Webhook Action uses: tsickert/discord-webhook@86dc739f3f165f16dadc5666051c367efa1692f4 with: webhook-url: ${{ secrets.COMPILER_DISCORD_WEBHOOK_URL }} embed-author-name: ${{ github.event.pull_request.user.login }} embed-author-url: ${{ github.event.pull_request.user.html_url }} embed-author-icon-url: ${{ github.event.pull_request.user.avatar_url }} embed-title: '#${{ github.event.number }} (+${{github.event.pull_request.additions}} -${{github.event.pull_request.deletions}}): ${{ github.event.pull_request.title }}' embed-description: ${{ github.event.pull_request.body }} embed-url: ${{ github.event.pull_request.html_url }} ================================================ FILE: .github/workflows/compiler_playground.yml ================================================ name: (Compiler) Playground on: push: branches: [main] pull_request: paths: - compiler/** - .github/workflows/compiler_playground.yml permissions: {} concurrency: group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.run_id }} cancel-in-progress: true env: TZ: /usr/share/zoneinfo/America/Los_Angeles # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1 defaults: run: working-directory: compiler/apps/playground jobs: playground: name: Test playground runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: compiler/**/yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 id: node_modules with: path: | **/node_modules key: compiler-and-playground-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }} - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' working-directory: compiler - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Check Playwright version id: playwright_version run: echo "playwright_version=$(npm ls @playwright/test | grep @playwright | sed 's/.*@//' | head -1)" >> "$GITHUB_OUTPUT" - name: Cache Playwright Browsers for version ${{ steps.playwright_version.outputs.playwright_version }} id: cache_playwright_browsers uses: actions/cache@v4 with: path: ~/.cache/ms-playwright key: playwright-browsers-v6-${{ runner.arch }}-${{ runner.os }}-${{ steps.playwright_version.outputs.playwright_version }} - run: npx playwright install --with-deps chromium if: steps.cache_playwright_browsers.outputs.cache-hit != 'true' - run: CI=true yarn test - run: ls -R test-results if: '!cancelled()' - name: Archive test results if: '!cancelled()' uses: actions/upload-artifact@v4 with: name: test-results path: compiler/apps/playground/test-results if-no-files-found: ignore ================================================ FILE: .github/workflows/compiler_prereleases.yml ================================================ name: (Compiler) Publish Prereleases on: workflow_call: inputs: commit_sha: required: true default: '' type: string release_channel: required: true type: string dist_tag: required: true type: string version_name: required: true type: string tag_version: required: false type: string dry_run: required: false type: boolean secrets: NPM_TOKEN: required: true permissions: {} env: TZ: /usr/share/zoneinfo/America/Los_Angeles # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1 NPM_TOKEN: ${{ secrets.NPM_TOKEN }} defaults: run: working-directory: compiler jobs: publish_prerelease: name: Publish prelease (${{ inputs.release_channel }}) ${{ inputs.commit_sha }} @${{ inputs.dist_tag }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: compiler/yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 id: node_modules with: path: | **/node_modules key: compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/yarn.lock') }} - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - if: inputs.dry_run == true name: Publish packages to npm (dry run) run: | cp ./scripts/release/ci-npmrc ~/.npmrc scripts/release/publish.js --frfr --debug --ci --versionName=${{ inputs.version_name }} --tag=${{ inputs.dist_tag }} ${{ inputs.tag_version && format('--tagVersion={0}', inputs.tag_version) || '' }} - if: inputs.dry_run != true name: Publish packages to npm run: | cp ./scripts/release/ci-npmrc ~/.npmrc scripts/release/publish.js --frfr --ci --versionName=${{ inputs.version_name }} --tag=${{ inputs.dist_tag }} ${{ inputs.tag_version && format('--tagVersion={0}', inputs.tag_version) || '' }} ================================================ FILE: .github/workflows/compiler_prereleases_manual.yml ================================================ name: (Compiler) Publish Prereleases Manual on: workflow_dispatch: inputs: prerelease_commit_sha: required: false release_channel: required: true type: string dist_tag: required: true type: string version_name: required: true type: string tag_version: required: false type: string dry_run: required: false type: boolean permissions: {} env: TZ: /usr/share/zoneinfo/America/Los_Angeles jobs: publish_prerelease_experimental: name: Publish to Experimental channel uses: facebook/react/.github/workflows/compiler_prereleases.yml@main with: commit_sha: ${{ inputs.prerelease_commit_sha || github.sha }} release_channel: ${{ inputs.release_channel }} dist_tag: ${{ inputs.dist_tag }} version_name: ${{ inputs.version_name }} tag_version: ${{ inputs.tag_version }} dry_run: ${{ inputs.dry_run }} secrets: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} ================================================ FILE: .github/workflows/compiler_prereleases_nightly.yml ================================================ name: (Compiler) Publish Prereleases Nightly on: schedule: # At 10 minutes past 16:00 on Mon, Tue, Wed, Thu, and Fri - cron: 10 16 * * 1,2,3,4,5 permissions: {} env: TZ: /usr/share/zoneinfo/America/Los_Angeles jobs: publish_prerelease_experimental: name: Publish to Experimental channel uses: facebook/react/.github/workflows/compiler_prereleases.yml@main with: commit_sha: ${{ github.sha }} release_channel: experimental dist_tag: experimental version_name: '0.0.0' dry_run: false secrets: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} ================================================ FILE: .github/workflows/compiler_typescript.yml ================================================ name: (Compiler) TypeScript on: push: branches: [main] pull_request: paths: - compiler/** - .github/workflows/compiler_typescript.yml permissions: {} concurrency: group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.run_id }} cancel-in-progress: true env: TZ: /usr/share/zoneinfo/America/Los_Angeles # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1 defaults: run: working-directory: compiler jobs: discover_yarn_workspaces: name: Discover yarn workspaces runs-on: ubuntu-latest outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - uses: actions/checkout@v4 - id: set-matrix run: echo "matrix=$(find packages -mindepth 1 -maxdepth 1 -type d | sed 's!packages/!!g' | tr '\n' ',' | sed s/.$// | jq -Rsc '. / "," - [""]')" >> $GITHUB_OUTPUT # Hardcoded to improve parallelism lint: name: Lint babel-plugin-react-compiler runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: compiler/yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 id: node_modules with: path: | **/node_modules key: compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/yarn.lock') }} - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: yarn workspace babel-plugin-react-compiler lint # Hardcoded to improve parallelism jest: name: Jest babel-plugin-react-compiler runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: compiler/yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 id: node_modules with: path: | **/node_modules key: compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/yarn.lock') }} - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: yarn workspace babel-plugin-react-compiler jest test: name: Test ${{ matrix.workspace_name }} needs: discover_yarn_workspaces runs-on: ubuntu-latest strategy: fail-fast: false matrix: workspace_name: ${{ fromJSON(needs.discover_yarn_workspaces.outputs.matrix) }} steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: compiler/yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 id: node_modules with: path: | **/node_modules key: compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/yarn.lock') }} - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: xvfb-run -a yarn workspace ${{ matrix.workspace_name }} test if: runner.os == 'Linux' && matrix.workspace_name == 'react-forgive' - run: yarn workspace ${{ matrix.workspace_name }} test if: matrix.workspace_name != 'react-forgive' ================================================ FILE: .github/workflows/devtools_discord_notify.yml ================================================ name: (DevTools) Discord Notify on: pull_request_target: types: [opened, ready_for_review] paths: - packages/react-devtools** - .github/workflows/devtools_**.yml permissions: {} jobs: check_access: if: ${{ github.event.pull_request.draft == false }} runs-on: ubuntu-latest outputs: is_member_or_collaborator: ${{ steps.check_is_member_or_collaborator.outputs.is_member_or_collaborator }} steps: - run: echo ${{ github.event.pull_request.author_association }} - name: Check is member or collaborator id: check_is_member_or_collaborator if: ${{ github.event.pull_request.author_association == 'MEMBER' || github.event.pull_request.author_association == 'COLLABORATOR' }} run: echo "is_member_or_collaborator=true" >> "$GITHUB_OUTPUT" check_maintainer: if: ${{ needs.check_access.outputs.is_member_or_collaborator == 'true' || needs.check_access.outputs.is_member_or_collaborator == true }} needs: [check_access] uses: facebook/react/.github/workflows/shared_check_maintainer.yml@main permissions: # Used by check_maintainer contents: read with: actor: ${{ github.event.pull_request.user.login }} notify: if: ${{ needs.check_maintainer.outputs.is_core_team == 'true' }} needs: check_maintainer runs-on: ubuntu-latest steps: - name: Discord Webhook Action uses: tsickert/discord-webhook@86dc739f3f165f16dadc5666051c367efa1692f4 with: webhook-url: ${{ secrets.DEVTOOLS_DISCORD_WEBHOOK_URL }} embed-author-name: ${{ github.event.pull_request.user.login }} embed-author-url: ${{ github.event.pull_request.user.html_url }} embed-author-icon-url: ${{ github.event.pull_request.user.avatar_url }} embed-title: '#${{ github.event.number }} (+${{github.event.pull_request.additions}} -${{github.event.pull_request.deletions}}): ${{ github.event.pull_request.title }}' embed-description: ${{ github.event.pull_request.body }} embed-url: ${{ github.event.pull_request.html_url }} ================================================ FILE: .github/workflows/devtools_regression_tests.yml ================================================ name: (DevTools) Regression Tests on: schedule: - cron: 0 0 * * * workflow_dispatch: inputs: commit_sha: required: false type: string permissions: {} env: TZ: /usr/share/zoneinfo/America/Los_Angeles # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1 jobs: download_build: name: Download base build runs-on: ubuntu-latest permissions: # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run actions: read steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 id: node_modules with: path: | **/node_modules key: runtime-release-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }} - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: yarn --cwd scripts/release install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Download react-devtools artifacts for base revision run: | git fetch origin main GH_TOKEN=${{ github.token }} scripts/release/download-experimental-build.js --commit=${{ inputs.commit_sha || '$(git rev-parse origin/main)' }} - name: Display structure of build run: ls -R build - name: Archive build uses: actions/upload-artifact@v4 with: name: build path: build if-no-files-found: error build_devtools_and_process_artifacts: name: Build DevTools and process artifacts needs: download_build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 id: node_modules with: path: | **/node_modules key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Restore archived build uses: actions/download-artifact@v4 with: name: build path: build - run: ./scripts/ci/pack_and_store_devtools_artifacts.sh env: RELEASE_CHANNEL: experimental - name: Display structure of build run: ls -R build - name: Archive devtools build uses: actions/upload-artifact@v4 with: name: react-devtools path: build/devtools if-no-files-found: error # Simplifies getting the extension for local testing - name: Archive chrome extension uses: actions/upload-artifact@v4 with: name: react-devtools-chrome-extension path: build/devtools/chrome-extension.zip if-no-files-found: error - name: Archive firefox extension uses: actions/upload-artifact@v4 with: name: react-devtools-firefox-extension path: build/devtools/firefox-extension.zip if-no-files-found: error run_devtools_tests_for_versions: name: Run DevTools tests for versions needs: build_devtools_and_process_artifacts runs-on: ubuntu-latest strategy: fail-fast: false matrix: version: - "16.0" - "16.5" # schedule package - "16.8" # hooks - "17.0" - "18.0" - "18.2" # compiler polyfill steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 id: node_modules with: path: | **/node_modules key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Restore all archived build artifacts uses: actions/download-artifact@v4 - name: Display structure of build run: ls -R build - run: ./scripts/ci/download_devtools_regression_build.js ${{ matrix.version }} --replaceBuild - run: node ./scripts/jest/jest-cli.js --build --project devtools --release-channel=experimental --reactVersion ${{ matrix.version }} --ci run_devtools_e2e_tests_for_versions: name: Run DevTools e2e tests for versions needs: build_devtools_and_process_artifacts runs-on: ubuntu-latest strategy: fail-fast: false matrix: version: - "16.0" - "16.5" # schedule package - "16.8" # hooks - "17.0" - "18.0" steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 id: node_modules with: path: | **/node_modules key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Restore all archived build artifacts uses: actions/download-artifact@v4 - name: Display structure of build run: ls -R build - name: Check Playwright version id: playwright_version run: echo "playwright_version=$(npm ls @playwright/test | grep @playwright | sed 's/.*@//' | head -1)" >> "$GITHUB_OUTPUT" - name: Cache Playwright Browsers for version ${{ steps.playwright_version.outputs.playwright_version }} id: cache_playwright_browsers uses: actions/cache@v4 with: path: ~/.cache/ms-playwright key: playwright-browsers-v6-${{ runner.arch }}-${{ runner.os }}-${{ steps.playwright_version.outputs.playwright_version }} - run: npx playwright install --with-deps if: steps.cache_playwright_browsers.outputs.cache-hit != 'true' - run: npx playwright install-deps if: steps.cache_playwright_browsers.outputs.cache-hit == 'true' - run: ./scripts/ci/download_devtools_regression_build.js ${{ matrix.version }} - run: ls -R build-regression - run: ./scripts/ci/run_devtools_e2e_tests.js ${{ matrix.version }} env: RELEASE_CHANNEL: experimental - name: Cleanup build regression folder run: rm -r ./build-regression - uses: actions/upload-artifact@v4 with: name: screenshots path: ./tmp/playwright-artifacts if-no-files-found: warn ================================================ FILE: .github/workflows/runtime_build_and_test.yml ================================================ name: (Runtime) Build and Test on: push: branches: [main] tags: # To get CI for backport releases. # This will duplicate CI for releases from main which is acceptable - "v*" pull_request: paths-ignore: - compiler/** workflow_dispatch: inputs: commit_sha: required: false type: string default: '' permissions: {} concurrency: group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.run_id }} cancel-in-progress: true env: TZ: /usr/share/zoneinfo/America/Los_Angeles # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1 jobs: # ----- NODE_MODULES CACHE ----- # Centralize the node_modules cache so it is saved once and each subsequent job only needs to # restore the cache. Prevents race conditions where multiple workflows try to write to the cache. runtime_node_modules_cache: name: Cache Runtime node_modules runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: 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 with: path: | **/node_modules key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} lookup-only: true - uses: actions/setup-node@v4 if: steps.node_modules.outputs.cache-hit != 'true' with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: yarn.lock - name: Warm with old cache if: steps.node_modules.outputs.cache-hit != 'true' uses: actions/cache/restore@v4 with: path: | **/node_modules key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} # Don't use restore-keys here. Otherwise the cache grows indefinitely. - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Save cache if: steps.node_modules.outputs.cache-hit != 'true' uses: actions/cache/save@v4 with: path: | **/node_modules key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} runtime_compiler_node_modules_cache: name: Cache Runtime, Compiler node_modules runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: 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 with: path: | **/node_modules key: runtime-and-compiler-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }} lookup-only: true - uses: actions/setup-node@v4 if: steps.node_modules.outputs.cache-hit != 'true' with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: | yarn.lock compiler/yarn.lock - name: Warm with old cache if: steps.node_modules.outputs.cache-hit != 'true' uses: actions/cache/restore@v4 with: path: | **/node_modules key: runtime-and-compiler-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }} # Don't use restore-keys here. Otherwise the cache grows indefinitely. - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: yarn --cwd compiler install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Save cache if: steps.node_modules.outputs.cache-hit != 'true' uses: actions/cache/save@v4 with: path: | **/node_modules key: runtime-and-compiler-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }} # ----- FLOW ----- discover_flow_inline_configs: name: Discover flow inline configs runs-on: ubuntu-latest outputs: matrix: ${{ steps.set-matrix.outputs.result }} steps: - uses: actions/checkout@v4 with: 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: script: | const inlinedHostConfigs = require('./scripts/shared/inlinedHostConfigs.js'); return inlinedHostConfigs.map(config => config.shortName); flow: name: Flow check ${{ matrix.flow_inline_config_shortname }} needs: [discover_flow_inline_configs, runtime_node_modules_cache] runs-on: ubuntu-latest strategy: fail-fast: false matrix: flow_inline_config_shortname: ${{ fromJSON(needs.discover_flow_inline_configs.outputs.matrix) }} steps: - uses: actions/checkout@v4 with: 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' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache/restore@v4 id: node_modules with: path: | **/node_modules key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} # Don't use restore-keys here. Otherwise the cache grows indefinitely. - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: node ./scripts/tasks/flow-ci ${{ matrix.flow_inline_config_shortname }} # ----- FIZZ ----- check_generated_fizz_runtime: name: Confirm generated inline Fizz runtime is up to date needs: [runtime_node_modules_cache] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: 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' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache/restore@v4 id: node_modules with: path: | **/node_modules key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} # Don't use restore-keys here. Otherwise the cache grows indefinitely. - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: | yarn generate-inline-fizz-runtime git diff --exit-code || (echo "There was a change to the Fizz runtime. Run \`yarn generate-inline-fizz-runtime\` and check in the result." && false) # ----- FEATURE FLAGS ----- flags: name: Check flags needs: [runtime_node_modules_cache] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: 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' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache/restore@v4 id: node_modules with: path: | **/node_modules key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: yarn flags # ----- TESTS ----- test: name: yarn test ${{ matrix.params }} (Shard ${{ matrix.shard }}) needs: [runtime_compiler_node_modules_cache] runs-on: ubuntu-latest strategy: fail-fast: false matrix: params: - "-r=stable --env=development" - "-r=stable --env=production" - "-r=experimental --env=development" - "-r=experimental --env=production" - "-r=www-classic --env=development --variant=false" - "-r=www-classic --env=production --variant=false" - "-r=www-classic --env=development --variant=true" - "-r=www-classic --env=production --variant=true" - "-r=www-modern --env=development --variant=false" - "-r=www-modern --env=production --variant=false" - "-r=www-modern --env=development --variant=true" - "-r=www-modern --env=production --variant=true" - "-r=xplat --env=development --variant=false" - "-r=xplat --env=development --variant=true" - "-r=xplat --env=production --variant=false" - "-r=xplat --env=production --variant=true" # TODO: Test more persistent configurations? - "-r=stable --env=development --persistent" - "-r=experimental --env=development --persistent" shard: - 1/5 - 2/5 - 3/5 - 4/5 - 5/5 steps: - uses: actions/checkout@v4 with: 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' cache: yarn cache-dependency-path: | yarn.lock compiler/yarn.lock - name: Restore cached node_modules uses: actions/cache/restore@v4 id: node_modules with: path: | **/node_modules key: runtime-and-compiler-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }} # Don't use restore-keys here. Otherwise the cache grows indefinitely. - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: yarn --cwd compiler install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: node --version - run: yarn test ${{ matrix.params }} --ci --shard=${{ matrix.shard }} # Hardcoded to improve parallelism test-linter: name: Test eslint-plugin-react-hooks needs: [runtime_compiler_node_modules_cache] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: | yarn.lock compiler/yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 id: node_modules with: path: | **/node_modules key: runtime-and-compiler-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }} - name: Install runtime dependencies run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Install compiler dependencies run: yarn install --frozen-lockfile working-directory: compiler if: steps.node_modules.outputs.cache-hit != 'true' - run: ./scripts/react-compiler/build-compiler.sh && ./scripts/react-compiler/link-compiler.sh - run: yarn workspace eslint-plugin-react-hooks test # ----- BUILD ----- build_and_lint: name: yarn build and lint needs: [runtime_compiler_node_modules_cache] runs-on: ubuntu-latest strategy: fail-fast: false matrix: # yml is dumb. update the --total arg to yarn build if you change the number of workers worker_id: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24] release_channel: [stable, experimental] steps: - uses: actions/checkout@v4 with: 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' cache: yarn cache-dependency-path: | yarn.lock compiler/yarn.lock - uses: actions/setup-java@v4 with: distribution: temurin java-version: 11.0.22 - name: Restore cached node_modules uses: actions/cache/restore@v4 id: node_modules with: path: | **/node_modules key: runtime-and-compiler-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }} # Don't use restore-keys here. Otherwise the cache grows indefinitely. - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: yarn --cwd compiler install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: yarn build --index=${{ matrix.worker_id }} --total=25 --r=${{ matrix.release_channel }} --ci env: CI: github RELEASE_CHANNEL: ${{ matrix.release_channel }} NODE_INDEX: ${{ matrix.worker_id }} - name: Lint build run: yarn lint-build - name: Display structure of build run: ls -R build - name: Archive build uses: actions/upload-artifact@v4 with: name: _build_${{ matrix.worker_id }}_${{ matrix.release_channel }} path: build if-no-files-found: error test_build: name: yarn test-build needs: [build_and_lint, runtime_compiler_node_modules_cache] strategy: fail-fast: false matrix: test_params: [ # Intentionally passing these as strings instead of creating a # separate parameter per CLI argument, since it's easier to # control/see which combinations we want to run. -r=stable --env=development, -r=stable --env=production, -r=experimental --env=development, -r=experimental --env=production, # TODO: Update test config to support www build tests # - "-r=www-classic --env=development --variant=false" # - "-r=www-classic --env=production --variant=false" # - "-r=www-classic --env=development --variant=true" # - "-r=www-classic --env=production --variant=true" # - "-r=www-modern --env=development --variant=false" # - "-r=www-modern --env=production --variant=false" # - "-r=www-modern --env=development --variant=true" # - "-r=www-modern --env=production --variant=true" # TODO: Update test config to support xplat build tests # - "-r=xplat --env=development --variant=false" # - "-r=xplat --env=development --variant=true" # - "-r=xplat --env=production --variant=false" # - "-r=xplat --env=production --variant=true" # TODO: Test more persistent configurations? ] shard: - 1/10 - 2/10 - 3/10 - 4/10 - 5/10 - 6/10 - 7/10 - 8/10 - 9/10 - 10/10 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: 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' cache: yarn cache-dependency-path: | yarn.lock compiler/yarn.lock - name: Restore cached node_modules uses: actions/cache/restore@v4 id: node_modules with: path: | **/node_modules key: runtime-and-compiler-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }} # Don't use restore-keys here. Otherwise the cache grows indefinitely. - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: yarn --cwd compiler install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Restore archived build uses: actions/download-artifact@v4 with: pattern: _build_* path: build merge-multiple: true - name: Display structure of build run: ls -R build - run: node --version - run: yarn test --build ${{ matrix.test_params }} --shard=${{ matrix.shard }} --ci test_build_devtools: name: yarn test-build (devtools) needs: [build_and_lint, runtime_node_modules_cache] strategy: fail-fast: false matrix: shard: - 1/5 - 2/5 - 3/5 - 4/5 - 5/5 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: 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' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache/restore@v4 id: node_modules with: path: | **/node_modules key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} # Don't use restore-keys here. Otherwise the cache grows indefinitely. - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Restore archived build uses: actions/download-artifact@v4 with: pattern: _build_* path: build merge-multiple: true - name: Display structure of build run: ls -R build - run: node --version - run: yarn test --build --project=devtools -r=experimental --shard=${{ matrix.shard }} --ci process_artifacts_combined: name: Process artifacts combined needs: [build_and_lint, runtime_node_modules_cache] permissions: # https://github.com/actions/attest-build-provenance id-token: write attestations: write runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: 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' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache/restore@v4 id: node_modules with: path: | **/node_modules key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} # Don't use restore-keys here. Otherwise the cache grows indefinitely. - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Restore archived build uses: actions/download-artifact@v4 with: pattern: _build_* path: build merge-multiple: true - name: Display structure of build run: ls -R build - 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__ node ./scripts/print-warnings/print-warnings.js > build/__test_utils__/ReactAllWarnings.js # Compress build directory into a single tarball for easy download - run: tar -zcvf ./build.tgz ./build # TODO: Migrate scripts to use `build` directory instead of `build2` - run: cp ./build.tgz ./build2.tgz - name: Archive build artifacts id: upload_artifacts_combined uses: actions/upload-artifact@v4 with: name: artifacts_combined path: | ./build.tgz ./build2.tgz if-no-files-found: error - uses: actions/attest-build-provenance@v2 # We don't verify builds generated from pull requests not originating from facebook/react. # However, if the PR lands, the run on `main` will generate the attestation which can then # be used to download a build via scripts/release/download-experimental-build.js. # # Note that this means that scripts/release/download-experimental-build.js must be run with # --no-verify when downloading a build from a fork. if: github.event_name == 'push' && github.ref_name == 'main' || github.event.pull_request.head.repo.full_name == github.repository with: subject-name: artifacts_combined.zip subject-digest: sha256:${{ steps.upload_artifacts_combined.outputs.artifact-digest }} check_error_codes: name: Search build artifacts for unminified errors needs: [build_and_lint, runtime_node_modules_cache] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: 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' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache/restore@v4 id: node_modules with: path: | **/node_modules key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} # Don't use restore-keys here. Otherwise the cache grows indefinitely. - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Restore archived build uses: actions/download-artifact@v4 with: pattern: _build_* path: build merge-multiple: true - name: Display structure of build run: ls -R build - name: Search build artifacts for unminified errors run: | yarn extract-errors git diff --exit-code || (echo "Found unminified errors. Either update the error codes map or disable error minification for the affected build, if appropriate." && false) check_release_dependencies: name: Check release dependencies needs: [build_and_lint, runtime_node_modules_cache] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: 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' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache/restore@v4 id: node_modules with: path: | **/node_modules key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} # Don't use restore-keys here. Otherwise the cache grows indefinitely. - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Restore archived build uses: actions/download-artifact@v4 with: pattern: _build_* path: build merge-multiple: true - name: Display structure of build run: ls -R build - run: yarn check-release-dependencies RELEASE_CHANNEL_stable_yarn_test_dom_fixtures: name: Check fixtures DOM (stable) needs: build_and_lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: 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' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 # note: this does not reuse centralized cache since it has unique cache key id: node_modules with: path: | **/node_modules key: fixtures_dom-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'fixtures/dom/yarn.lock') }} - name: Ensure clean build directory run: rm -rf build - run: yarn --cwd fixtures/dom install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Restore archived build uses: actions/download-artifact@v4 with: pattern: _build_* path: build merge-multiple: true - name: Display structure of build run: ls -R build - name: Run DOM fixture tests run: | yarn predev yarn test working-directory: fixtures/dom env: RELEASE_CHANNEL: stable # ----- FLIGHT ----- run_fixtures_flight_tests: name: Run fixtures Flight tests needs: build_and_lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: 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' cache: yarn cache-dependency-path: yarn.lock # Fixture copies some built packages from the workroot after install. # That means dependencies of the built packages are not installed. # We need to install dependencies of the workroot to fulfill all dependency constraints - name: Restore cached node_modules uses: actions/cache@v4 # note: this does not reuse centralized cache since it has unique cache key id: node_modules with: path: | **/node_modules key: fixtures_flight-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'fixtures/flight/yarn.lock') }} - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: yarn --cwd fixtures/flight install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Check Playwright version id: playwright_version run: echo "playwright_version=$(npm ls @playwright/test | grep @playwright | sed 's/.*@//' | head -1)" >> "$GITHUB_OUTPUT" - name: Cache Playwright Browsers for version ${{ steps.playwright_version.outputs.playwright_version }} id: cache_playwright_browsers uses: actions/cache@v4 with: path: ~/.cache/ms-playwright key: playwright-browsers-v6-${{ runner.arch }}-${{ runner.os }}-${{ steps.playwright_version.outputs.playwright_version }} - name: Playwright install deps if: steps.cache_playwright_browsers.outputs.cache-hit != 'true' working-directory: fixtures/flight run: npx playwright install --with-deps chromium - name: Restore archived build uses: actions/download-artifact@v4 with: pattern: _build_* path: build merge-multiple: true - name: Display structure of build run: ls -R build - name: Run tests working-directory: fixtures/flight run: yarn test env: # Otherwise the webserver is a blackbox DEBUG: pw:webserver - name: Archive Flight fixture artifacts uses: actions/upload-artifact@v4 with: name: flight-playwright-report path: fixtures/flight/playwright-report if-no-files-found: warn - name: Archive Flight fixture artifacts uses: actions/upload-artifact@v4 with: name: flight-test-results path: fixtures/flight/test-results if-no-files-found: ignore # ----- DEVTOOLS ----- build_devtools_and_process_artifacts: name: Build DevTools and process artifacts needs: [build_and_lint, runtime_node_modules_cache] runs-on: ubuntu-latest strategy: fail-fast: false matrix: browser: [chrome, firefox, edge] steps: - uses: actions/checkout@v4 with: 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' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache/restore@v4 id: node_modules with: path: | **/node_modules key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} # Don't use restore-keys here. Otherwise the cache grows indefinitely. - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Restore archived build uses: actions/download-artifact@v4 with: pattern: _build_* path: build merge-multiple: true - run: ./scripts/ci/pack_and_store_devtools_artifacts.sh ${{ matrix.browser }} env: RELEASE_CHANNEL: experimental - name: Display structure of build run: ls -R build # Simplifies getting the extension for local testing - name: Archive ${{ matrix.browser }} extension uses: actions/upload-artifact@v4 with: name: react-devtools-${{ matrix.browser }}-extension path: build/devtools/${{ matrix.browser }}-extension.zip if-no-files-found: error - name: Archive ${{ matrix.browser }} metadata uses: actions/upload-artifact@v4 with: name: react-devtools-${{ matrix.browser }}-metadata path: build/devtools/webpack-stats.*.json merge_devtools_artifacts: name: Merge DevTools artifacts needs: build_devtools_and_process_artifacts runs-on: ubuntu-latest steps: - name: Merge artifacts uses: actions/upload-artifact/merge@v4 with: name: react-devtools pattern: react-devtools-* run_devtools_e2e_tests: name: Run DevTools e2e tests needs: [build_and_lint, runtime_node_modules_cache] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: 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' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache/restore@v4 id: node_modules with: path: | **/node_modules key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} # Don't use restore-keys here. Otherwise the cache grows indefinitely. - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Restore archived build uses: actions/download-artifact@v4 with: pattern: _build_* path: build merge-multiple: true - name: Check Playwright version id: playwright_version run: echo "playwright_version=$(npm ls @playwright/test | grep @playwright | sed 's/.*@//' | head -1)" >> "$GITHUB_OUTPUT" - name: Cache Playwright Browsers for version ${{ steps.playwright_version.outputs.playwright_version }} id: cache_playwright_browsers uses: actions/cache@v4 with: path: ~/.cache/ms-playwright key: playwright-browsers-v6-${{ runner.arch }}-${{ runner.os }}-${{ steps.playwright_version.outputs.playwright_version }} - name: Playwright install deps if: steps.cache_playwright_browsers.outputs.cache-hit != 'true' run: npx playwright install --with-deps chromium - run: ./scripts/ci/run_devtools_e2e_tests.js env: RELEASE_CHANNEL: experimental - name: Archive Playwright report uses: actions/upload-artifact@v4 with: name: devtools-playwright-artifacts path: tmp/playwright-artifacts if-no-files-found: warn # ----- SIZEBOT ----- sizebot: if: ${{ github.event_name == 'pull_request' && github.ref_name != 'main' && github.event.pull_request.base.ref == 'main' }} name: Run sizebot needs: [build_and_lint] permissions: # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run actions: read runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: 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' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 # note: this does not reuse centralized cache since it has unique cache key id: node_modules with: path: | **/node_modules key: runtime-release-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }} - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: yarn --cwd scripts/release install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Download artifacts for base revision # The build could have been generated from a fork, so we must download the build without # any verification. This is safe since we only use this for sizebot calculation and the # unverified artifact is not used. Additionally this workflow runs in the pull_request # trigger so only restricted permissions are available. run: | GH_TOKEN=${{ github.token }} scripts/release/download-experimental-build.js --commit=$(git rev-parse ${{ github.event.pull_request.base.sha }}) ${{ (github.event.pull_request.head.repo.full_name != github.repository && '--noVerify') || ''}} mv ./build ./base-build - name: Delete extraneous files # TODO: The `download-experimental-build` script copies the npm # packages into the `node_modules` directory. This is a historical # quirk of how the release script works. Let's pretend they # don't exist. run: rm -rf ./base-build/node_modules - name: Display structure of base-build from origin/main run: ls -R base-build - name: Ensure clean build directory run: rm -rf build - name: Restore archived build for PR uses: actions/download-artifact@v4 with: pattern: _build_* path: build merge-multiple: true - name: Scrape warning messages run: | mkdir -p ./build/__test_utils__ 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.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 with: name: sizebot-message path: sizebot-message.md if-no-files-found: ignore ================================================ FILE: .github/workflows/runtime_commit_artifacts.yml ================================================ name: (Runtime) Commit Artifacts for Meta WWW and fbsource V2 on: workflow_run: workflows: ["(Runtime) Build and Test"] types: [completed] branches: - main workflow_dispatch: inputs: commit_sha: required: false type: string force: description: 'Force a commit to the builds/... branches' required: true default: false type: boolean dry_run: description: Perform a dry run (run everything except push) required: true default: false type: boolean permissions: {} env: TZ: /usr/share/zoneinfo/America/Los_Angeles # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1 jobs: download_artifacts: runs-on: ubuntu-latest permissions: # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run actions: read steps: - uses: actions/checkout@v4 - name: Restore cached node_modules uses: actions/cache@v4 id: node_modules with: path: | **/node_modules key: runtime-release-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }} - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: yarn --cwd scripts/release install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Download artifacts for base revision run: | GH_TOKEN=${{ github.token }} scripts/release/download-experimental-build.js --commit=${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} - name: Display structure of build run: ls -R build - name: Archive build uses: actions/upload-artifact@v4 with: name: build path: build/ if-no-files-found: error process_artifacts: runs-on: ubuntu-latest needs: [download_artifacts] outputs: www_branch_count: ${{ steps.check_branches.outputs.www_branch_count }} fbsource_branch_count: ${{ steps.check_branches.outputs.fbsource_branch_count }} last_version_classic: ${{ steps.get_last_version_www.outputs.last_version_classic }} last_version_modern: ${{ steps.get_last_version_www.outputs.last_version_modern }} last_version_rn: ${{ steps.get_last_version_rn.outputs.last_version_rn }} current_version_classic: ${{ steps.get_current_version.outputs.current_version_classic }} current_version_modern: ${{ steps.get_current_version.outputs.current_version_modern }} current_version_rn: ${{ steps.get_current_version.outputs.current_version_rn }} steps: - uses: actions/checkout@v4 with: ref: builds/facebook-www - name: "Get last version string for www" id: get_last_version_www run: | # Empty checks only needed for backwards compatibility,can remove later. VERSION_CLASSIC=$( [ -f ./compiled/facebook-www/VERSION_CLASSIC ] && cat ./compiled/facebook-www/VERSION_CLASSIC || echo '' ) VERSION_MODERN=$( [ -f ./compiled/facebook-www/VERSION_MODERN ] && cat ./compiled/facebook-www/VERSION_MODERN || echo '' ) echo "Last classic version is $VERSION_CLASSIC" echo "Last modern version is $VERSION_MODERN" echo "last_version_classic=$VERSION_CLASSIC" >> "$GITHUB_OUTPUT" echo "last_version_modern=$VERSION_MODERN" >> "$GITHUB_OUTPUT" - uses: actions/checkout@v4 with: ref: builds/facebook-fbsource - name: "Get last version string for rn" id: get_last_version_rn run: | # Empty checks only needed for backwards compatibility,can remove later. VERSION_NATIVE_FB=$( [ -f ./compiled-rn/VERSION_NATIVE_FB ] && cat ./compiled-rn/VERSION_NATIVE_FB || echo '' ) echo "Last rn version is $VERSION_NATIVE_FB" echo "last_version_rn=$VERSION_NATIVE_FB" >> "$GITHUB_OUTPUT" - uses: actions/checkout@v4 - name: "Check branches" id: check_branches run: | echo "www_branch_count=$(git ls-remote --heads origin "refs/heads/meta-www" | wc -l)" >> "$GITHUB_OUTPUT" echo "fbsource_branch_count=$(git ls-remote --heads origin "refs/heads/meta-fbsource" | wc -l)" >> "$GITHUB_OUTPUT" - name: Restore downloaded build uses: actions/download-artifact@v4 with: name: build path: build - name: Display structure of build run: ls -R build - name: Strip @license from eslint plugin and react-refresh run: | sed -i -e 's/ @license React*//' \ build/oss-experimental/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js \ build/facebook-www/ESLintPluginReactHooks-dev.modern.js \ build/oss-experimental/react-refresh/cjs/react-refresh-babel.development.js - name: Insert @headers into eslint plugin and react-refresh run: | sed -i -e 's/ LICENSE file in the root directory of this source tree./ LICENSE file in the root directory of this source tree.\n *\n * @noformat\n * @nolint\n * @lightSyntaxTransform\n * @preventMunge\n * @oncall react_core/' \ build/oss-experimental/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js \ build/facebook-www/ESLintPluginReactHooks-dev.modern.js \ build/oss-experimental/react-refresh/cjs/react-refresh-babel.development.js - name: Move relevant files for React in www into compiled run: | # Move the facebook-www folder into compiled mkdir ./compiled mv build/facebook-www ./compiled # Move ReactAllWarnings.js to facebook-www mkdir ./compiled/facebook-www/__test_utils__ mv build/__test_utils__/ReactAllWarnings.js ./compiled/facebook-www/__test_utils__/ReactAllWarnings.js # Copy eslint-plugin-react-hooks (www build with feature flags) mkdir ./compiled/eslint-plugin-react-hooks cp ./compiled/facebook-www/ESLintPluginReactHooks-dev.modern.js \ ./compiled/eslint-plugin-react-hooks/index.js # Move unstable_server-external-runtime.js into facebook-www mv build/oss-experimental/react-dom/unstable_server-external-runtime.js \ ./compiled/facebook-www/unstable_server-external-runtime.js # Move react-refresh-babel.development.js into babel-plugin-react-refresh mkdir ./compiled/babel-plugin-react-refresh mv build/oss-experimental/react-refresh/cjs/react-refresh-babel.development.js \ ./compiled/babel-plugin-react-refresh/index.js ls -R ./compiled - name: Move relevant files for React in fbsource into compiled-rn run: | BASE_FOLDER='compiled-rn/facebook-fbsource/xplat/js' mkdir -p ${BASE_FOLDER}/react-native-github/Libraries/Renderer/ mkdir -p ${BASE_FOLDER}/RKJSModules/vendor/react/{scheduler,react,react-dom,react-is,react-test-renderer}/ # Move React Native renderer mv build/react-native/implementations/ $BASE_FOLDER/react-native-github/Libraries/Renderer/ mv build/react-native/shims/ $BASE_FOLDER/react-native-github/Libraries/Renderer/ mv build/facebook-react-native/scheduler/cjs/ $BASE_FOLDER/RKJSModules/vendor/react/scheduler/ mv build/facebook-react-native/react/cjs/ $BASE_FOLDER/RKJSModules/vendor/react/react/ mv build/facebook-react-native/react-dom/cjs/ $BASE_FOLDER/RKJSModules/vendor/react/react-dom/ mv build/facebook-react-native/react-is/cjs/ $BASE_FOLDER/RKJSModules/vendor/react/react-is/ mv build/facebook-react-native/react-test-renderer/cjs/ $BASE_FOLDER/RKJSModules/vendor/react/react-test-renderer/ # Delete the OSS renderers, these are sync'd to RN separately. RENDERER_FOLDER=$BASE_FOLDER/react-native-github/Libraries/Renderer/implementations/ rm $RENDERER_FOLDER/ReactFabric-{dev,prod,profiling}.js # Delete the legacy renderer shim, this is not sync'd and will get deleted in the future. SHIM_FOLDER=$BASE_FOLDER/react-native-github/Libraries/Renderer/shims/ rm $SHIM_FOLDER/ReactNative.js # Copy eslint-plugin-react-hooks # NOTE: This is different from www, here we include the full package # including package.json to include dependencies in fbsource. mkdir "$BASE_FOLDER/tools" cp -r build/oss-experimental/eslint-plugin-react-hooks "$BASE_FOLDER/tools" # Move React Native version file mv build/facebook-react-native/VERSION_NATIVE_FB ./compiled-rn/VERSION_NATIVE_FB ls -R ./compiled-rn - name: Add REVISION files run: | echo ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} >> ./compiled/facebook-www/REVISION cp ./compiled/facebook-www/REVISION ./compiled/facebook-www/REVISION_TRANSFORMS echo ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} >> ./compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/REVISION - name: "Get current version string" id: get_current_version run: | VERSION_CLASSIC=$(cat ./compiled/facebook-www/VERSION_CLASSIC) VERSION_MODERN=$(cat ./compiled/facebook-www/VERSION_MODERN) VERSION_NATIVE_FB=$(cat ./compiled-rn/VERSION_NATIVE_FB) echo "Current classic version is $VERSION_CLASSIC" echo "Current modern version is $VERSION_MODERN" echo "Current rn version is $VERSION_NATIVE_FB" echo "current_version_classic=$VERSION_CLASSIC" >> "$GITHUB_OUTPUT" echo "current_version_modern=$VERSION_MODERN" >> "$GITHUB_OUTPUT" echo "current_version_rn=$VERSION_NATIVE_FB" >> "$GITHUB_OUTPUT" - uses: actions/upload-artifact@v4 with: name: compiled path: compiled/ if-no-files-found: error - uses: actions/upload-artifact@v4 with: name: compiled-rn path: compiled-rn/ if-no-files-found: error commit_www_artifacts: needs: [download_artifacts, process_artifacts] if: inputs.force == true || (github.ref == 'refs/heads/main' && needs.process_artifacts.outputs.www_branch_count == '0') runs-on: ubuntu-latest permissions: # Used to push a commit to builds/facebook-www contents: write steps: - uses: actions/checkout@v4 with: ref: builds/facebook-www - name: Ensure clean directory run: rm -rf compiled - uses: actions/download-artifact@v4 with: name: compiled path: compiled/ - name: Revert version changes if: needs.process_artifacts.outputs.last_version_classic != '' && needs.process_artifacts.outputs.last_version_modern != '' env: CURRENT_VERSION_CLASSIC: ${{ needs.process_artifacts.outputs.current_version_classic }} CURRENT_VERSION_MODERN: ${{ needs.process_artifacts.outputs.current_version_modern }} LAST_VERSION_CLASSIC: ${{ needs.process_artifacts.outputs.last_version_classic }} LAST_VERSION_MODERN: ${{ needs.process_artifacts.outputs.last_version_modern }} run: | echo "Reverting $CURRENT_VERSION_CLASSIC to $LAST_VERSION_CLASSIC" grep -rl "$CURRENT_VERSION_CLASSIC" ./compiled || echo "No files found with $CURRENT_VERSION_CLASSIC" grep -rl "$CURRENT_VERSION_CLASSIC" ./compiled | xargs -r sed -i -e "s/$CURRENT_VERSION_CLASSIC/$LAST_VERSION_CLASSIC/g" grep -rl "$CURRENT_VERSION_CLASSIC" ./compiled || echo "Classic version reverted" echo "====================" echo "Reverting $CURRENT_VERSION_MODERN to $LAST_VERSION_MODERN" grep -rl "$CURRENT_VERSION_MODERN" ./compiled || echo "No files found with $CURRENT_VERSION_MODERN" grep -rl "$CURRENT_VERSION_MODERN" ./compiled | xargs -r sed -i -e "s/$CURRENT_VERSION_MODERN/$LAST_VERSION_MODERN/g" grep -rl "$CURRENT_VERSION_MODERN" ./compiled || echo "Modern version reverted" - name: Check for changes if: inputs.force != true id: check_should_commit run: | echo "Full git status" git add . git status echo "====================" if git status --porcelain | grep -qv '/REVISION'; then echo "Changes detected" echo "===== Changes =====" git --no-pager diff -U0 | grep '^[+-]' | head -n 50 echo "===================" echo "should_commit=true" >> "$GITHUB_OUTPUT" else echo "No Changes detected" echo "should_commit=false" >> "$GITHUB_OUTPUT" fi - name: Re-apply version changes if: inputs.force == true || (steps.check_should_commit.outputs.should_commit == 'true' && needs.process_artifacts.outputs.last_version_classic != '' && needs.process_artifacts.outputs.last_version_modern != '') env: CURRENT_VERSION_CLASSIC: ${{ needs.process_artifacts.outputs.current_version_classic }} CURRENT_VERSION_MODERN: ${{ needs.process_artifacts.outputs.current_version_modern }} LAST_VERSION_CLASSIC: ${{ needs.process_artifacts.outputs.last_version_classic }} LAST_VERSION_MODERN: ${{ needs.process_artifacts.outputs.last_version_modern }} run: | echo "Re-applying $LAST_VERSION_CLASSIC to $CURRENT_VERSION_CLASSIC" grep -rl "$LAST_VERSION_CLASSIC" ./compiled || echo "No files found with $LAST_VERSION_CLASSIC" grep -rl "$LAST_VERSION_CLASSIC" ./compiled | xargs -r sed -i -e "s/$LAST_VERSION_CLASSIC/$CURRENT_VERSION_CLASSIC/g" grep -rl "$LAST_VERSION_CLASSIC" ./compiled || echo "Classic version re-applied" echo "====================" echo "Re-applying $LAST_VERSION_MODERN to $CURRENT_VERSION_MODERN" grep -rl "$LAST_VERSION_MODERN" ./compiled || echo "No files found with $LAST_VERSION_MODERN" grep -rl "$LAST_VERSION_MODERN" ./compiled | xargs -r sed -i -e "s/$LAST_VERSION_MODERN/$CURRENT_VERSION_MODERN/g" grep -rl "$LAST_VERSION_MODERN" ./compiled || echo "Classic version re-applied" - name: Will commit these changes if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true' run: | git add . git status - name: Check commit message if: inputs.dry_run run: | git fetch origin --quiet git show ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} --no-patch --pretty=format:"%B" - name: Commit changes to branch if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true' run: | git config --global user.email "${{ format('{0}@users.noreply.github.com', github.triggering_actor) }}" git config --global user.name "${{ github.triggering_actor }}" git fetch origin --quiet git commit -m "$(git show ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} --no-patch --pretty=format:'%B%n%nDiffTrain build for [${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }}](https://github.com/facebook/react/commit/${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha}})')" || echo "No changes to commit" - name: Push changes to branch if: inputs.dry_run == false && (inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true') run: git push commit_fbsource_artifacts: needs: [download_artifacts, process_artifacts] permissions: # Used to push a commit to builds/facebook-fbsource contents: write if: inputs.force == true || (github.ref == 'refs/heads/main' && needs.process_artifacts.outputs.fbsource_branch_count == '0') runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: ref: builds/facebook-fbsource - name: Ensure clean directory run: rm -rf compiled-rn - uses: actions/download-artifact@v4 with: name: compiled-rn path: compiled-rn/ - name: Revert version changes if: needs.process_artifacts.outputs.last_version_rn != '' env: CURRENT_VERSION: ${{ needs.process_artifacts.outputs.current_version_rn }} LAST_VERSION: ${{ needs.process_artifacts.outputs.last_version_rn }} run: | echo "Reverting $CURRENT_VERSION to $LAST_VERSION" grep -rl "$CURRENT_VERSION" ./compiled-rn || echo "No files found with $CURRENT_VERSION" grep -rl "$CURRENT_VERSION" ./compiled-rn | xargs -r sed -i -e "s/$CURRENT_VERSION/$LAST_VERSION/g" grep -rl "$CURRENT_VERSION" ./compiled-rn || echo "Version reverted" - name: Check for changes if: inputs.force != 'true' id: check_should_commit run: | echo "Full git status" git add . git --no-pager diff -U0 --cached | grep '^[+-]' | head -n 100 echo "====================" # Ignore REVISION or lines removing @generated headers. if git diff --cached ':(exclude)*REVISION' ':(exclude)*/eslint-plugin-react-hooks/package.json' | grep -vE "^(@@|diff|index|\-\-\-|\+\+\+|\- \* @generated SignedSource)" | grep "^[+-]" > /dev/null; then echo "Changes detected" echo "===== Changes =====" git --no-pager diff --cached ':(exclude)*REVISION' ':(exclude)*/eslint-plugin-react-hooks/package.json' | grep -vE "^(@@|diff|index|\-\-\-|\+\+\+|\- \* @generated SignedSource)" | grep "^[+-]" | head -n 50 echo "===================" echo "should_commit=true" >> "$GITHUB_OUTPUT" else echo "No Changes detected" echo "should_commit=false" >> "$GITHUB_OUTPUT" fi - name: Re-apply version changes if: inputs.force == true || (steps.check_should_commit.outputs.should_commit == 'true' && needs.process_artifacts.outputs.last_version_rn != '') env: CURRENT_VERSION: ${{ needs.process_artifacts.outputs.current_version_rn }} LAST_VERSION: ${{ needs.process_artifacts.outputs.last_version_rn }} run: | echo "Re-applying $LAST_VERSION to $CURRENT_VERSION" grep -rl "$LAST_VERSION" ./compiled-rn || echo "No files found with $LAST_VERSION" grep -rl "$LAST_VERSION" ./compiled-rn | xargs -r sed -i -e "s/$LAST_VERSION/$CURRENT_VERSION/g" grep -rl "$LAST_VERSION" ./compiled-rn || echo "Version re-applied" - name: Add files for signing if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true' run: | echo ":" git add . - name: Signing files if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true' uses: actions/github-script@v7 with: script: | // TODO: Move this to a script file. // We currently can't call scripts from the repo because // at this point in the workflow, we're on the compiled // artifact branch (so the scripts don't exist). // We can fix this with a composite action in the main repo. // This script is duplicated above. const fs = require('fs'); const crypto = require('crypto'); const {execSync} = require('child_process'); // TODO: when we move this to a script, we can use this from npm. // Copy of signedsource since we can't install deps on this branch. const GENERATED = '@' + 'generated'; const NEWTOKEN = '<>'; const PATTERN = new RegExp(`${GENERATED} (?:SignedSource<<([a-f0-9]{32})>>)`); const TokenNotFoundError = new Error( `SignedSource.signFile(...): Cannot sign file without token: ${NEWTOKEN}` ); function hash(data, encoding) { const md5sum = crypto.createHash('md5'); md5sum.update(data, encoding); return md5sum.digest('hex'); } const SignedSource = { getSigningToken() { return `${GENERATED} ${NEWTOKEN}`; }, isSigned(data) { return PATTERN.exec(data) != null; }, signFile(data) { if (!data.includes(NEWTOKEN)) { if (SignedSource.isSigned(data)) { // Signing a file that was previously signed. data = data.replace(PATTERN, SignedSource.getSigningToken()); } else { throw TokenNotFoundError; } } return data.replace(NEWTOKEN, `SignedSource<<${hash(data, 'utf8')}>>`); }, }; const directory = './compiled-rn'; console.log('Signing files in directory:', directory); try { const result = execSync(`git status --porcelain ${directory}`, {encoding: 'utf8'}); console.log(result); // Parse the git status output to get file paths! const files = result.split('\n').filter(file => file.endsWith('.js')); if (files.length === 0) { throw new Error( 'git status returned no files to sign. this job should not have run.' ); } else { files.forEach(line => { let file = null; if (line.startsWith('D ')) { return; } else if (line.startsWith('R ')) { file = line.slice(line.indexOf('->') + 3); } else { file = line.slice(3).trim(); } if (file) { console.log(' Signing file:', file); const originalContents = fs.readFileSync(file, 'utf8'); const signedContents = SignedSource.signFile( originalContents // Need to add the header in, since it's not inserted at build time. .replace(' */\n', ` * ${SignedSource.getSigningToken()}\n */\n`) ); fs.writeFileSync(file, signedContents, 'utf8'); } }); } } catch (e) { process.exitCode = 1; console.error('Error signing files:', e); } - name: Will commit these changes if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true' run: | git add . git status - name: Check commit message if: inputs.dry_run run: | git fetch origin --quiet git show ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} --no-patch --pretty=format:"%B" - name: Commit changes to branch if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true' run: | git config --global user.email "${{ format('{0}@users.noreply.github.com', github.triggering_actor) }}" git config --global user.name "${{ github.triggering_actor }}" git fetch origin --quiet git commit -m "$(git show ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} --no-patch --pretty=format:'%B%n%nDiffTrain build for [${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }}](https://github.com/facebook/react/commit/${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha}})')" || echo "No changes to commit" - name: Push changes to branch if: inputs.dry_run == false && (inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true') run: git push ================================================ FILE: .github/workflows/runtime_discord_notify.yml ================================================ name: (Runtime) Discord Notify on: pull_request_target: types: [opened, ready_for_review] paths-ignore: - packages/react-devtools** - compiler/** - .github/workflows/compiler_**.yml - .github/workflows/devtools**.yml permissions: {} jobs: check_access: if: ${{ github.event.pull_request.draft == false }} runs-on: ubuntu-latest outputs: is_member_or_collaborator: ${{ steps.check_is_member_or_collaborator.outputs.is_member_or_collaborator }} steps: - run: echo ${{ github.event.pull_request.author_association }} - name: Check is member or collaborator id: check_is_member_or_collaborator if: ${{ github.event.pull_request.author_association == 'MEMBER' || github.event.pull_request.author_association == 'COLLABORATOR' }} run: echo "is_member_or_collaborator=true" >> "$GITHUB_OUTPUT" check_maintainer: if: ${{ needs.check_access.outputs.is_member_or_collaborator == 'true' || needs.check_access.outputs.is_member_or_collaborator == true }} needs: [check_access] uses: facebook/react/.github/workflows/shared_check_maintainer.yml@main permissions: # Used by check_maintainer contents: read with: actor: ${{ github.event.pull_request.user.login }} notify: if: ${{ needs.check_maintainer.outputs.is_core_team == 'true' }} needs: check_maintainer runs-on: ubuntu-latest steps: - name: Discord Webhook Action uses: tsickert/discord-webhook@86dc739f3f165f16dadc5666051c367efa1692f4 with: webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }} embed-author-name: ${{ github.event.pull_request.user.login }} embed-author-url: ${{ github.event.pull_request.user.html_url }} embed-author-icon-url: ${{ github.event.pull_request.user.avatar_url }} embed-title: '#${{ github.event.number }} (+${{github.event.pull_request.additions}} -${{github.event.pull_request.deletions}}): ${{ github.event.pull_request.title }}' embed-description: ${{ github.event.pull_request.body }} embed-url: ${{ github.event.pull_request.html_url }} ================================================ FILE: .github/workflows/runtime_eslint_plugin_e2e.yml ================================================ name: (Runtime) ESLint Plugin E2E on: push: branches: [main] pull_request: paths-ignore: - compiler/** permissions: {} concurrency: group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.run_id }} cancel-in-progress: true env: TZ: /usr/share/zoneinfo/America/Los_Angeles jobs: # ----- TESTS ----- test: name: ESLint v${{ matrix.eslint_major }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: eslint_major: - "6" - "7" - "8" - "9" - "10" steps: - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} - uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: | yarn.lock compiler/yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 id: node_modules with: path: | **/node_modules key: runtime-and-compiler-eslint_e2e-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock', 'fixtures/eslint-v*/yarn.lock') }} - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: yarn --cwd compiler install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Install fixture dependencies working-directory: ./fixtures/eslint-v${{ matrix.eslint_major }} run: yarn --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - name: Build plugin working-directory: fixtures/eslint-v${{ matrix.eslint_major }} run: node build.mjs - name: Run lint test working-directory: ./fixtures/eslint-v${{ matrix.eslint_major }} run: yarn lint ================================================ FILE: .github/workflows/runtime_fuzz_tests.yml ================================================ name: (Runtime) Fuzz tests on: schedule: - cron: 0 * * * * push: branches: - main workflow_dispatch: permissions: {} env: TZ: /usr/share/zoneinfo/America/Los_Angeles jobs: test_fuzz: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4.1.0 - uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: 'yarn' - name: Install dependencies run: yarn install --frozen-lockfile env: ELECTRON_SKIP_BINARY_DOWNLOAD: "1" shell: bash - name: Run fuzz tests run: |- FUZZ_TEST_SEED=$RANDOM yarn test fuzz --ci FUZZ_TEST_SEED=$RANDOM yarn test --prod fuzz --ci ================================================ FILE: .github/workflows/runtime_prereleases.yml ================================================ name: (Runtime) Publish Prereleases on: workflow_call: inputs: commit_sha: required: true default: '' type: string release_channel: required: true type: string dist_tag: required: true type: string enableFailureNotification: description: 'Whether to notify the team on Discord when the release fails. Useful if this workflow is called from an automation.' required: false type: boolean only_packages: description: Packages to publish (space separated) type: string skip_packages: description: Packages to NOT publish (space separated) type: string dry: required: true description: Dry run instead of publish? type: boolean default: true secrets: DISCORD_WEBHOOK_URL: description: 'Discord webhook URL to notify on failure. Only required if enableFailureNotification is true.' required: false GH_TOKEN: required: true NPM_TOKEN: required: true permissions: {} env: TZ: /usr/share/zoneinfo/America/Los_Angeles # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1 NPM_TOKEN: ${{ secrets.NPM_TOKEN }} jobs: publish_prerelease: name: Publish prelease (${{ inputs.release_channel }}) ${{ inputs.commit_sha }} @${{ inputs.dist_tag }} runs-on: ubuntu-latest permissions: # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run actions: read steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 id: node_modules with: path: | **/node_modules key: runtime-release-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }} - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: yarn --cwd scripts/release install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: cp ./scripts/release/ci-npmrc ~/.npmrc - run: | GH_TOKEN=${{ secrets.GH_TOKEN }} scripts/release/prepare-release-from-ci.js --skipTests -r ${{ inputs.release_channel }} --commit=${{ inputs.commit_sha }} - name: Check prepared files run: ls -R build/node_modules - if: '${{ inputs.only_packages }}' name: 'Publish ${{ inputs.only_packages }}' run: | scripts/release/publish.js \ --ci \ --tags=${{ inputs.dist_tag }} \ --onlyPackages=${{ inputs.only_packages }} ${{ (inputs.dry && '') || '\'}} ${{ inputs.dry && '--dry' || '' }} - if: '${{ inputs.skip_packages }}' name: 'Publish all packages EXCEPT ${{ inputs.skip_packages }}' run: | scripts/release/publish.js \ --ci \ --tags=${{ inputs.dist_tag }} \ --skipPackages=${{ inputs.skip_packages }} ${{ (inputs.dry && '') || '\'}} ${{ inputs.dry && '--dry' || '' }} - if: '${{ !inputs.skip_packages && !inputs.only_packages }}' name: 'Publish all packages' run: | scripts/release/publish.js \ --ci \ --tags=${{ inputs.dist_tag }} ${{ (inputs.dry && '') || '\'}} ${{ inputs.dry && '--dry' || '' }} - name: Notify Discord on failure if: failure() && inputs.enableFailureNotification == true uses: tsickert/discord-webhook@86dc739f3f165f16dadc5666051c367efa1692f4 with: webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }} embed-author-name: "GitHub Actions" embed-title: '[Runtime] Publish of ${{ inputs.release_channel }}@${{ inputs.dist_tag}} release failed' embed-url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/attempts/${{ github.run_attempt }} ================================================ FILE: .github/workflows/runtime_prereleases_manual.yml ================================================ name: (Runtime) Publish Prereleases Manual on: workflow_dispatch: inputs: prerelease_commit_sha: required: true only_packages: description: Packages to publish (space separated) type: string skip_packages: description: Packages to NOT publish (space separated) type: string dry: required: true description: Dry run instead of publish? type: boolean default: true experimental_only: type: boolean description: Only publish to the experimental tag default: false force_notify: description: Force a Discord notification? type: boolean default: false permissions: {} env: TZ: /usr/share/zoneinfo/America/Los_Angeles jobs: notify: if: ${{ inputs.force_notify || inputs.dry == false || inputs.dry == 'false' }} runs-on: ubuntu-latest steps: - name: Discord Webhook Action uses: tsickert/discord-webhook@86dc739f3f165f16dadc5666051c367efa1692f4 with: webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }} embed-author-name: ${{ github.event.sender.login }} embed-author-url: ${{ github.event.sender.html_url }} embed-author-icon-url: ${{ github.event.sender.avatar_url }} embed-title: "⚠️ Publishing ${{ inputs.experimental_only && 'EXPERIMENTAL' || 'CANARY & EXPERIMENTAL' }} release ${{ (inputs.dry && ' (dry run)') || '' }}" embed-description: | ```json ${{ toJson(inputs) }} ``` embed-url: https://github.com/facebook/react/actions/runs/${{ github.run_id }} publish_prerelease_canary: if: ${{ !inputs.experimental_only }} name: Publish to Canary channel uses: facebook/react/.github/workflows/runtime_prereleases.yml@main permissions: # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run actions: read with: commit_sha: ${{ inputs.prerelease_commit_sha }} release_channel: stable # The tags to use when publishing canaries. The main one we should # always include is "canary" but we can use multiple (e.g. alpha, # beta, rc). To declare multiple, use a comma-separated string, like # this: # dist_tag: "canary,alpha,beta,rc" # # TODO: We currently tag canaries with "next" in addition to "canary" # because this used to be called the "next" channel and some # downstream consumers might still expect that tag. We can remove this # after some time has elapsed and the change has been communicated. dist_tag: canary,next only_packages: ${{ inputs.only_packages }} skip_packages: ${{ inputs.skip_packages }} dry: ${{ inputs.dry }} secrets: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} publish_prerelease_experimental: name: Publish to Experimental channel uses: facebook/react/.github/workflows/runtime_prereleases.yml@main permissions: # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run actions: read # NOTE: Intentionally running these jobs sequentially because npm # will sometimes fail if you try to concurrently publish two # different versions of the same package, even if they use different # dist tags. needs: publish_prerelease_canary # Ensures the job runs even if canary is skipped if: always() with: commit_sha: ${{ inputs.prerelease_commit_sha }} release_channel: experimental dist_tag: experimental only_packages: ${{ inputs.only_packages }} skip_packages: ${{ inputs.skip_packages }} dry: ${{ inputs.dry }} secrets: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} ================================================ FILE: .github/workflows/runtime_prereleases_nightly.yml ================================================ name: (Runtime) Publish Prereleases Nightly on: schedule: # At 10 minutes past 16:00 on Mon, Tue, Wed, Thu, and Fri - cron: 10 16 * * 1,2,3,4,5 permissions: {} env: TZ: /usr/share/zoneinfo/America/Los_Angeles jobs: publish_prerelease_canary: name: Publish to Canary channel uses: facebook/react/.github/workflows/runtime_prereleases.yml@main permissions: # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run actions: read with: commit_sha: ${{ github.sha }} release_channel: stable dist_tag: canary,next enableFailureNotification: true dry: false secrets: DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} publish_prerelease_experimental: name: Publish to Experimental channel uses: facebook/react/.github/workflows/runtime_prereleases.yml@main permissions: # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run actions: read # NOTE: Intentionally running these jobs sequentially because npm # will sometimes fail if you try to concurrently publish two # different versions of the same package, even if they use different # dist tags. needs: publish_prerelease_canary with: commit_sha: ${{ github.sha }} release_channel: experimental dist_tag: experimental enableFailureNotification: true dry: false secrets: DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} ================================================ FILE: .github/workflows/runtime_releases_from_npm_manual.yml ================================================ name: (Runtime) Publish Releases from NPM Manual on: workflow_dispatch: inputs: version_to_promote: required: true description: Current npm version (non-experimental) to promote type: string version_to_publish: required: true description: Version to publish for the specified packages type: string only_packages: description: Packages to publish (space separated) type: string skip_packages: description: Packages to NOT publish (space separated) type: string tags: description: NPM tags (space separated) type: string default: untagged dry: required: true description: Dry run instead of publish? type: boolean default: true force_notify: description: Force a Discord notification? type: boolean default: false permissions: {} env: TZ: /usr/share/zoneinfo/America/Los_Angeles # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1 NPM_TOKEN: ${{ secrets.NPM_TOKEN }} jobs: notify: if: ${{ inputs.force_notify || inputs.dry == false || inputs.dry == 'false' }} runs-on: ubuntu-latest steps: - name: Discord Webhook Action uses: tsickert/discord-webhook@86dc739f3f165f16dadc5666051c367efa1692f4 with: webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }} embed-author-name: ${{ github.event.sender.login }} embed-author-url: ${{ github.event.sender.html_url }} embed-author-icon-url: ${{ github.event.sender.avatar_url }} embed-title: "⚠️ Publishing release from NPM${{ (inputs.dry && ' (dry run)') || '' }}" embed-description: | ```json ${{ toJson(inputs) }} ``` embed-url: https://github.com/facebook/react/actions/runs/${{ github.run_id }} publish: name: Publish releases runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 id: node_modules with: path: | **/node_modules key: runtime-release-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }} - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: yarn --cwd scripts/release install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: cp ./scripts/release/ci-npmrc ~/.npmrc - if: '${{ inputs.only_packages }}' name: 'Prepare ${{ inputs.only_packages }} from NPM' run: | scripts/release/prepare-release-from-npm.js \ --ci \ --skipTests \ --version=${{ inputs.version_to_promote }} \ --publishVersion=${{ inputs.version_to_publish }} \ --onlyPackages=${{ inputs.only_packages }} - if: '${{ inputs.skip_packages }}' name: 'Prepare all packages EXCEPT ${{ inputs.skip_packages }} from NPM' run: | scripts/release/prepare-release-from-npm.js \ --ci \ --skipTests \ --version=${{ inputs.version_to_promote }} \ --publishVersion=${{ inputs.version_to_publish }} \ --skipPackages=${{ inputs.skip_packages }} - name: Check prepared files run: ls -R build/node_modules - if: '${{ inputs.only_packages }}' name: 'Publish ${{ inputs.only_packages }}' run: | scripts/release/publish.js \ --ci \ --tags=${{ inputs.tags }} \ --publishVersion=${{ inputs.version_to_publish }} \ --onlyPackages=${{ inputs.only_packages }} ${{ (inputs.dry && '') || '\'}} ${{ inputs.dry && '--dry' || '' }} - if: '${{ inputs.skip_packages }}' name: 'Publish all packages EXCEPT ${{ inputs.skip_packages }}' run: | scripts/release/publish.js \ --ci \ --tags=${{ inputs.tags }} \ --publishVersion=${{ inputs.version_to_publish }} \ --skipPackages=${{ inputs.skip_packages }} ${{ (inputs.dry && '') || '\'}} ${{ inputs.dry && '--dry' || '' }} - name: Archive released package for debugging uses: actions/upload-artifact@v4 with: name: build path: | ./build/node_modules ================================================ FILE: .github/workflows/shared_check_maintainer.yml ================================================ name: (Shared) Check maintainer on: workflow_call: inputs: actor: required: true type: string outputs: is_core_team: value: ${{ jobs.check_maintainer.outputs.is_core_team }} permissions: {} env: TZ: /usr/share/zoneinfo/America/Los_Angeles # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1 jobs: check_maintainer: runs-on: ubuntu-latest permissions: # We fetch the contents of the MAINTAINERS file contents: read outputs: is_core_team: ${{ steps.check_if_actor_is_maintainer.outputs.result }} steps: - name: Check if actor is maintainer id: check_if_actor_is_maintainer uses: actions/github-script@v7 with: script: | const fs = require('fs'); const actor = '${{ inputs.actor }}'; const res = await github.rest.repos.getContent({ owner: 'facebook', repo: 'react', path: 'MAINTAINERS', ref: 'main', headers: { Accept: 'application/vnd.github+json' } }); if (res.status !== 200) { console.error(res); throw new Error('Unable to fetch MAINTAINERS file'); } content = Buffer.from(res.data.content, 'base64').toString(); if (content == null || typeof content !== 'string') { throw new Error('Unable to retrieve MAINTAINERS file'); } const maintainers = new Set(content.split('\n')); if (maintainers.has(actor)) { console.log(`🟢 ${actor} is a maintainer`); return true; } console.log(`🔴 ${actor} is NOT a maintainer`); return null; ================================================ FILE: .github/workflows/shared_cleanup_merged_branch_caches.yml ================================================ # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#force-deletion-of-caches-overriding-default-cache-eviction-policy name: (Shared) Cleanup Merged Branch Caches on: pull_request: types: - closed workflow_dispatch: inputs: pr_number: required: true type: string permissions: {} jobs: cleanup: runs-on: ubuntu-latest permissions: # `actions:write` permission is required to delete caches # See also: https://docs.github.com/en/rest/actions/cache?apiVersion=2022-11-28#delete-a-github-actions-cache-for-a-repository-using-a-cache-id actions: write contents: read steps: - name: Cleanup run: | echo "Fetching list of cache key" cacheKeysForPR=$(gh cache list --ref $BRANCH --limit 100 --json id --jq '.[].id') ## Setting this to not fail the workflow while deleting cache keys. set +e for cacheKey in $cacheKeysForPR do gh cache delete $cacheKey echo "Deleting $cacheKey" done echo "Done" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_REPO: ${{ github.repository }} BRANCH: refs/pull/${{ inputs.pr_number || github.event.pull_request.number }}/merge ================================================ FILE: .github/workflows/shared_cleanup_stale_branch_caches.yml ================================================ # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#force-deletion-of-caches-overriding-default-cache-eviction-policy name: (Shared) Cleanup Stale Branch Caches on: schedule: # Every 6 hours - cron: 0 */6 * * * workflow_dispatch: permissions: {} jobs: cleanup: runs-on: ubuntu-latest permissions: # `actions:write` permission is required to delete caches # See also: https://docs.github.com/en/rest/actions/cache?apiVersion=2022-11-28#delete-a-github-actions-cache-for-a-repository-using-a-cache-id actions: write contents: read steps: - name: Cleanup run: | echo "Fetching list of cache keys" cacheKeysForPR=$(gh cache list --limit 100 --json id,ref --jq '.[] | select(.ref != "refs/heads/main") | .id') ## Setting this to not fail the workflow while deleting cache keys. set +e for cacheKey in $cacheKeysForPR do gh cache delete $cacheKey echo "Deleting $cacheKey" done echo "Done" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_REPO: ${{ github.repository }} ================================================ FILE: .github/workflows/shared_close_direct_sync_branch_prs.yml ================================================ name: (Shared) Close Direct Sync Branch PRs on: pull_request: branches: - 'builds/facebook-**' permissions: {} env: TZ: /usr/share/zoneinfo/America/Los_Angeles # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1 jobs: close_pr: runs-on: ubuntu-latest permissions: # Used to create a review and close PRs pull-requests: write contents: write steps: - name: Close PR uses: actions/github-script@v7 with: script: | const owner = context.repo.owner; const repo = context.repo.repo; const pullNumber = ${{ github.event.number }}; await github.rest.pulls.createReview({ owner, repo, pull_number: pullNumber, body: 'Do not land changes to `${{ github.event.pull_request.base.ref }}`. Please re-open your PR targeting `main` instead.', event: 'REQUEST_CHANGES' }); await github.rest.pulls.update({ owner, repo, pull_number: pullNumber, state: 'closed' }); ================================================ FILE: .github/workflows/shared_label_core_team_prs.yml ================================================ name: (Shared) Label Core Team PRs on: pull_request_target: types: [opened] permissions: {} env: TZ: /usr/share/zoneinfo/America/Los_Angeles # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1 jobs: check_access: runs-on: ubuntu-latest outputs: is_member_or_collaborator: ${{ steps.check_is_member_or_collaborator.outputs.is_member_or_collaborator }} steps: - run: echo ${{ github.event.pull_request.author_association }} - name: Check is member or collaborator id: check_is_member_or_collaborator if: ${{ github.event.pull_request.author_association == 'MEMBER' || github.event.pull_request.author_association == 'COLLABORATOR' }} run: echo "is_member_or_collaborator=true" >> "$GITHUB_OUTPUT" check_maintainer: if: ${{ needs.check_access.outputs.is_member_or_collaborator == 'true' || needs.check_access.outputs.is_member_or_collaborator == true }} needs: [check_access] uses: facebook/react/.github/workflows/shared_check_maintainer.yml@main permissions: # Used by check_maintainer contents: read with: actor: ${{ github.event.pull_request.user.login }} label: if: ${{ needs.check_maintainer.outputs.is_core_team == 'true' }} runs-on: ubuntu-latest needs: check_maintainer permissions: # Used to add labels on issues issues: write # Used to add labels on PRs pull-requests: write steps: - name: Label PR as React Core Team uses: actions/github-script@v7 with: script: | github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, issue_number: ${{ github.event.number }}, labels: ['React Core Team'] }); ================================================ FILE: .github/workflows/shared_lint.yml ================================================ name: (Shared) Lint on: push: branches: [main] pull_request: permissions: {} concurrency: group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.run_id }} cancel-in-progress: true env: TZ: /usr/share/zoneinfo/America/Los_Angeles # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1 jobs: prettier: name: Run prettier runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 id: node_modules with: path: | **/node_modules key: shared-lint-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }} - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: yarn prettier-check eslint: name: Run eslint runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 id: node_modules with: path: | **/node_modules key: shared-lint-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }} - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: node ./scripts/tasks/eslint check_license: name: Check license runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 id: node_modules with: path: | **/node_modules key: shared-lint-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }} - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: ./scripts/ci/check_license.sh test_print_warnings: name: Test print warnings runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn cache-dependency-path: yarn.lock - name: Restore cached node_modules uses: actions/cache@v4 id: node_modules with: path: | **/node_modules key: shared-lint-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }} - name: Ensure clean build directory run: rm -rf build - run: yarn install --frozen-lockfile if: steps.node_modules.outputs.cache-hit != 'true' - run: ./scripts/ci/test_print_warnings.sh ================================================ FILE: .github/workflows/shared_stale.yml ================================================ # Configuration for stale action workflow - https://github.com/actions/stale name: (Shared) Manage stale issues and PRs on: schedule: # Run hourly - cron: '0 * * * *' workflow_dispatch: permissions: # https://github.com/actions/stale/tree/v9/?tab=readme-ov-file#recommended-permissions issues: write pull-requests: write env: TZ: /usr/share/zoneinfo/America/Los_Angeles jobs: stale: runs-on: ubuntu-latest steps: - uses: actions/stale@v9 with: # --- Issues & PRs --- # Number of days of inactivity before an issue or PR becomes stale days-before-stale: 90 # Number of days of inactivity before a stale issue or PR is closed days-before-close: 7 # API calls per run operations-per-run: 100 # --- Issues --- stale-issue-label: "Resolution: Stale" # Comment to post when marking an issue as stale stale-issue-message: > This issue has been automatically marked as stale. **If this issue is still affecting you, please leave any comment** (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment! # Comment to post when closing a stale issue close-issue-message: > Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you! # Issues with these labels will never be considered stale exempt-issue-labels: "Partner,React Core Team,Resolution: Backlog,Type: Bug,Type: Discussion,Type: Needs Investigation,Type: Regression,Type: Feature Request,Type: Enhancement" # --- PRs --- stale-pr-label: "Resolution: Stale" # Comment to post when marking a pull request as stale stale-pr-message: > This pull request has been automatically marked as stale. **If this pull request is still relevant, please leave any comment** (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize reviewing it yet. Your contribution is very much appreciated. # Comment to post when closing a stale pull request close-pr-message: > Closing this pull request after a prolonged period of inactivity. If this issue is still present in the latest release, please ask for this pull request to be reopened. Thank you! # PRs with these labels will never be considered stale exempt-pr-labels: "Partner,React Core Team,Resolution: Backlog,Type: Bug,Type: Discussion,Type: Needs Investigation,Type: Regression,Type: Feature Request,Type: Enhancement" ================================================ FILE: .gitignore ================================================ .DS_STORE node_modules scripts/flow/*/.flowconfig .flowconfig *~ *.pyc .grunt _SpecRunner.html __benchmarks__ build/ remote-repo/ coverage/ .module-cache fixtures/dom/public/react-dom.js fixtures/dom/public/react.js test/the-files-to-test.generated.js *.log* chrome-user-data *.sublime-project *.sublime-workspace .idea *.iml .vscode *.swp *.swo /tmp /.worktrees .claude/*.local.* packages/react-devtools-core/dist packages/react-devtools-extensions/chrome/build packages/react-devtools-extensions/chrome/*.crx packages/react-devtools-extensions/chrome/*.pem packages/react-devtools-extensions/firefox/build packages/react-devtools-extensions/firefox/*.xpi packages/react-devtools-extensions/firefox/*.pem packages/react-devtools-extensions/shared/build packages/react-devtools-extensions/.tempUserDataDir packages/react-devtools-fusebox/dist packages/react-devtools-inline/dist packages/react-devtools-shell/dist packages/react-devtools-timeline/dist ================================================ FILE: .mailmap ================================================ Adam Timberlake Alex Mykyta Alex Pien Alex Pien Alex Pien Andreas Savvides Andreas Savvides Andreas Svensson Andres Suarez Andrew Kulakov Andrew Sokolov Anto Aravinth Baraa Hamodi Ben Halpern Ben Newman Benjamin Woodruff Bill Fisher Blaine Kasten Brandon Tilley Changsoon Bok Cheng Lou Christian Oliff Christoph Pojer Christoph Pojer Connor McSheffrey Conor Hastings Dan Schafer Daniel Gasienica Daniel Gasienica Daniel Hejl Daniel Lo Nigro Dave Galbraith Dennis Johnson Dmitry Blues Dongsheng Liu Erik Harper Evan Coonrod Fabio M. Costa Felix Kling François-Xavier Bois Fyodor Ivanishchev Gabe Levi Geert Pasteels George A Sisco III Georgii Dolzhykov Harry Hull Hendrik Swanepoel Hyeock Kwon Ian Obermiller Ilia Pavlenkov Ilyá Belsky Ingvar Stepanyan Irae Carvalho Ivan Vergiliev JJ Weber Jae Hun Ro Jaime Mingo James Brantly Jan Hancic Jan Kassens Jason Bonta Jason Quense Jason Trill Jeff Chan Jeff Morrison Jeff Morrison Jeff Morrison Jeffrey Lin Jim Sproch Jim Sproch Jim Sproch Jinwoo Oh Jinxiu Lee Jiyeon Seo Jon Chester Jon Madison Jonathan Hsu Jonathan Persson Jordan Walke Jordan Walke Joseph Savona Josh Duck Juan Serrano Jun Wu Justin Robison Keito Uchiyama Kevin Coughlin Krystian Karczewski Kunal Mehta Laurence Rowe Lea Rosema Marcin K. Mark Anderson Mark Funk Martin Andert Mathieu M-Gosselin Matsunoki Matt Brookes Matt Dunn-Rankin Matt Zabriskie Matthew Johnston Matthew Looi Mattijs Kneppers Max Heiber Max Stoiber Michal Srb xixixao Michelle Todd Mihai Parparita Minwe LUO Murray M. Moss Murray M. Moss Neri Marschik Nick Gavalas Nick Thompson Patrick Stapleton Paul O’Shannessy Paul Shen Pete Hunt Pete Hunt Pete Hunt Pete Hunt Petri Lievonen Petri Lievonen Pieter Vanderwerff Pouja Nikray Rainer Oviir Ray Richard Feldman Richard Livesey Rick Hanlon Rick Hanlon Rob Arnold Robert Binna Robin Frischmann Sander Spies Scott Feeney Sebastian Markbåge Sergey Rubanov Shogun Sea Soichiro Kawamura Sophie Alpert Sophie Alpert Sophie Alpert Sophie Alpert Sota Ohara Steven Luscher Steven Luscher Steven Luscher Steven Luscher Seth Webster Stoyan Stefanov Tengfei Guo Thomas Aylott Timothy Yung Tomoya Suzuki Vasiliy Loginevskiy Vasiliy Loginevskiy Vjeux Vjeux Volkan Unsal Wander Wang Xavier Morel YouBao Nong Yutaka Nakajima Zach Bruggeman iawia002 <850127508@qq.com> 元彦 张敏 ================================================ FILE: .nvmrc ================================================ v20.19.0 ================================================ FILE: .prettierignore ================================================ # react runtime build packages/react-devtools-core/dist packages/react-devtools-extensions/chrome/build packages/react-devtools-extensions/firefox/build packages/react-devtools-extensions/edge/build packages/react-devtools-extensions/shared/build packages/react-devtools-extensions/src/ErrorTesterCompiled.js packages/react-devtools-fusebox/dist packages/react-devtools-inline/dist packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/ packages/react-devtools-shared/src/hooks/__tests__/__source__/__untransformed__/ packages/react-devtools-shell/dist packages/react-devtools-timeline/dist packages/react-devtools-timeline/static # react compiler compiler/**/dist compiler/**/__tests__/fixtures/**/*.expect.md compiler/**/.next # contains invalid graphql`...` which results in a promise rejection error from `yarn prettier-all`. compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-kitchensink.js compiler/crates compiler/target compiler/apps/playground/public compiler/**/LICENSE compiler/*.md* compiler/*.json compiler/*.css compiler/*.webmanifest compiler/*.map compiler/*.sh compiler/*.txt compiler/*.ico compiler/*.svg compiler/*.lock compiler/*.toml ================================================ FILE: .prettierrc.js ================================================ 'use strict'; const {esNextPaths} = require('./scripts/shared/pathsByLanguageVersion'); module.exports = { bracketSpacing: false, singleQuote: true, bracketSameLine: true, trailingComma: 'es5', printWidth: 80, parser: 'flow', arrowParens: 'avoid', overrides: [ { files: ['*.code-workspace'], options: { parser: 'json-stringify', }, }, { files: esNextPaths, options: { trailingComma: 'all', }, }, { files: ['*.ts', '*.tsx'], options: { trailingComma: 'all', parser: 'typescript', }, }, ], }; ================================================ FILE: .watchmanconfig ================================================ {} ================================================ FILE: CHANGELOG.md ================================================ ## 19.2.1 (Dec 3, 2025) ### React Server Components - Bring React Server Component fixes to Server Actions (@sebmarkbage [#35277](https://github.com/facebook/react/pull/35277)) ## 19.2.0 (October 1st, 2025) Below is a list of all new features, APIs, and bug fixes. Read the [React 19.2 release post](https://react.dev/blog/2025/10/01/react-19-2) for more information. ### New React Features - [``](https://react.dev/reference/react/Activity): A new API to hide and restore the UI and internal state of its children. - [`useEffectEvent`](https://react.dev/reference/react/useEffectEvent) is a React Hook that lets you extract non-reactive logic into an [Effect Event](https://react.dev/learn/separating-events-from-effects#declaring-an-effect-event). - [`cacheSignal`](https://react.dev/reference/react/cacheSignal) (for RSCs) lets your know when the `cache()` lifetime is over. - [React Performance tracks](https://react.dev/reference/dev-tools/react-performance-tracks) appear on the Performance panel’s timeline in your browser developer tools ### New React DOM Features - Added resume APIs for partial pre-rendering with Web Streams: - [`resume`](https://react.dev/reference/react-dom/server/resume): to resume a prerender to a stream. - [`resumeAndPrerender`](https://react.dev/reference/react-dom/static/resumeAndPrerender): to resume a prerender to HTML. - Added resume APIs for partial pre-rendering with Node Streams: - [`resumeToPipeableStream`](https://react.dev/reference/react-dom/server/resumeToPipeableStream): to resume a prerender to a stream. - [`resumeAndPrerenderToNodeStream`](https://react.dev/reference/react-dom/static/resumeAndPrerenderToNodeStream): to resume a prerender to HTML. - Updated [`prerender`](https://react.dev/reference/react-dom/static/prerender) APIs to return a `postponed` state that can be passed to the `resume` APIs. ### Notable changes - React DOM now batches suspense boundary reveals, matching the behavior of client side rendering. This change is especially noticeable when animating the reveal of Suspense boundaries e.g. with the upcoming `` Component. React will batch as much reveals as possible before the first paint while trying to hit popular first-contentful paint metrics. - Add Node Web Streams (`prerender`, `renderToReadableStream`) to server-side-rendering APIs for Node.js - Use underscore instead of `:` IDs generated by useId ### All Changes #### React - `` was developed over many years, starting before `ClassComponent.setState` (@acdlite @sebmarkbage and many others) - Stringify context as "SomeContext" instead of "SomeContext.Provider" (@kassens [#33507](https://github.com/facebook/react/pull/33507)) - Include stack of cause of React instrumentation errors with `%o` placeholder (@eps1lon [#34198](https://github.com/facebook/react/pull/34198)) - Fix infinite `useDeferredValue` loop in popstate event (@acdlite [#32821](https://github.com/facebook/react/pull/32821)) - Fix a bug when an initial value was passed to `useDeferredValue` (@acdlite [#34376](https://github.com/facebook/react/pull/34376)) - Fix a crash when submitting forms with Client Actions (@sebmarkbage [#33055](https://github.com/facebook/react/pull/33055)) - Hide/unhide the content of dehydrated suspense boundaries if they resuspend (@sebmarkbage [#32900](https://github.com/facebook/react/pull/32900)) - Avoid stack overflow on wide trees during Hot Reload (@sophiebits [#34145](https://github.com/facebook/react/pull/34145)) - Improve Owner and Component stacks in various places (@sebmarkbage, @eps1lon: [#33629](https://github.com/facebook/react/pull/33629), [#33724](https://github.com/facebook/react/pull/33724), [#32735](https://github.com/facebook/react/pull/32735), [#33723](https://github.com/facebook/react/pull/33723)) - Add `cacheSignal` (@sebmarkbage [#33557](https://github.com/facebook/react/pull/33557)) #### React DOM - Block on Suspensey Fonts during reveal of server-side-rendered content (@sebmarkbage [#33342](https://github.com/facebook/react/pull/33342)) - Use underscore instead of `:` for IDs generated by `useId` (@sebmarkbage, @eps1lon: [#32001](https://github.com/facebook/react/pull/32001), [https://github.com/facebook/react/pull/33342](https://github.com/facebook/react/pull/33342)[#33099](https://github.com/facebook/react/pull/33099), [#33422](https://github.com/facebook/react/pull/33422)) - Stop warning when ARIA 1.3 attributes are used (@Abdul-Omira [#34264](https://github.com/facebook/react/pull/34264)) - Allow `nonce` to be used on hoistable styles (@Andarist [#32461](https://github.com/facebook/react/pull/32461)) - Warn for using a React owned node as a Container if it also has text content (@sebmarkbage [#32774](https://github.com/facebook/react/pull/32774)) - s/HTML/text for for error messages if text hydration mismatches (@rickhanlonii [#32763](https://github.com/facebook/react/pull/32763)) - Fix a bug with `React.use` inside `React.lazy`\-ed Component (@hi-ogawa [#33941](https://github.com/facebook/react/pull/33941)) - Enable the `progressiveChunkSize` option for server-side-rendering APIs (@sebmarkbage [#33027](https://github.com/facebook/react/pull/33027)) - Fix a bug with deeply nested Suspense inside Suspense fallback when server-side-rendering (@gnoff [#33467](https://github.com/facebook/react/pull/33467)) - Avoid hanging when suspending after aborting while rendering (@gnoff [#34192](https://github.com/facebook/react/pull/34192)) - Add Node Web Streams to server-side-rendering APIs for Node.js (@sebmarkbage [#33475](https://github.com/facebook/react/pull/33475)) #### React Server Components - Preload `` and `` using hints before they're rendered (@sebmarkbage [#34604](https://github.com/facebook/react/pull/34604)) - Log error if production elements are rendered during development (@eps1lon [#34189](https://github.com/facebook/react/pull/34189)) - Fix a bug when returning a Temporary reference (e.g. a Client Reference) from Server Functions (@sebmarkbage [#34084](https://github.com/facebook/react/pull/34084), @denk0403 [#33761](https://github.com/facebook/react/pull/33761)) - Pass line/column to `filterStackFrame` (@eps1lon [#33707](https://github.com/facebook/react/pull/33707)) - Support Async Modules in Turbopack Server References (@lubieowoce [#34531](https://github.com/facebook/react/pull/34531)) - Add support for .mjs file extension in Webpack (@jennyscript [#33028](https://github.com/facebook/react/pull/33028)) - Fix a wrong missing key warning (@unstubbable [#34350](https://github.com/facebook/react/pull/34350)) - Make console log resolve in predictable order (@sebmarkbage [#33665](https://github.com/facebook/react/pull/33665)) #### React Reconciler - [createContainer](https://github.com/facebook/react/blob/v19.2.0/packages/react-reconciler/src/ReactFiberReconciler.js#L255-L261) and [createHydrationContainer](https://github.com/facebook/react/blob/v19.2.0/packages/react-reconciler/src/ReactFiberReconciler.js#L305-L312) had their parameter order adjusted after `on*` handlers to account for upcoming experimental APIs ## 19.1.2 (Dec 3, 2025) ### React Server Components - Bring React Server Component fixes to Server Actions (@sebmarkbage [#35277](https://github.com/facebook/react/pull/35277)) ## 19.1.1 (July 28, 2025) ### React * Fixed Owner Stacks to work with ES2015 function.name semantics ([#33680](https://github.com/facebook/react/pull/33680) by @hoxyq) ## 19.1.0 (March 28, 2025) ### Owner Stack An Owner Stack is a string representing the components that are directly responsible for rendering a particular component. You can log Owner Stacks when debugging or use Owner Stacks to enhance error overlays or other development tools. Owner Stacks are only available in development builds. Component Stacks in production are unchanged. * An Owner Stack is a development-only stack trace that helps identify which components are responsible for rendering a particular component. An Owner Stack is distinct from a Component Stacks, which shows the hierarchy of components leading to an error. * The [captureOwnerStack API](https://react.dev/reference/react/captureOwnerStack) is only available in development mode and returns a Owner Stack, if available. The API can be used to enhance error overlays or log component relationships when debugging. [#29923](https://github.com/facebook/react/pull/29923), [#32353](https://github.com/facebook/react/pull/32353), [#30306](https://github.com/facebook/react/pull/30306), [#32538](https://github.com/facebook/react/pull/32538), [#32529](https://github.com/facebook/react/pull/32529), [#32538](https://github.com/facebook/react/pull/32538) ### React * Enhanced support for Suspense boundaries to be used anywhere, including the client, server, and during hydration. [#32069](https://github.com/facebook/react/pull/32069), [#32163](https://github.com/facebook/react/pull/32163), [#32224](https://github.com/facebook/react/pull/32224), [#32252](https://github.com/facebook/react/pull/32252) * Reduced unnecessary client rendering through improved hydration scheduling [#31751](https://github.com/facebook/react/pull/31751) * Increased priority of client rendered Suspense boundaries [#31776](https://github.com/facebook/react/pull/31776) * Fixed frozen fallback states by rendering unfinished Suspense boundaries on the client. [#31620](https://github.com/facebook/react/pull/31620) * Reduced garbage collection pressure by improving Suspense boundary retries. [#31667](https://github.com/facebook/react/pull/31667) * Fixed erroneous “Waiting for Paint” log when the passive effect phase was not delayed [#31526](https://github.com/facebook/react/pull/31526) * Fixed a regression causing key warnings for flattened positional children in development mode. [#32117](https://github.com/facebook/react/pull/32117) * Updated `useId` to use valid CSS selectors, changing format from `:r123:` to `«r123»`. [#32001](https://github.com/facebook/react/pull/32001) * Added a dev-only warning for null/undefined created in useEffect, useInsertionEffect, and useLayoutEffect. [#32355](https://github.com/facebook/react/pull/32355) * Fixed a bug where dev-only methods were exported in production builds. React.act is no longer available in production builds. [#32200](https://github.com/facebook/react/pull/32200) * Improved consistency across prod and dev to improve compatibility with Google Closure Compiler and bindings [#31808](https://github.com/facebook/react/pull/31808) * Improve passive effect scheduling for consistent task yielding. [#31785](https://github.com/facebook/react/pull/31785) * Fixed asserts in React Native when passChildrenWhenCloningPersistedNodes is enabled for OffscreenComponent rendering. [#32528](https://github.com/facebook/react/pull/32528) * Fixed component name resolution for Portal [#32640](https://github.com/facebook/react/pull/32640) * Added support for beforetoggle and toggle events on the dialog element. [#32479](https://github.com/facebook/react/pull/32479) ### React DOM * Fixed double warning when the `href` attribute is an empty string [#31783](https://github.com/facebook/react/pull/31783) * Fixed an edge case where `getHoistableRoot()` didn’t work properly when the container was a Document [#32321](https://github.com/facebook/react/pull/32321) * Removed support for using HTML comments (e.g. ``) as a DOM container. [#32250](https://github.com/facebook/react/pull/32250) * Added support for `
`; return html; } ================================================ FILE: compiler/packages/react-mcp-server/src/types/algolia.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ // https://github.com/algolia/docsearch/blob/15ebcba606b281aa0dddc4ccb8feb19d396bf79e/packages/docsearch-react/src/types/DocSearchHit.ts type ContentType = | 'content' | 'lvl0' | 'lvl1' | 'lvl2' | 'lvl3' | 'lvl4' | 'lvl5' | 'lvl6'; interface DocSearchHitAttributeHighlightResult { value: string; matchLevel: 'full' | 'none' | 'partial'; matchedWords: string[]; fullyHighlighted?: boolean; } interface DocSearchHitHighlightResultHierarchy { lvl0: DocSearchHitAttributeHighlightResult; lvl1: DocSearchHitAttributeHighlightResult; lvl2: DocSearchHitAttributeHighlightResult; lvl3: DocSearchHitAttributeHighlightResult; lvl4: DocSearchHitAttributeHighlightResult; lvl5: DocSearchHitAttributeHighlightResult; lvl6: DocSearchHitAttributeHighlightResult; } interface DocSearchHitHighlightResult { content: DocSearchHitAttributeHighlightResult; hierarchy: DocSearchHitHighlightResultHierarchy; hierarchy_camel: DocSearchHitHighlightResultHierarchy[]; } interface DocSearchHitAttributeSnippetResult { value: string; matchLevel: 'full' | 'none' | 'partial'; } interface DocSearchHitSnippetResult { content: DocSearchHitAttributeSnippetResult; hierarchy: DocSearchHitHighlightResultHierarchy; hierarchy_camel: DocSearchHitHighlightResultHierarchy[]; } export declare type DocSearchHit = { objectID: string; content: string | null; url: string; url_without_anchor: string; type: ContentType; anchor: string | null; hierarchy: { lvl0: string; lvl1: string; lvl2: string | null; lvl3: string | null; lvl4: string | null; lvl5: string | null; lvl6: string | null; }; _highlightResult: DocSearchHitHighlightResult; _snippetResult: DocSearchHitSnippetResult; _rankingInfo?: { promoted: boolean; nbTypos: number; firstMatchedWord: number; proximityDistance?: number; geoDistance: number; geoPrecision?: number; nbExactWords: number; words: number; filters: number; userScore: number; matchedGeoLocation?: { lat: number; lng: number; distance: number; }; }; _distinctSeqID?: number; __autocomplete_indexName?: string; __autocomplete_queryID?: string; __autocomplete_algoliaCredentials?: { appId: string; apiKey: string; }; __autocomplete_id?: number; }; export type InternalDocSearchHit = DocSearchHit & { __docsearch_parent: InternalDocSearchHit | null; }; ================================================ FILE: compiler/packages/react-mcp-server/src/utils/algolia.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import type {DocSearchHit, InternalDocSearchHit} from '../types/algolia'; import {liteClient, type Hit, type SearchResponse} from 'algoliasearch/lite'; // https://github.com/reactjs/react.dev/blob/55986965fbf69c2584040039c9586a01bd54eba7/src/siteConfig.js#L15-L19 const ALGOLIA_CONFIG = { appId: '1FCF9AYYAT', apiKey: '1b7ad4e1c89e645e351e59d40544eda1', indexName: 'beta-react', }; export const ALGOLIA_CLIENT = liteClient( ALGOLIA_CONFIG.appId, ALGOLIA_CONFIG.apiKey, ); export function printHierarchy( hit: DocSearchHit | InternalDocSearchHit, ): string { let val = `${hit.hierarchy.lvl0} > ${hit.hierarchy.lvl1}`; if (hit.hierarchy.lvl2 != null) { val = val.concat(` > ${hit.hierarchy.lvl2}`); } if (hit.hierarchy.lvl3 != null) { val = val.concat(` > ${hit.hierarchy.lvl3}`); } if (hit.hierarchy.lvl4 != null) { val = val.concat(` > ${hit.hierarchy.lvl4}`); } if (hit.hierarchy.lvl5 != null) { val = val.concat(` > ${hit.hierarchy.lvl5}`); } if (hit.hierarchy.lvl6 != null) { val = val.concat(` > ${hit.hierarchy.lvl6}`); } return val; } export async function queryAlgolia( message: string | Array, ): Promise> { const {results} = await ALGOLIA_CLIENT.search({ requests: [ { query: Array.isArray(message) ? message.join('\n') : message, indexName: ALGOLIA_CONFIG.indexName, attributesToRetrieve: [ 'hierarchy.lvl0', 'hierarchy.lvl1', 'hierarchy.lvl2', 'hierarchy.lvl3', 'hierarchy.lvl4', 'hierarchy.lvl5', 'hierarchy.lvl6', 'content', 'url', ], attributesToSnippet: [ `hierarchy.lvl1:10`, `hierarchy.lvl2:10`, `hierarchy.lvl3:10`, `hierarchy.lvl4:10`, `hierarchy.lvl5:10`, `hierarchy.lvl6:10`, `content:10`, ], snippetEllipsisText: '…', hitsPerPage: 30, attributesToHighlight: [ 'hierarchy.lvl0', 'hierarchy.lvl1', 'hierarchy.lvl2', 'hierarchy.lvl3', 'hierarchy.lvl4', 'hierarchy.lvl5', 'hierarchy.lvl6', 'content', ], }, ], }); const firstResult = results[0] as SearchResponse; const {hits} = firstResult; const deduped = new Map(); for (const hit of hits) { // drop hashes to dedupe properly const u = new URL(hit.url); if (deduped.has(u.pathname)) { continue; } deduped.set(u.pathname, hit); } const pages: Array = await Promise.all( Array.from(deduped.values()).map(hit => { return fetch(hit.url, { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36', }, }).then(res => { if (res.ok === true) { return res.text(); } else { console.error( `Could not fetch docs: ${res.status} ${res.statusText}`, ); return null; } }); }), ); return pages.filter(page => page !== null); } ================================================ FILE: compiler/packages/react-mcp-server/src/utils/assertExhaustive.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ /** * Trigger an exhaustiveness check in TypeScript and throw at runtime. */ export default function assertExhaustive(_: never, errorMsg: string): never { throw new Error(errorMsg); } ================================================ FILE: compiler/packages/react-mcp-server/todo.md ================================================ TODO - [ ] If code doesnt compile, read diagnostics and try again - [ ] Provide detailed examples in assistant prompt (use another LLM to generate good prompts, iterate from there) - [ ] Provide more tools for working with HIR/AST (eg so we can prompt it to try and optimize code via HIR, which it can then translate back into user code changes) ================================================ FILE: compiler/packages/react-mcp-server/tsconfig.json ================================================ { "extends": "@tsconfig/strictest/tsconfig.json", "compilerOptions": { "module": "Node16", "moduleResolution": "Node16", "rootDir": "../", "noEmit": true, "jsx": "react-jsxdev", "lib": ["ES2022"], // weaken strictness from preset "importsNotUsedAsValues": "remove", "noUncheckedIndexedAccess": false, "noUnusedParameters": false, "useUnknownInCatchVariables": false, "target": "ES2022", // ideally turn off only during dev, or on a per-file basis "noUnusedLocals": false, }, "exclude": ["node_modules"], "include": ["src/**/*.ts"], } ================================================ FILE: compiler/packages/react-mcp-server/tsup.config.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import {defineConfig} from 'tsup'; export default defineConfig({ entry: ['./src/index.ts'], outDir: './dist', external: [], splitting: false, sourcemap: false, dts: false, bundle: true, format: 'cjs', platform: 'node', target: 'es2022', banner: { js: `#!/usr/bin/env node /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @lightSyntaxTransform * @noflow * @nolint * @preventMunge * @preserve-invariant-messages */`, }, }); ================================================ FILE: compiler/packages/snap/package.json ================================================ { "name": "snap", "version": "0.0.1", "public": false, "description": "Snapshot testing CLI tool", "main": "dist/main.js", "license": "MIT", "files": [ "src" ], "scripts": { "postinstall": "./scripts/link-react-compiler-runtime.sh && perl -p -i -e 's/react\\.element/react.transitional.element/' ../../node_modules/fbt/lib/FbtReactUtil.js && perl -p -i -e 's/didWarnAboutUsingAct = false;/didWarnAboutUsingAct = true;/' ../../node_modules/react-dom/cjs/react-dom-test-utils.development.js", "build": "rimraf dist && concurrently -n snap,runtime \"tsc --build\" \"yarn --silent workspace react-compiler-runtime build\"", "snap": "node dist/main.js", "test": "echo 'no tests'", "prettier": "prettier --write 'src/**/*.ts'" }, "repository": { "type": "git", "url": "git+https://github.com/facebook/react.git", "directory": "compiler/packages/snap" }, "dependencies": { "@babel/code-frame": "^7.22.5", "@babel/generator": "^7.19.1", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/preset-flow": "^7.7.4", "@babel/preset-typescript": "^7.26.0", "@parcel/watcher": "^2.1.0", "@testing-library/react": "^13.4.0", "babel-plugin-idx": "^3.0.3", "babel-plugin-syntax-hermes-parser": "^0.25.1", "chalk": "4", "fbt": "^1.0.2", "glob": "^10.3.10", "hermes-parser": "^0.25.1", "jsdom": "^22.1.0", "react": "0.0.0-experimental-4beb1fd8-20241118", "react-dom": "0.0.0-experimental-4beb1fd8-20241118", "readline": "^1.3.0", "yargs": "^17.7.1", "zod": "^3.25.0 || ^4.0.0", "zod-validation-error": "^3.5.0 || ^4.0.0" }, "devDependencies": { "@babel/core": "^7.19.1", "@babel/parser": "^7.20.15", "@babel/plugin-transform-modules-commonjs": "^7.18.6", "@babel/preset-react": "^7.18.6", "@babel/traverse": "^7.19.1", "@types/babel__code-frame": "^7.0.6", "@types/fbt": "^1.0.4", "@types/glob": "^8.1.0", "@types/node": "^18.7.18", "@typescript-eslint/eslint-plugin": "^7.4.0", "@typescript-eslint/parser": "^7.4.0", "object-assign": "^4.1.1" }, "resolutions": { "./**/@babel/parser": "7.7.4", "./**/@babel/types": "7.7.4", "@babel/generator": "7.2.0", "@babel/preset-flow": "7.22.5" } } ================================================ FILE: compiler/packages/snap/scripts/link-react-compiler-runtime.sh ================================================ #!/usr/bin/env bash # Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. set -eo pipefail yarn --silent workspace react-compiler-runtime link yarn --silent workspace snap link react-compiler-runtime ================================================ FILE: compiler/packages/snap/src/SproutTodoFilter.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ const skipFilter = new Set([ /** * Observable different in logging between Forget and non-Forget */ 'early-return-no-declarations-reassignments-dependencies', /** * Category A: * Tests with 0 parameters and 0 refs to external values */ // TODO: fix invalid .set call 'assignment-variations-complex-lvalue-array', // TODO: uses jsx (requires React) 'sketchy-code-rules-of-hooks', // TODO: fix infinite loop 'ssa-for-trivial-update', // TODO: fix infinite loop 'ssa-while-no-reassign', /** * Category B: * Tests with at least one param and 0 refs to external values */ 'bug.useMemo-deps-array-not-cleared', 'capture_mutate-across-fns', 'capture-indirect-mutate-alias', 'capturing-arrow-function-1', 'capturing-func-mutate-3', 'capturing-func-mutate-nested', 'capturing-function-1', 'capturing-function-alias-computed-load', 'capturing-function-decl', 'capturing-function-skip-computed-path', 'capturing-function-within-block', 'capturing-member-expr', 'capturing-nested-member-call', 'capturing-nested-member-expr-in-nested-func', 'capturing-nested-member-expr', 'capturing-variable-in-nested-block', 'capturing-variable-in-nested-function', 'complex-while', 'component', 'cond-deps-conditional-member-expr', 'conditional-break-labeled', 'propagate-scope-deps-hir-fork/conditional-break-labeled', 'conditional-set-state-in-render', 'constant-computed', 'constant-propagation-phi', 'debugger-memoized', 'debugger', 'declare-reassign-variable-in-closure', 'delete-computed-property', 'delete-property', 'dependencies-outputs', 'dependencies', 'destructure-direct-reassignment', 'destructuring-array-default', 'destructuring-array-param-default', 'destructuring-assignment-array-default', 'destructuring-assignment', 'destructuring-object-default', 'destructuring-object-param-default', 'destructuring', 'disable-jsx-memoization', 'do-while-break', 'do-while-compound-test', 'dominator', 'early-return', 'escape-analysis-destructured-rest-element', 'escape-analysis-jsx-child', 'escape-analysis-logical', 'escape-analysis-non-escaping-interleaved-allocating-dependency', 'escape-analysis-non-escaping-interleaved-allocating-nested-dependency', 'escape-analysis-non-escaping-interleaved-primitive-dependency', 'escape-analysis-not-conditional-test', 'escape-analysis-not-if-test', 'escape-analysis-not-switch-case', 'escape-analysis-not-switch-test', 'expression-with-assignment-dynamic', 'extend-scopes-if', 'fbt/fbt-params', 'for-empty-update-with-continue', 'for-empty-update', 'for-logical', 'for-return', 'function-declaration-simple', 'function-param-assignment-pattern', 'globals-Boolean', 'globals-Number', 'globals-String', 'holey-array-pattern-dce-2', 'holey-array-pattern-dce', 'holey-array', 'independently-memoize-object-property', 'inverted-if-else', 'inverted-if', 'jsx-empty-expression', 'jsx-fragment', 'jsx-namespaced-name', 'lambda-mutated-non-reactive-to-reactive', 'lambda-mutated-ref-non-reactive', 'logical-expression-object', 'logical-expression', 'nested-function-shadowed-identifiers', 'nonoptional-load-from-optional-memberexpr', 'object-computed-access-assignment', 'object-expression-string-literal-key', 'object-literal-spread-element', 'object-pattern-params', 'optional-member-expression-chain', 'overlapping-scopes-interleaved-by-terminal', 'overlapping-scopes-interleaved', 'overlapping-scopes-shadowed', 'overlapping-scopes-shadowing-within-block', 'overlapping-scopes-while', 'overlapping-scopes-within-block', 'prop-capturing-function-1', 'reactive-scopes-if', 'reactive-scopes', 'reactivity-analysis-interleaved-reactivity', 'reassign-object-in-context', 'reassignment-separate-scopes', 'return-conditional', 'return-undefined', 'reverse-postorder', 'same-variable-as-dep-and-redeclare-maybe-frozen', 'same-variable-as-dep-and-redeclare', 'simple-scope', 'ssa-arrayexpression', 'ssa-for-of', 'ssa-multiple-phis', 'ssa-nested-loops-no-reassign', 'ssa-nested-partial-phi', 'ssa-nested-partial-reassignment', 'ssa-non-empty-initializer', 'ssa-objectexpression', 'ssa-property-alias-if', 'ssa-reassign', 'ssa-renaming-via-destructuring', 'ssa-renaming', 'ssa-sibling-phis', 'switch-with-fallthrough', 'ternary-assignment-expression', 'ternary-expression', 'trivial', 'type-args-test-binary-operator', 'type-cast-expression.flow', 'unary-expr', 'unconditional-break-label', 'unused-array-middle-element', 'unused-array-rest-element', 'unused-conditional', 'unused-logical', 'unused-object-element-with-rest', 'unused-object-element', 'useMemo-inlining-block-return', 'useMemo-inverted-if', 'useMemo-labeled-statement-unconditional-return', 'useMemo-logical', 'useMemo-nested-ifs', 'useMemo-switch-no-fallthrough', 'useMemo-switch-return', 'while-break', 'while-conditional-continue', 'while-logical', 'while-property', 'validate-no-set-state-in-render-uncalled-function-with-mutable-range-is-valid', // Category B with multiple entrypoints, 'conditional-break', /** * Category C: * Tests with at 0 params and at least one ref to external values */ 'alias-capture-in-method-receiver', 'alias-nested-member-path-mutate', 'concise-arrow-expr', 'const-propagation-into-function-expression-global', 'lambda-mutate-shadowed-object', 'fbt/lambda-with-fbt', 'recursive-function-expr', 'ref-current-aliased-no-added-to-dep', 'ref-current-field-not-added-to-dep', 'ref-current-not-added-to-dep', 'ref-current-optional-field-no-added-to-dep', 'ref-current-write-not-added-to-dep', 'rewrite-phis-in-lambda-capture-context', 'sketchy-code-exhaustive-deps', 'ssa-property-alias-mutate', 'ssa-property-mutate-2', 'ssa-property-mutate-alias', 'ssa-property-mutate', 'ssa-reassign-in-rval', 'store-via-call', 'store-via-new', 'tagged-template-literal', 'transitive-alias-fields', 'type-binary-operator', 'type-test-field-load-binary-op', 'type-test-polymorphic', 'type-test-return-type-inference', 'use-callback-simple', // defines two functions 'simple-alias', /** * Category D: * Tests with one or more params, with external references. */ 'alias-computed-load', 'allocating-primitive-as-dep', 'allow-passing-refs-as-props', 'array-at-closure', 'array-at-effect', 'array-at-mutate-after-capture', 'array-join', 'array-push-effect', 'assignment-in-nested-if', 'await-side-effecting-promise', 'await', 'builtin-jsx-tag-lowered-between-mutations', 'call-args-assignment', 'call-args-destructuring-assignment', 'call-with-independently-memoizable-arg', 'capture-param-mutate', 'capturing-function-conditional-capture-mutate', 'capturing-function-member-expr-arguments', 'capturing-function-member-expr-call', 'codegen-emit-imports-same-source', 'codegen-emit-make-read-only', 'computed-call-spread', 'computed-load-primitive-as-dependency', 'destructuring-mixed-scope-declarations-and-locals', 'destructuring-property-inference', 'do-while-conditional-break', 'do-while-early-unconditional-break', 'fbt/fbt-params-complex-param-value', 'function-expression-captures-value-later-frozen-jsx', 'function-expression-maybe-mutates-hook-return-value', 'function-expression-with-store-to-parameter', 'global-jsx-tag-lowered-between-mutations', 'hook-inside-logical-expression', 'immutable-hooks', 'inadvertent-mutability-readonly-class', 'inadvertent-mutability-readonly-lambda', 'infer-computed-delete', 'infer-property-delete', 'inner-memo-value-not-promoted-to-outer-scope-dynamic', 'inner-memo-value-not-promoted-to-outer-scope-static', 'issue852', 'jsx-member-expression-tag-grouping', 'jsx-member-expression', 'jsx-spread', 'lambda-capture-returned-alias', 'method-call-computed', 'method-call-fn-call', 'nested-optional-member-expr', 'nested-scopes-hook-call', 'new-spread', 'obj-literal-cached-in-if-else', 'obj-literal-mutated-after-if-else', 'obj-mutated-after-if-else-with-alias', 'obj-mutated-after-if-else', 'obj-mutated-after-nested-if-else-with-alias', 'object-properties', 'optional-call-chained', 'optional-call-logical', 'optional-call-simple', 'optional-call-with-independently-memoizable-arg', 'optional-call-with-optional-property-load', 'optional-call', 'optional-computed-load-static', 'optional-computed-member-expression', 'optional-member-expression-call-as-property', 'optional-member-expression-with-optional-member-expr-as-property', 'optional-member-expression', 'optional-method-call', 'optional-receiver-method-call', 'optional-receiver-optional-method', 'primitive-alias-mutate', 'primitive-as-dep', 'property-assignment', 'property-call-spread', 'reactive-dependencies-non-optional-properties-inside-optional-chain', 'reactivity-analysis-reactive-via-mutation-of-computed-load', 'reactivity-analysis-reactive-via-mutation-of-property-load', 'reassigned-phi-in-returned-function-expression', 'reassignment-conditional', 'reassignment', 'ref-current-aliased-not-added-to-dep-2', 'ref-current-not-added-to-dep-2', 'ref-in-effect', 'regexp-literal', 'remove-memoization-kitchen-sink', 'repro-reassign-to-variable-without-mutable-range', 'repro-scope-missing-mutable-range', 'repro', 'simple', 'ssa-property-alias-alias-mutate-if', 'ssa-property-alias-mutate-if', 'ssa-property-alias-mutate-inside-if', 'switch-global-propertyload-case-test', 'switch-non-final-default', 'switch', 'tagged-template-in-hook', 'temporary-accessed-outside-scope', 'temporary-at-start-of-value-block', 'temporary-property-load-accessed-outside-scope', 'timers', 'todo-function-expression-captures-value-later-frozen', 'uninitialized-declaration-in-reactive-scope', 'unknown-hooks-do-not-assert', 'unused-logical-assigned-to-variable', 'unused-optional-method-assigned-to-variable', 'unused-ternary-assigned-to-variable', 'useEffect-arg-memoized', 'useEffect-nested-lambdas', 'useMemo-if-else-multiple-return', 'useMemo-independently-memoizeable', 'useMemo-named-function', 'useMemo-return-empty', 'useMemo-simple', 'use-no-forget-module-level', 'use-no-memo-module-level', // defines multiple functions 'alias-while', 'babel-existing-react-import', 'babel-existing-react-kitchensink-import', 'call', 'codegen-instrument-forget-test', 'conditional-on-mutable', 'constructor', 'frozen-after-alias', 'hook-call', 'hooks-freeze-arguments', 'hooks-freeze-possibly-mutable-arguments', 'independent-across-if', 'independent', 'interdependent-across-if', 'interdependent', 'mutable-liverange-loop', 'sequence-expression', 'ssa-call-jsx-2', 'ssa-call-jsx', 'ssa-newexpression', 'ssa-shadowing', 'template-literal', // works, but appears differently when printing // due to optional function argument 'nested-function-with-param-as-captured-dep', 'deeply-nested-function-expressions-with-params', // TODO: we should be able to support these 'readonly-object-method-calls', 'readonly-object-method-calls-mutable-lambda', 'preserve-memo-validation/useMemo-with-refs.flow', // TODO: we probably want to always skip these 'rules-of-hooks/rules-of-hooks-0592bd574811', 'rules-of-hooks/rules-of-hooks-0e2214abc294', 'rules-of-hooks/rules-of-hooks-1ff6c3fbbc94', 'rules-of-hooks/rules-of-hooks-23dc7fffde57', 'rules-of-hooks/rules-of-hooks-2bec02ac982b', 'rules-of-hooks/rules-of-hooks-2e405c78cb80', 'rules-of-hooks/rules-of-hooks-33a6e23edac1', 'rules-of-hooks/rules-of-hooks-347b0dae66f1', 'rules-of-hooks/rules-of-hooks-485bf041f55f', 'rules-of-hooks/rules-of-hooks-4f6c78a14bf7', 'rules-of-hooks/rules-of-hooks-7e52f5eec669', 'rules-of-hooks/rules-of-hooks-844a496db20b', 'rules-of-hooks/rules-of-hooks-8f1c2c3f71c9', 'rules-of-hooks/rules-of-hooks-9a47e97b5d13', 'rules-of-hooks/rules-of-hooks-9d7879272ff6', 'rules-of-hooks/rules-of-hooks-c1e8c7f4c191', 'rules-of-hooks/rules-of-hooks-c5d1f3143c4c', 'rules-of-hooks/rules-of-hooks-cfdfe5572fc7', 'rules-of-hooks/rules-of-hooks-df4d750736f3', 'rules-of-hooks/rules-of-hooks-dfde14171fcd', 'rules-of-hooks/rules-of-hooks-e5dd6caf4084', 'rules-of-hooks/rules-of-hooks-e66a744cffbe', 'rules-of-hooks/rules-of-hooks-eacfcaa6ef89', 'rules-of-hooks/rules-of-hooks-fe6042f7628b', 'infer-function-assignment', 'infer-functions-component-with-jsx', 'infer-function-forwardRef', 'infer-function-React-memo', 'infer-functions-component-with-hook-call', 'infer-functions-component-with-jsx', 'infer-functions-hook-with-hook-call', 'infer-functions-hook-with-jsx', 'infer-function-expression-component', 'infer-skip-components-without-hooks-or-jsx', 'class-component-with-render-helper', 'fbt/fbtparam-with-jsx-element-content', 'fbt/fbtparam-text-must-use-expression-container', 'fbt/fbtparam-with-jsx-fragment-value', 'todo.useContext-mutate-context-in-callback', 'loop-unused-let', 'reanimated-no-memo-arg', 'reanimated-shared-value-writes', 'userspace-use-memo-cache', 'transitive-freeze-function-expressions', // nothing to compile/run 'gating/repro-no-gating-import-without-compiled-functions', // TODOs 'rules-of-hooks/todo.bail.rules-of-hooks-279ac76f53af', 'rules-of-hooks/todo.bail.rules-of-hooks-28a78701970c', 'rules-of-hooks/todo.bail.rules-of-hooks-3d692676194b', 'rules-of-hooks/todo.bail.rules-of-hooks-6949b255e7eb', 'rules-of-hooks/todo.bail.rules-of-hooks-8503ca76d6f8', 'rules-of-hooks/todo.bail.rules-of-hooks-e0a5db3ae21e', 'rules-of-hooks/todo.bail.rules-of-hooks-e9f9bac89f8f', 'rules-of-hooks/todo.bail.rules-of-hooks-fadd52c1e460', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-0a1dbff27ba0', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-0de1224ce64b', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-191029ac48c8', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-206e2811c87c', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-28a7111f56a7', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-2c51251df67a', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-449a37146a83', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-5a7ac9a6e8fa', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-76a74b4666e9', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-8303403b8e4c', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-99b5c750d1d1', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-9c79feec4b9b', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-a63fd4f9dcc0', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-acb56658fe7e', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-c59788ef5676', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-d842d36db450', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-d952b82c2597', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-ddeca9708b63', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-e675f0a672d8', 'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-e69ffce323c3', 'todo.unnecessary-lambda-memoization', 'rules-of-hooks/rules-of-hooks-93dc5d5e538a', 'rules-of-hooks/rules-of-hooks-69521d94fa03', // false positives 'invalid-jsx-lowercase-localvar', // bugs 'inner-function/nullable-objects/bug-invalid-array-map-manual', 'bug-object-expression-computed-key-modified-during-after-construction-hoisted-sequence-expr', `bug-capturing-func-maybealias-captured-mutate`, 'bug-aliased-capture-aliased-mutate', 'bug-aliased-capture-mutate', 'bug-functiondecl-hoisting', 'bug-type-inference-control-flow', 'fbt/bug-fbt-plural-multiple-function-calls', 'fbt/bug-fbt-plural-multiple-mixed-call-tag', 'bug-invalid-phi-as-dependency', 'bug-ref-prefix-postfix-operator', // 'react-compiler-runtime' not yet supported 'flag-enable-emit-hook-guards', 'fast-refresh-refresh-on-const-changes-dev', 'useState-pruned-dependency-change-detect', 'useState-unpruned-dependency', 'useState-and-other-hook-unpruned-dependency', 'change-detect-reassign', // Depends on external functions 'idx-method-no-outlining-wildcard', 'idx-method-no-outlining', 'target-flag-meta-internal', // needs to be executed as a module 'meta-property', // needs context lowering support in React 'todo.lower-context-access-property-load', 'todo.lower-context-access-nested-destructuring', 'todo.lower-context-access-mixed-array-obj', 'todo.lower-context-access-destructure-multiple', 'todo.lower-context-access-array-destructuring', 'lower-context-selector-simple', 'lower-context-acess-multiple', 'bug-separate-memoization-due-to-callback-capturing', // SSR optimization rewrites files in a way that causes differences or warnings 'ssr/optimize-ssr', 'ssr/ssr-use-reducer', 'ssr/ssr-use-reducer-initializer', 'ssr/infer-event-handlers-from-setState', 'ssr/infer-event-handlers-from-startTransition', ]); export default skipFilter; ================================================ FILE: compiler/packages/snap/src/compiler.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import type * as BabelCore from '@babel/core'; import {transformFromAstSync} from '@babel/core'; import * as BabelParser from '@babel/parser'; import {NodePath} from '@babel/traverse'; import * as t from '@babel/types'; import type { Logger, LoggerEvent, PluginOptions, CompilerReactTarget, CompilerPipelineValue, } from 'babel-plugin-react-compiler/src/Entrypoint'; import type { Effect, ValueKind, ValueReason, } from 'babel-plugin-react-compiler/src/HIR'; import type {parseConfigPragmaForTests as ParseConfigPragma} from 'babel-plugin-react-compiler/src/Utils/TestUtils'; import * as HermesParser from 'hermes-parser'; import invariant from 'invariant'; import path from 'path'; import prettier from 'prettier'; import SproutTodoFilter from './SproutTodoFilter'; import {isExpectError} from './fixture-utils'; import {makeSharedRuntimeTypeProvider} from './sprout/shared-runtime-type-provider'; export function parseLanguage(source: string): 'flow' | 'typescript' { return source.indexOf('@flow') !== -1 ? 'flow' : 'typescript'; } export function parseSourceType(source: string): 'script' | 'module' { return source.indexOf('@script') !== -1 ? 'script' : 'module'; } /** * Parse react compiler plugin + environment options from test fixture. Note * that although this primarily uses `Environment:parseConfigPragma`, it also * has test fixture specific (i.e. not applicable to playground) parsing logic. */ function makePluginOptions( firstLine: string, parseConfigPragmaFn: typeof ParseConfigPragma, debugIRLogger: (value: CompilerPipelineValue) => void, EffectEnum: typeof Effect, ValueKindEnum: typeof ValueKind, ValueReasonEnum: typeof ValueReason, ): { options: PluginOptions; loggerTestOnly: boolean; logs: Array<{filename: string | null; event: LoggerEvent}>; } { // TODO(@mofeiZ) rewrite snap fixtures to @validatePreserveExistingMemo:false let validatePreserveExistingMemoizationGuarantees = false; let target: CompilerReactTarget = '19'; /** * Snap currently runs all fixtures without `validatePreserveExistingMemo` as * most fixtures are interested in compilation output, not whether the * compiler was able to preserve existing memo. * * TODO: flip the default. `useMemo` is rare in test fixtures -- fixtures that * use useMemo should be explicit about whether this flag is enabled */ if (firstLine.includes('@validatePreserveExistingMemoizationGuarantees')) { validatePreserveExistingMemoizationGuarantees = true; } const loggerTestOnly = firstLine.includes('@loggerTestOnly'); const logs: Array<{filename: string | null; event: LoggerEvent}> = []; const logger: Logger = { logEvent: (filename, event) => { logs.push({filename, event}); }, debugLogIRs: debugIRLogger, }; const config = parseConfigPragmaFn(firstLine, {compilationMode: 'all'}); const options = { ...config, environment: { ...config.environment, moduleTypeProvider: makeSharedRuntimeTypeProvider({ EffectEnum, ValueKindEnum, ValueReasonEnum, }), assertValidMutableRanges: true, validatePreserveExistingMemoizationGuarantees, }, logger, enableReanimatedCheck: false, target, }; return {options, loggerTestOnly, logs}; } export function parseInput( input: string, filename: string, language: 'flow' | 'typescript', sourceType: 'module' | 'script', ): BabelCore.types.File { // Extract the first line to quickly check for custom test directives if (language === 'flow') { return HermesParser.parse(input, { babel: true, flow: 'all', sourceFilename: filename, sourceType, enableExperimentalComponentSyntax: true, }); } else { return BabelParser.parse(input, { sourceFilename: filename, plugins: ['typescript', 'jsx'], sourceType, }); } } function getEvaluatorPresets( language: 'typescript' | 'flow', ): Array { const presets: Array = [ { plugins: [ 'babel-plugin-fbt', 'babel-plugin-fbt-runtime', 'babel-plugin-idx', ], }, ]; presets.push( language === 'typescript' ? [ '@babel/preset-typescript', { /** * onlyRemoveTypeImports needs to be set as fbt imports * would otherwise be removed by this pass. * https://github.com/facebook/fbt/issues/49 * https://github.com/facebook/sfbt/issues/72 * https://dev.to/retyui/how-to-add-support-typescript-for-fbt-an-internationalization-framework-3lo0 */ onlyRemoveTypeImports: true, }, ] : '@babel/preset-flow', ); presets.push({ plugins: ['@babel/plugin-syntax-jsx'], }); presets.push( ['@babel/preset-react', {throwIfNamespace: false}], { plugins: ['@babel/plugin-transform-modules-commonjs'], }, { plugins: [ function BabelPluginRewriteRequirePath() { return { visitor: { CallExpression(path: NodePath) { const {callee} = path.node; if (callee.type === 'Identifier' && callee.name === 'require') { const arg = path.node.arguments[0]; if (arg.type === 'StringLiteral') { // rewrite to use relative import as eval happens in // sprout/evaluator.ts if (arg.value === 'shared-runtime') { arg.value = './shared-runtime'; } else if (arg.value === 'ReactForgetFeatureFlag') { arg.value = './ReactForgetFeatureFlag'; } else if (arg.value === 'useEffectWrapper') { arg.value = './useEffectWrapper'; } } } }, }, }; }, ], }, ); return presets; } async function format( inputCode: string, language: 'typescript' | 'flow', ): Promise { return await prettier.format(inputCode, { semi: true, parser: language === 'typescript' ? 'babel-ts' : 'flow', }); } const TypescriptEvaluatorPresets = getEvaluatorPresets('typescript'); const FlowEvaluatorPresets = getEvaluatorPresets('flow'); export type TransformResult = { forgetOutput: string; logs: string | null; evaluatorCode: { original: string; forget: string; } | null; }; export async function transformFixtureInput( input: string, fixturePath: string, parseConfigPragmaFn: typeof ParseConfigPragma, plugin: BabelCore.PluginObj, includeEvaluator: boolean, debugIRLogger: (value: CompilerPipelineValue) => void, EffectEnum: typeof Effect, ValueKindEnum: typeof ValueKind, ValueReasonEnum: typeof ValueReason, ): Promise<{kind: 'ok'; value: TransformResult} | {kind: 'err'; msg: string}> { // Extract the first line to quickly check for custom test directives const firstLine = input.substring(0, input.indexOf('\n')); const language = parseLanguage(firstLine); const sourceType = parseSourceType(firstLine); // Preserve file extension as it determines typescript's babel transform // mode (e.g. stripping types, parsing rules for brackets) const filename = path.basename(fixturePath) + (language === 'typescript' ? '.ts' : ''); const inputAst = parseInput(input, filename, language, sourceType); // Give babel transforms an absolute path as relative paths get prefixed // with `cwd`, which is different across machines const virtualFilepath = '/' + filename; const presets = language === 'typescript' ? TypescriptEvaluatorPresets : FlowEvaluatorPresets; /** * Get Forget compiled code */ const {options, loggerTestOnly, logs} = makePluginOptions( firstLine, parseConfigPragmaFn, debugIRLogger, EffectEnum, ValueKindEnum, ValueReasonEnum, ); const forgetResult = transformFromAstSync(inputAst, input, { filename: virtualFilepath, highlightCode: false, retainLines: true, compact: true, plugins: [ [plugin, options], 'babel-plugin-fbt', 'babel-plugin-fbt-runtime', 'babel-plugin-idx', ], sourceType: 'module', ast: includeEvaluator, cloneInputAst: includeEvaluator, configFile: false, babelrc: false, }); invariant( forgetResult?.code != null, 'Expected BabelPluginReactForget to codegen successfully.', ); const forgetCode = forgetResult.code; let evaluatorCode = null; if ( includeEvaluator && !SproutTodoFilter.has(fixturePath) && !isExpectError(filename) ) { let forgetEval: string; try { invariant( forgetResult?.ast != null, 'Expected BabelPluginReactForget ast.', ); const result = transformFromAstSync(forgetResult.ast, forgetCode, { presets, filename: virtualFilepath, configFile: false, babelrc: false, }); if (result?.code == null) { return { kind: 'err', msg: 'Unexpected error in forget transform pipeline - no code emitted', }; } else { forgetEval = result.code; } } catch (e) { return { kind: 'err', msg: 'Unexpected error in Forget transform pipeline: ' + e.message, }; } /** * Get evaluator code for source (no Forget) */ let originalEval: string; try { const result = transformFromAstSync(inputAst, input, { presets, filename: virtualFilepath, configFile: false, babelrc: false, }); if (result?.code == null) { return { kind: 'err', msg: 'Unexpected error in non-forget transform pipeline - no code emitted', }; } else { originalEval = result.code; } } catch (e) { return { kind: 'err', msg: 'Unexpected error in non-forget transform pipeline: ' + e.message, }; } evaluatorCode = { forget: forgetEval, original: originalEval, }; } const forgetOutput = await format(forgetCode, language); let formattedLogs = null; if (loggerTestOnly && logs.length !== 0) { formattedLogs = logs .map(({event}) => { return JSON.stringify(event, (key, value) => { if ( key === 'detail' && value != null && typeof value.serialize === 'function' ) { return value.serialize(); } return value; }); }) .join('\n'); } const expectNothingCompiled = firstLine.indexOf('@expectNothingCompiled') !== -1; const successFailures = logs.filter( log => log.event.kind === 'CompileSuccess' || log.event.kind === 'CompileError', ); if (successFailures.length === 0 && !expectNothingCompiled) { return { kind: 'err', msg: 'No success/failure events, add `// @expectNothingCompiled` to the first line if this is expected', }; } else if (successFailures.length !== 0 && expectNothingCompiled) { return { kind: 'err', msg: 'Expected nothing to be compiled (from `// @expectNothingCompiled`), but some functions compiled or errored', }; } const unexpectedThrows = logs.filter( log => log.event.kind === 'CompileUnexpectedThrow', ); if (unexpectedThrows.length > 0) { return { kind: 'err', msg: `Compiler pass(es) threw instead of recording errors:\n` + unexpectedThrows.map(l => (l.event as any).data).join('\n'), }; } return { kind: 'ok', value: { forgetOutput, logs: formattedLogs, evaluatorCode, }, }; } ================================================ FILE: compiler/packages/snap/src/constants.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import path from 'path'; export const PROJECT_ROOT = path.join(process.cwd(), '..', '..'); // We assume this is run from `babel-plugin-react-compiler` export const BABEL_PLUGIN_ROOT = path.normalize( path.join(PROJECT_ROOT, 'packages', 'babel-plugin-react-compiler'), ); export const BABEL_PLUGIN_SRC = path.normalize( path.join(BABEL_PLUGIN_ROOT, 'dist', 'index.js'), ); export const PRINT_HIR_IMPORT = 'printFunctionWithOutlined'; export const PRINT_REACTIVE_IR_IMPORT = 'printReactiveFunction'; export const PARSE_CONFIG_PRAGMA_IMPORT = 'parseConfigPragmaForTests'; export const FIXTURES_PATH = path.join( BABEL_PLUGIN_ROOT, 'src', '__tests__', 'fixtures', 'compiler', ); export const SNAPSHOT_EXTENSION = '.expect.md'; ================================================ FILE: compiler/packages/snap/src/fixture-utils.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import fs from 'fs/promises'; import * as glob from 'glob'; import path from 'path'; import {FIXTURES_PATH, SNAPSHOT_EXTENSION} from './constants'; const INPUT_EXTENSIONS = [ '.js', '.cjs', '.mjs', '.ts', '.cts', '.mts', '.jsx', '.tsx', ]; export type TestFilter = { paths: Array; }; function stripExtension(filename: string, extensions: Array): string { for (const ext of extensions) { if (filename.endsWith(ext)) { return filename.slice(0, -ext.length); } } return filename; } export function getBasename(fixture: TestFixture): string { return stripExtension(path.basename(fixture.inputPath), INPUT_EXTENSIONS); } export function isExpectError(fixture: TestFixture | string): boolean { const basename = typeof fixture === 'string' ? fixture : getBasename(fixture); return basename.startsWith('error.') || basename.startsWith('todo.error'); } export type TestFixture = | { fixturePath: string; input: string | null; inputPath: string; snapshot: string | null; snapshotPath: string; } | { fixturePath: string; input: null; inputPath: string; snapshot: string; snapshotPath: string; }; async function readInputFixtures( rootDir: string, filter: TestFilter | null, ): Promise> { let inputFiles: Array; if (filter == null) { inputFiles = glob.sync(`**/*{${INPUT_EXTENSIONS.join(',')}}`, { cwd: rootDir, }); } else { inputFiles = ( await Promise.all( filter.paths.map(pattern => { // If the pattern already has an extension other than .expect.md, // search for the pattern directly. Otherwise, search for the // pattern with the expected input extensions added. // Eg // `alias-while` => search for `alias-while{.js,.jsx,.ts,.tsx}` // `alias-while.js` => search as-is // `alias-while.expect.md` => search for `alias-while{.js,.jsx,.ts,.tsx}` const patternWithoutExt = stripExtension(pattern, [ ...INPUT_EXTENSIONS, SNAPSHOT_EXTENSION, ]); const hasExtension = pattern !== patternWithoutExt; const globPattern = hasExtension && !pattern.endsWith(SNAPSHOT_EXTENSION) ? pattern : `${patternWithoutExt}{${INPUT_EXTENSIONS.join(',')}}`; return glob.glob(globPattern, { cwd: rootDir, }); }), ) ).flat(); } const inputs: Array> = []; for (const filePath of inputFiles) { // Do not include extensions in unique identifier for fixture const partialPath = stripExtension(filePath, INPUT_EXTENSIONS); inputs.push( fs.readFile(path.join(rootDir, filePath), 'utf8').then(input => { return [ partialPath, { value: input, filepath: filePath, }, ]; }), ); } return new Map(await Promise.all(inputs)); } async function readOutputFixtures( rootDir: string, filter: TestFilter | null, ): Promise> { let outputFiles: Array; if (filter == null) { outputFiles = glob.sync(`**/*${SNAPSHOT_EXTENSION}`, { cwd: rootDir, }); } else { outputFiles = ( await Promise.all( filter.paths.map(pattern => { // Strip all extensions and find matching .expect.md files const basenameWithoutExt = stripExtension(pattern, [ ...INPUT_EXTENSIONS, SNAPSHOT_EXTENSION, ]); return glob.glob(`${basenameWithoutExt}${SNAPSHOT_EXTENSION}`, { cwd: rootDir, }); }), ) ).flat(); } const outputs: Array> = []; for (const filePath of outputFiles) { // Do not include extensions in unique identifier for fixture const partialPath = stripExtension(filePath, [SNAPSHOT_EXTENSION]); const outputPath = path.join(rootDir, filePath); const output: Promise<[string, string]> = fs .readFile(outputPath, 'utf8') .then(output => { return [partialPath, output]; }); outputs.push(output); } return new Map(await Promise.all(outputs)); } export async function getFixtures( filter: TestFilter | null, ): Promise> { const inputs = await readInputFixtures(FIXTURES_PATH, filter); const outputs = await readOutputFixtures(FIXTURES_PATH, filter); const fixtures: Map = new Map(); for (const [partialPath, {value, filepath}] of inputs) { const output = outputs.get(partialPath) ?? null; fixtures.set(partialPath, { fixturePath: partialPath, input: value, inputPath: filepath, snapshot: output, snapshotPath: path.join(FIXTURES_PATH, partialPath) + SNAPSHOT_EXTENSION, }); } for (const [partialPath, output] of outputs) { if (!fixtures.has(partialPath)) { fixtures.set(partialPath, { fixturePath: partialPath, input: null, inputPath: 'none', snapshot: output, snapshotPath: path.join(FIXTURES_PATH, partialPath) + SNAPSHOT_EXTENSION, }); } } return fixtures; } ================================================ FILE: compiler/packages/snap/src/main.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import {fork} from 'child_process'; import invariant from 'invariant'; import process from 'process'; import * as readline from 'readline'; import {hideBin} from 'yargs/helpers'; readline.emitKeypressEvents(process.stdin); if (process.stdin.isTTY) { process.stdin.setRawMode(true); } process.stdin.on('keypress', function (_, key) { if (key && key.name === 'c' && key.ctrl) { // handle sigint if (childProc) { console.log('Interrupted!!'); childProc.kill('SIGINT'); childProc.unref(); process.exit(-1); } } }); const childProc = fork(require.resolve('./runner.js'), hideBin(process.argv), { // for some reason, keypress events aren't sent to handlers in both processes // when we `inherit` stdin. // pipe stdout and stderr so we can silence child process after parent exits stdio: ['pipe', 'pipe', 'pipe', 'ipc'], // forward existing env variables, like `NODE_OPTIONS` which VSCode uses to attach // its debugger env: {...process.env, FORCE_COLOR: 'true'}, }); invariant( childProc.stdin && childProc.stdout && childProc.stderr, 'Expected forked process to have piped stdio', ); process.stdin.pipe(childProc.stdin); childProc.stdout.pipe(process.stdout); childProc.stderr.pipe(process.stderr); childProc.on('exit', code => { process.exit(code ?? -1); }); ================================================ FILE: compiler/packages/snap/src/minimize.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import type {PluginObj} from '@babel/core'; import {transformFromAstSync} from '@babel/core'; import generate from '@babel/generator'; import traverse from '@babel/traverse'; import * as t from '@babel/types'; import type {parseConfigPragmaForTests as ParseConfigPragma} from 'babel-plugin-react-compiler/src/Utils/TestUtils'; import {parseInput} from './compiler.js'; import {PARSE_CONFIG_PRAGMA_IMPORT, BABEL_PLUGIN_SRC} from './constants.js'; type CompileSuccess = {kind: 'success'}; type CompileParseError = {kind: 'parse_error'; message: string}; type CompileErrors = { kind: 'errors'; errors: Array<{category: string; reason: string; description: string | null}>; }; type CompileResult = CompileSuccess | CompileParseError | CompileErrors; /** * Compile code and extract error information */ function compileAndGetError( code: string, filename: string, language: 'flow' | 'typescript', sourceType: 'module' | 'script', plugin: PluginObj, parseConfigPragmaFn: typeof ParseConfigPragma, ): CompileResult { let ast: t.File; try { ast = parseInput(code, filename, language, sourceType); } catch (e: unknown) { return {kind: 'parse_error', message: (e as Error).message}; } const firstLine = code.substring(0, code.indexOf('\n')); const config = parseConfigPragmaFn(firstLine, {compilationMode: 'all'}); const options = { ...config, environment: { ...config.environment, }, logger: { logEvent: () => {}, debugLogIRs: () => {}, }, enableReanimatedCheck: false, }; try { transformFromAstSync(ast, code, { filename: '/' + filename, highlightCode: false, retainLines: true, compact: true, plugins: [[plugin, options]], sourceType: 'module', ast: false, cloneInputAst: true, configFile: false, babelrc: false, }); return {kind: 'success'}; } catch (e: unknown) { const error = e as Error & { details?: Array<{ category: string; reason: string; description: string | null; }>; }; // Check if this is a CompilerError with details if (error.details && error.details.length > 0) { return { kind: 'errors', errors: error.details.map(detail => ({ category: detail.category, reason: detail.reason, description: detail.description, })), }; } // Fallback for other errors - use error name/message return { kind: 'errors', errors: [ { category: error.name ?? 'Error', reason: error.message, description: null, }, ], }; } } /** * Check if two compile errors match */ function errorsMatch(a: CompileErrors, b: CompileResult): boolean { if (b.kind !== 'errors') { return false; } if (a.errors.length !== b.errors.length) { return false; } for (let i = 0; i < a.errors.length; i++) { if ( a.errors[i].category !== b.errors[i].category || a.errors[i].reason !== b.errors[i].reason || a.errors[i].description !== b.errors[i].description ) { return false; } } return true; } /** * Convert AST to code string */ function astToCode(ast: t.File): string { return generate(ast).code; } /** * Clone an AST node deeply */ function cloneAst(ast: t.File): t.File { return t.cloneNode(ast, true); } /** * Generator that yields ASTs with statements removed one at a time */ function* removeStatements(ast: t.File): Generator { // Collect all statement locations: which container (by index) and which statement index const statementLocations: Array<{containerIndex: number; stmtIndex: number}> = []; let containerIndex = 0; t.traverseFast(ast, node => { if (t.isBlockStatement(node) || t.isProgram(node)) { const body = node.body as t.Statement[]; // Iterate in reverse order so removing later statements first for (let i = body.length - 1; i >= 0; i--) { statementLocations.push({containerIndex, stmtIndex: i}); } containerIndex++; } }); for (const { containerIndex: targetContainerIdx, stmtIndex, } of statementLocations) { const cloned = cloneAst(ast); let idx = 0; let modified = false; t.traverseFast(cloned, node => { if (modified) return; if (t.isBlockStatement(node) || t.isProgram(node)) { if (idx === targetContainerIdx) { const body = node.body as t.Statement[]; if (stmtIndex < body.length) { body.splice(stmtIndex, 1); modified = true; } } idx++; } }); if (modified) { yield cloned; } } } /** * Generator that yields ASTs with call arguments removed one at a time */ function* removeCallArguments(ast: t.File): Generator { // Collect all call expressions with their argument counts const callSites: Array<{callIndex: number; argCount: number}> = []; let callIndex = 0; t.traverseFast(ast, node => { if (t.isCallExpression(node) && node.arguments.length > 0) { callSites.push({callIndex, argCount: node.arguments.length}); callIndex++; } }); // For each call site, try removing each argument one at a time (from end to start) for (const {callIndex: targetCallIdx, argCount} of callSites) { for (let argIdx = argCount - 1; argIdx >= 0; argIdx--) { const cloned = cloneAst(ast); let idx = 0; let modified = false; t.traverseFast(cloned, node => { if (modified) return; if (t.isCallExpression(node) && node.arguments.length > 0) { if (idx === targetCallIdx && argIdx < node.arguments.length) { node.arguments.splice(argIdx, 1); modified = true; } idx++; } }); if (modified) { yield cloned; } } } } /** * Generator that yields ASTs with function parameters removed one at a time */ function* removeFunctionParameters(ast: t.File): Generator { // Collect all functions with parameters const funcSites: Array<{funcIndex: number; paramCount: number}> = []; let funcIndex = 0; t.traverseFast(ast, node => { if (t.isFunction(node) && node.params.length > 0) { funcSites.push({funcIndex, paramCount: node.params.length}); funcIndex++; } }); // For each function, try removing each parameter (from end to start) for (const {funcIndex: targetFuncIdx, paramCount} of funcSites) { for (let paramIdx = paramCount - 1; paramIdx >= 0; paramIdx--) { const cloned = cloneAst(ast); let idx = 0; let modified = false; t.traverseFast(cloned, node => { if (modified) return; if (t.isFunction(node) && node.params.length > 0) { if (idx === targetFuncIdx && paramIdx < node.params.length) { node.params.splice(paramIdx, 1); modified = true; } idx++; } }); if (modified) { yield cloned; } } } } /** * Generator that simplifies call expressions by replacing them with their arguments. * For single argument: foo(x) -> x * For multiple arguments: foo(x, y) -> [x, y] */ function* simplifyCallExpressions(ast: t.File): Generator { // Count call expressions with arguments let callCount = 0; t.traverseFast(ast, node => { if (t.isCallExpression(node) && node.arguments.length > 0) { callCount++; } }); // For each call, try replacing with arguments for (let targetIdx = 0; targetIdx < callCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { CallExpression(path) { if (modified) return; if (path.node.arguments.length > 0 && idx === targetIdx) { const args = path.node.arguments; // Filter to only Expression arguments (not SpreadElement) const exprArgs = args.filter((arg): arg is t.Expression => t.isExpression(arg), ); if (exprArgs.length === 0) { idx++; return; } if (exprArgs.length === 1) { // Single argument: replace call with the argument path.replaceWith(exprArgs[0]); } else { // Multiple arguments: replace call with array of arguments path.replaceWith(t.arrayExpression(exprArgs)); } modified = true; } idx++; }, }); if (modified) { yield cloned; } } // Also try replacing with each individual argument for multi-arg calls for (let targetIdx = 0; targetIdx < callCount; targetIdx++) { // First, find the arg count for this call let argCount = 0; let currentIdx = 0; t.traverseFast(ast, node => { if (t.isCallExpression(node) && node.arguments.length > 0) { if (currentIdx === targetIdx) { argCount = node.arguments.length; } currentIdx++; } }); // Try replacing with each argument individually for (let argIdx = 0; argIdx < argCount; argIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { CallExpression(path) { if (modified) return; if (path.node.arguments.length > 0 && idx === targetIdx) { const arg = path.node.arguments[argIdx]; if (t.isExpression(arg)) { path.replaceWith(arg); modified = true; } } idx++; }, }); if (modified) { yield cloned; } } } } /** * Generator that simplifies conditional expressions (a ? b : c) -> a, b, or c */ function* simplifyConditionals(ast: t.File): Generator { // Count conditionals let condCount = 0; t.traverseFast(ast, node => { if (t.isConditionalExpression(node)) { condCount++; } }); // Try replacing with test condition for (let targetIdx = 0; targetIdx < condCount; targetIdx++) { const cloned = cloneAst(ast); let modified = false; let idx = 0; traverse(cloned, { ConditionalExpression(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(path.node.test); modified = true; } idx++; }, }); if (modified) { yield cloned; } } // Try replacing with consequent for (let targetIdx = 0; targetIdx < condCount; targetIdx++) { const cloned = cloneAst(ast); let modified = false; let idx = 0; traverse(cloned, { ConditionalExpression(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(path.node.consequent); modified = true; } idx++; }, }); if (modified) { yield cloned; } } // Also try replacing with alternate for (let targetIdx = 0; targetIdx < condCount; targetIdx++) { const cloned = cloneAst(ast); let modified = false; let idx = 0; traverse(cloned, { ConditionalExpression(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(path.node.alternate); modified = true; } idx++; }, }); if (modified) { yield cloned; } } } /** * Generator that simplifies logical expressions (a && b) -> a or b */ function* simplifyLogicalExpressions(ast: t.File): Generator { // Count logical expressions let logicalCount = 0; t.traverseFast(ast, node => { if (t.isLogicalExpression(node)) { logicalCount++; } }); // Try replacing with left side for (let targetIdx = 0; targetIdx < logicalCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { LogicalExpression(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(path.node.left); modified = true; } idx++; }, }); if (modified) { yield cloned; } } // Try replacing with right side for (let targetIdx = 0; targetIdx < logicalCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { LogicalExpression(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(path.node.right); modified = true; } idx++; }, }); if (modified) { yield cloned; } } } /** * Generator that simplifies optional chains (a?.b) -> a.b */ function* simplifyOptionalChains(ast: t.File): Generator { // Count optional expressions let optionalCount = 0; t.traverseFast(ast, node => { if ( t.isOptionalMemberExpression(node) || t.isOptionalCallExpression(node) ) { optionalCount++; } }); for (let targetIdx = 0; targetIdx < optionalCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { OptionalMemberExpression(path) { if (modified) return; if (idx === targetIdx) { const {object, property, computed} = path.node; path.replaceWith(t.memberExpression(object, property, computed)); modified = true; } idx++; }, OptionalCallExpression(path) { if (modified) return; if (idx === targetIdx) { const {callee, arguments: args} = path.node; if (t.isExpression(callee)) { path.replaceWith(t.callExpression(callee, args)); modified = true; } } idx++; }, }); if (modified) { yield cloned; } } } /** * Generator that simplifies await expressions: await expr -> expr */ function* simplifyAwaitExpressions(ast: t.File): Generator { // Count await expressions let awaitCount = 0; t.traverseFast(ast, node => { if (t.isAwaitExpression(node)) { awaitCount++; } }); for (let targetIdx = 0; targetIdx < awaitCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { AwaitExpression(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(path.node.argument); modified = true; } idx++; }, }); if (modified) { yield cloned; } } } /** * Generator that simplifies if statements: * - Replace with test expression (as expression statement) * - Replace with consequent block * - Replace with alternate block (if present) */ function* simplifyIfStatements(ast: t.File): Generator { // Count if statements let ifCount = 0; t.traverseFast(ast, node => { if (t.isIfStatement(node)) { ifCount++; } }); // Try replacing with test expression for (let targetIdx = 0; targetIdx < ifCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { IfStatement(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(t.expressionStatement(path.node.test)); modified = true; } idx++; }, }); if (modified) { yield cloned; } } // Try replacing with consequent for (let targetIdx = 0; targetIdx < ifCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { IfStatement(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(path.node.consequent); modified = true; } idx++; }, }); if (modified) { yield cloned; } } // Try replacing with alternate (if present) for (let targetIdx = 0; targetIdx < ifCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { IfStatement(path) { if (modified) return; if (idx === targetIdx && path.node.alternate) { path.replaceWith(path.node.alternate); modified = true; } idx++; }, }); if (modified) { yield cloned; } } } /** * Generator that simplifies switch statements: * - Replace with discriminant expression * - Replace with each case's consequent statements */ function* simplifySwitchStatements(ast: t.File): Generator { // Count switch statements let switchCount = 0; t.traverseFast(ast, node => { if (t.isSwitchStatement(node)) { switchCount++; } }); // Try replacing with discriminant for (let targetIdx = 0; targetIdx < switchCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { SwitchStatement(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(t.expressionStatement(path.node.discriminant)); modified = true; } idx++; }, }); if (modified) { yield cloned; } } // For each switch, try replacing with each case's body for (let targetIdx = 0; targetIdx < switchCount; targetIdx++) { // Find case count for this switch let caseCount = 0; let currentIdx = 0; t.traverseFast(ast, node => { if (t.isSwitchStatement(node)) { if (currentIdx === targetIdx) { caseCount = node.cases.length; } currentIdx++; } }); for (let caseIdx = 0; caseIdx < caseCount; caseIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { SwitchStatement(path) { if (modified) return; if (idx === targetIdx) { const switchCase = path.node.cases[caseIdx]; if (switchCase && switchCase.consequent.length > 0) { path.replaceWithMultiple(switchCase.consequent); modified = true; } } idx++; }, }); if (modified) { yield cloned; } } } } /** * Generator that simplifies while statements: * - Replace with test expression * - Replace with body */ function* simplifyWhileStatements(ast: t.File): Generator { // Count while statements let whileCount = 0; t.traverseFast(ast, node => { if (t.isWhileStatement(node)) { whileCount++; } }); // Try replacing with test for (let targetIdx = 0; targetIdx < whileCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { WhileStatement(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(t.expressionStatement(path.node.test)); modified = true; } idx++; }, }); if (modified) { yield cloned; } } // Try replacing with body for (let targetIdx = 0; targetIdx < whileCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { WhileStatement(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(path.node.body); modified = true; } idx++; }, }); if (modified) { yield cloned; } } } /** * Generator that simplifies do-while statements: * - Replace with test expression * - Replace with body */ function* simplifyDoWhileStatements(ast: t.File): Generator { // Count do-while statements let doWhileCount = 0; t.traverseFast(ast, node => { if (t.isDoWhileStatement(node)) { doWhileCount++; } }); // Try replacing with test for (let targetIdx = 0; targetIdx < doWhileCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { DoWhileStatement(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(t.expressionStatement(path.node.test)); modified = true; } idx++; }, }); if (modified) { yield cloned; } } // Try replacing with body for (let targetIdx = 0; targetIdx < doWhileCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { DoWhileStatement(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(path.node.body); modified = true; } idx++; }, }); if (modified) { yield cloned; } } } /** * Generator that simplifies for statements: * - Replace with init (if expression) * - Replace with test expression * - Replace with update expression * - Replace with body */ function* simplifyForStatements(ast: t.File): Generator { // Count for statements let forCount = 0; t.traverseFast(ast, node => { if (t.isForStatement(node)) { forCount++; } }); // Try replacing with init (if it's an expression) for (let targetIdx = 0; targetIdx < forCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { ForStatement(path) { if (modified) return; if (idx === targetIdx && path.node.init) { if (t.isExpression(path.node.init)) { path.replaceWith(t.expressionStatement(path.node.init)); } else { // It's a VariableDeclaration path.replaceWith(path.node.init); } modified = true; } idx++; }, }); if (modified) { yield cloned; } } // Try replacing with test for (let targetIdx = 0; targetIdx < forCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { ForStatement(path) { if (modified) return; if (idx === targetIdx && path.node.test) { path.replaceWith(t.expressionStatement(path.node.test)); modified = true; } idx++; }, }); if (modified) { yield cloned; } } // Try replacing with update for (let targetIdx = 0; targetIdx < forCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { ForStatement(path) { if (modified) return; if (idx === targetIdx && path.node.update) { path.replaceWith(t.expressionStatement(path.node.update)); modified = true; } idx++; }, }); if (modified) { yield cloned; } } // Try replacing with body for (let targetIdx = 0; targetIdx < forCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { ForStatement(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(path.node.body); modified = true; } idx++; }, }); if (modified) { yield cloned; } } } /** * Generator that simplifies for-in statements: * - Replace with left (variable declaration or expression) * - Replace with right expression * - Replace with body */ function* simplifyForInStatements(ast: t.File): Generator { // Count for-in statements let forInCount = 0; t.traverseFast(ast, node => { if (t.isForInStatement(node)) { forInCount++; } }); // Try replacing with left for (let targetIdx = 0; targetIdx < forInCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { ForInStatement(path) { if (modified) return; if (idx === targetIdx) { const left = path.node.left; if (t.isExpression(left)) { path.replaceWith(t.expressionStatement(left)); } else { path.replaceWith(left); } modified = true; } idx++; }, }); if (modified) { yield cloned; } } // Try replacing with right for (let targetIdx = 0; targetIdx < forInCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { ForInStatement(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(t.expressionStatement(path.node.right)); modified = true; } idx++; }, }); if (modified) { yield cloned; } } // Try replacing with body for (let targetIdx = 0; targetIdx < forInCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { ForInStatement(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(path.node.body); modified = true; } idx++; }, }); if (modified) { yield cloned; } } } /** * Generator that simplifies for-of statements: * - Replace with left (variable declaration or expression) * - Replace with right expression * - Replace with body */ function* simplifyForOfStatements(ast: t.File): Generator { // Count for-of statements let forOfCount = 0; t.traverseFast(ast, node => { if (t.isForOfStatement(node)) { forOfCount++; } }); // Try replacing with left for (let targetIdx = 0; targetIdx < forOfCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { ForOfStatement(path) { if (modified) return; if (idx === targetIdx) { const left = path.node.left; if (t.isExpression(left)) { path.replaceWith(t.expressionStatement(left)); } else { path.replaceWith(left); } modified = true; } idx++; }, }); if (modified) { yield cloned; } } // Try replacing with right for (let targetIdx = 0; targetIdx < forOfCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { ForOfStatement(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(t.expressionStatement(path.node.right)); modified = true; } idx++; }, }); if (modified) { yield cloned; } } // Try replacing with body for (let targetIdx = 0; targetIdx < forOfCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { ForOfStatement(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(path.node.body); modified = true; } idx++; }, }); if (modified) { yield cloned; } } } /** * Generator that simplifies variable declarations by removing init expressions. * let x = expr; -> let x; * var x = expr; -> var x; * Note: const without init is invalid, so we skip const declarations. */ function* simplifyVariableDeclarations(ast: t.File): Generator { // Collect all variable declarators with init expressions (excluding const) const declaratorSites: Array<{declIndex: number}> = []; let declIndex = 0; t.traverseFast(ast, node => { if (t.isVariableDeclaration(node) && node.kind !== 'const') { for (const declarator of node.declarations) { if (declarator.init) { declaratorSites.push({declIndex}); declIndex++; } } } }); // Try removing init from each declarator for (const {declIndex: targetDeclIdx} of declaratorSites) { const cloned = cloneAst(ast); let idx = 0; let modified = false; t.traverseFast(cloned, node => { if (modified) return; if (t.isVariableDeclaration(node) && node.kind !== 'const') { for (const declarator of node.declarations) { if (declarator.init) { if (idx === targetDeclIdx) { declarator.init = null; modified = true; return; } idx++; } } } }); if (modified) { yield cloned; } } } /** * Generator that simplifies try/catch/finally statements: * - Replace with try block contents * - Replace with catch block contents (if present) * - Replace with finally block contents (if present) */ function* simplifyTryStatements(ast: t.File): Generator { // Count try statements let tryCount = 0; t.traverseFast(ast, node => { if (t.isTryStatement(node)) { tryCount++; } }); // Try replacing with try block contents for (let targetIdx = 0; targetIdx < tryCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { TryStatement(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(path.node.block); modified = true; } idx++; }, }); if (modified) { yield cloned; } } // Try replacing with catch block contents (if present) for (let targetIdx = 0; targetIdx < tryCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { TryStatement(path) { if (modified) return; if (idx === targetIdx && path.node.handler) { path.replaceWith(path.node.handler.body); modified = true; } idx++; }, }); if (modified) { yield cloned; } } // Try replacing with finally block contents (if present) for (let targetIdx = 0; targetIdx < tryCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { TryStatement(path) { if (modified) return; if (idx === targetIdx && path.node.finalizer) { path.replaceWith(path.node.finalizer); modified = true; } idx++; }, }); if (modified) { yield cloned; } } } /** * Generator that simplifies single-statement block statements: * { statement } -> statement */ function* simplifySingleStatementBlocks(ast: t.File): Generator { // Count block statements with exactly one statement let blockCount = 0; t.traverseFast(ast, node => { if (t.isBlockStatement(node) && node.body.length === 1) { blockCount++; } }); for (let targetIdx = 0; targetIdx < blockCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { BlockStatement(path) { if (modified) return; if (path.node.body.length === 1 && idx === targetIdx) { // Don't unwrap blocks that require BlockStatement syntax if ( t.isFunction(path.parent) || t.isCatchClause(path.parent) || t.isClassMethod(path.parent) || t.isObjectMethod(path.parent) || t.isTryStatement(path.parent) ) { idx++; return; } path.replaceWith(path.node.body[0]); modified = true; } idx++; }, }); if (modified) { yield cloned; } } } /** * Generator that removes array elements one at a time */ function* removeArrayElements(ast: t.File): Generator { // Collect all array expressions with their element counts const arraySites: Array<{arrayIndex: number; elementCount: number}> = []; let arrayIndex = 0; t.traverseFast(ast, node => { if (t.isArrayExpression(node) && node.elements.length > 0) { arraySites.push({arrayIndex, elementCount: node.elements.length}); arrayIndex++; } }); // For each array, try removing each element one at a time (from end to start) for (const {arrayIndex: targetArrayIdx, elementCount} of arraySites) { for (let elemIdx = elementCount - 1; elemIdx >= 0; elemIdx--) { const cloned = cloneAst(ast); let idx = 0; let modified = false; t.traverseFast(cloned, node => { if (modified) return; if (t.isArrayExpression(node) && node.elements.length > 0) { if (idx === targetArrayIdx && elemIdx < node.elements.length) { node.elements.splice(elemIdx, 1); modified = true; } idx++; } }); if (modified) { yield cloned; } } } } /** * Generator that removes JSX element attributes (props) one at a time */ function* removeJSXAttributes(ast: t.File): Generator { // Collect all JSX elements with their attribute counts const jsxSites: Array<{jsxIndex: number; attrCount: number}> = []; let jsxIndex = 0; t.traverseFast(ast, node => { if (t.isJSXOpeningElement(node) && node.attributes.length > 0) { jsxSites.push({jsxIndex, attrCount: node.attributes.length}); jsxIndex++; } }); // For each JSX element, try removing each attribute one at a time (from end to start) for (const {jsxIndex: targetJsxIdx, attrCount} of jsxSites) { for (let attrIdx = attrCount - 1; attrIdx >= 0; attrIdx--) { const cloned = cloneAst(ast); let idx = 0; let modified = false; t.traverseFast(cloned, node => { if (modified) return; if (t.isJSXOpeningElement(node) && node.attributes.length > 0) { if (idx === targetJsxIdx && attrIdx < node.attributes.length) { node.attributes.splice(attrIdx, 1); modified = true; } idx++; } }); if (modified) { yield cloned; } } } } /** * Generator that removes JSX element children one at a time */ function* removeJSXChildren(ast: t.File): Generator { // Collect all JSX elements with children const jsxSites: Array<{jsxIndex: number; childCount: number}> = []; let jsxIndex = 0; t.traverseFast(ast, node => { if (t.isJSXElement(node) && node.children.length > 0) { jsxSites.push({jsxIndex, childCount: node.children.length}); jsxIndex++; } }); // For each JSX element, try removing each child one at a time (from end to start) for (const {jsxIndex: targetJsxIdx, childCount} of jsxSites) { for (let childIdx = childCount - 1; childIdx >= 0; childIdx--) { const cloned = cloneAst(ast); let idx = 0; let modified = false; t.traverseFast(cloned, node => { if (modified) return; if (t.isJSXElement(node) && node.children.length > 0) { if (idx === targetJsxIdx && childIdx < node.children.length) { node.children.splice(childIdx, 1); modified = true; } idx++; } }); if (modified) { yield cloned; } } } } /** * Generator that removes JSX fragment children one at a time */ function* removeJSXFragmentChildren(ast: t.File): Generator { // Collect all JSX fragments with children const fragmentSites: Array<{fragIndex: number; childCount: number}> = []; let fragIndex = 0; t.traverseFast(ast, node => { if (t.isJSXFragment(node) && node.children.length > 0) { fragmentSites.push({fragIndex, childCount: node.children.length}); fragIndex++; } }); // For each fragment, try removing each child one at a time (from end to start) for (const {fragIndex: targetFragIdx, childCount} of fragmentSites) { for (let childIdx = childCount - 1; childIdx >= 0; childIdx--) { const cloned = cloneAst(ast); let idx = 0; let modified = false; t.traverseFast(cloned, node => { if (modified) return; if (t.isJSXFragment(node) && node.children.length > 0) { if (idx === targetFragIdx && childIdx < node.children.length) { node.children.splice(childIdx, 1); modified = true; } idx++; } }); if (modified) { yield cloned; } } } } /** * Generator that replaces single-element arrays with the element itself */ function* simplifySingleElementArrays(ast: t.File): Generator { // Count single-element arrays let arrayCount = 0; t.traverseFast(ast, node => { if (t.isArrayExpression(node) && node.elements.length === 1) { arrayCount++; } }); for (let targetIdx = 0; targetIdx < arrayCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { ArrayExpression(path) { if (modified) return; if (path.node.elements.length === 1 && idx === targetIdx) { const elem = path.node.elements[0]; if (t.isExpression(elem)) { path.replaceWith(elem); modified = true; } } idx++; }, }); if (modified) { yield cloned; } } } /** * Generator that replaces single-property objects with the property value. * For regular properties: {key: value} -> value * For computed properties: {[key]: value} -> key (also try value) */ function* simplifySinglePropertyObjects(ast: t.File): Generator { // Count single-property objects let objectCount = 0; t.traverseFast(ast, node => { if (t.isObjectExpression(node) && node.properties.length === 1) { objectCount++; } }); // Try replacing with value for (let targetIdx = 0; targetIdx < objectCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { ObjectExpression(path) { if (modified) return; if (path.node.properties.length === 1 && idx === targetIdx) { const prop = path.node.properties[0]; if (t.isObjectProperty(prop) && t.isExpression(prop.value)) { path.replaceWith(prop.value); modified = true; } } idx++; }, }); if (modified) { yield cloned; } } // For computed properties, also try replacing with key for (let targetIdx = 0; targetIdx < objectCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { ObjectExpression(path) { if (modified) return; if (path.node.properties.length === 1 && idx === targetIdx) { const prop = path.node.properties[0]; if ( t.isObjectProperty(prop) && prop.computed && t.isExpression(prop.key) ) { path.replaceWith(prop.key); modified = true; } } idx++; }, }); if (modified) { yield cloned; } } } /** * Generator that removes object properties one at a time */ function* removeObjectProperties(ast: t.File): Generator { // Collect all object expressions with their property counts const objectSites: Array<{objectIndex: number; propCount: number}> = []; let objectIndex = 0; t.traverseFast(ast, node => { if (t.isObjectExpression(node) && node.properties.length > 0) { objectSites.push({objectIndex, propCount: node.properties.length}); objectIndex++; } }); // For each object, try removing each property one at a time (from end to start) for (const {objectIndex: targetObjIdx, propCount} of objectSites) { for (let propIdx = propCount - 1; propIdx >= 0; propIdx--) { const cloned = cloneAst(ast); let idx = 0; let modified = false; t.traverseFast(cloned, node => { if (modified) return; if (t.isObjectExpression(node) && node.properties.length > 0) { if (idx === targetObjIdx && propIdx < node.properties.length) { node.properties.splice(propIdx, 1); modified = true; } idx++; } }); if (modified) { yield cloned; } } } } /** * Generator that removes elements from array destructuring patterns one at a time */ function* removeArrayPatternElements(ast: t.File): Generator { // Collect all array patterns with elements const patternSites: Array<{patternIndex: number; elementCount: number}> = []; let patternIndex = 0; t.traverseFast(ast, node => { if (t.isArrayPattern(node) && node.elements.length > 0) { patternSites.push({patternIndex, elementCount: node.elements.length}); patternIndex++; } }); // For each pattern, try removing each element (from end to start) for (const {patternIndex: targetPatternIdx, elementCount} of patternSites) { for (let elemIdx = elementCount - 1; elemIdx >= 0; elemIdx--) { const cloned = cloneAst(ast); let idx = 0; let modified = false; t.traverseFast(cloned, node => { if (modified) return; if (t.isArrayPattern(node) && node.elements.length > 0) { if (idx === targetPatternIdx && elemIdx < node.elements.length) { node.elements.splice(elemIdx, 1); modified = true; } idx++; } }); if (modified) { yield cloned; } } } } /** * Generator that removes properties from object destructuring patterns one at a time */ function* removeObjectPatternProperties(ast: t.File): Generator { // Collect all object patterns with properties const patternSites: Array<{patternIndex: number; propCount: number}> = []; let patternIndex = 0; t.traverseFast(ast, node => { if (t.isObjectPattern(node) && node.properties.length > 0) { patternSites.push({patternIndex, propCount: node.properties.length}); patternIndex++; } }); // For each pattern, try removing each property (from end to start) for (const {patternIndex: targetPatternIdx, propCount} of patternSites) { for (let propIdx = propCount - 1; propIdx >= 0; propIdx--) { const cloned = cloneAst(ast); let idx = 0; let modified = false; t.traverseFast(cloned, node => { if (modified) return; if (t.isObjectPattern(node) && node.properties.length > 0) { if (idx === targetPatternIdx && propIdx < node.properties.length) { node.properties.splice(propIdx, 1); modified = true; } idx++; } }); if (modified) { yield cloned; } } } } /** * Generator that simplifies assignment expressions (a = b) -> a or b */ function* simplifyAssignmentExpressions(ast: t.File): Generator { // Count assignment expressions let assignmentCount = 0; t.traverseFast(ast, node => { if (t.isAssignmentExpression(node)) { assignmentCount++; } }); // Try replacing with left side (assignment target) for (let targetIdx = 0; targetIdx < assignmentCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { AssignmentExpression(path) { if (modified) return; if (idx === targetIdx) { const left = path.node.left; if (t.isExpression(left)) { path.replaceWith(left); modified = true; } } idx++; }, }); if (modified) { yield cloned; } } // Try replacing with right side (assignment value) for (let targetIdx = 0; targetIdx < assignmentCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { AssignmentExpression(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(path.node.right); modified = true; } idx++; }, }); if (modified) { yield cloned; } } } /** * Generator that simplifies binary expressions (a + b) -> a or b */ function* simplifyBinaryExpressions(ast: t.File): Generator { // Count binary expressions let binaryCount = 0; t.traverseFast(ast, node => { if (t.isBinaryExpression(node)) { binaryCount++; } }); // Try replacing with left side for (let targetIdx = 0; targetIdx < binaryCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { BinaryExpression(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(path.node.left); modified = true; } idx++; }, }); if (modified) { yield cloned; } } // Try replacing with right side for (let targetIdx = 0; targetIdx < binaryCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { BinaryExpression(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(path.node.right); modified = true; } idx++; }, }); if (modified) { yield cloned; } } } /** * Generator that simplifies member expressions (obj.value) -> obj * For computed expressions: obj[key] -> obj or key */ function* simplifyMemberExpressions(ast: t.File): Generator { // Count member expressions let memberCount = 0; t.traverseFast(ast, node => { if (t.isMemberExpression(node)) { memberCount++; } }); // Try replacing with object for (let targetIdx = 0; targetIdx < memberCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { MemberExpression(path) { if (modified) return; if (idx === targetIdx) { path.replaceWith(path.node.object); modified = true; } idx++; }, }); if (modified) { yield cloned; } } // For computed expressions, also try replacing with key for (let targetIdx = 0; targetIdx < memberCount; targetIdx++) { const cloned = cloneAst(ast); let idx = 0; let modified = false; traverse(cloned, { MemberExpression(path) { if (modified) return; if (idx === targetIdx && path.node.computed) { const property = path.node.property; if (t.isExpression(property)) { path.replaceWith(property); modified = true; } } idx++; }, }); if (modified) { yield cloned; } } } /** * Helper to collect all unique identifier names in the AST */ function collectUniqueIdentifierNames(ast: t.File): Set { const names = new Set(); t.traverseFast(ast, node => { if (t.isIdentifier(node)) { names.add(node.name); } }); return names; } /** * Helper to rename all occurrences of an identifier throughout the AST */ function renameAllIdentifiers( ast: t.File, oldName: string, newName: string, ): boolean { let modified = false; t.traverseFast(ast, node => { if (t.isIdentifier(node) && node.name === oldName) { node.name = newName; modified = true; } }); return modified; } /** * Generator that simplifies identifiers by removing "on" prefix. * onClick -> Click */ function* simplifyIdentifiersRemoveOnPrefix(ast: t.File): Generator { const names = collectUniqueIdentifierNames(ast); for (const name of names) { // Check if name starts with "on" followed by uppercase letter if ( name.length > 2 && name.startsWith('on') && name[2] === name[2].toUpperCase() ) { const newName = name.slice(2); // Skip if the new name would conflict with an existing identifier if (names.has(newName)) { continue; } const cloned = cloneAst(ast); if (renameAllIdentifiers(cloned, name, newName)) { yield cloned; } } } } /** * Generator that simplifies identifiers by removing "Ref" suffix. * inputRef -> input */ function* simplifyIdentifiersRemoveRefSuffix(ast: t.File): Generator { const names = collectUniqueIdentifierNames(ast); for (const name of names) { // Check if name ends with "Ref" and has more characters before it if (name.length > 3 && name.endsWith('Ref')) { const newName = name.slice(0, -3); // Skip if the new name would conflict with an existing identifier if (names.has(newName)) { continue; } // Skip if new name would be empty or just whitespace if (newName.length === 0) { continue; } const cloned = cloneAst(ast); if (renameAllIdentifiers(cloned, name, newName)) { yield cloned; } } } } /** * Generator that rewrites "ref" identifier to "ref_" to avoid conflicts. */ function* simplifyIdentifiersRenameRef(ast: t.File): Generator { const names = collectUniqueIdentifierNames(ast); if (names.has('ref')) { // Only rename if ref_ doesn't already exist if (!names.has('ref_')) { const cloned = cloneAst(ast); if (renameAllIdentifiers(cloned, 'ref', 'ref_')) { yield cloned; } } } } /** * All simplification strategies in order of priority (coarse to fine) */ const simplificationStrategies = [ {name: 'removeStatements', generator: removeStatements}, {name: 'removeCallArguments', generator: removeCallArguments}, {name: 'removeFunctionParameters', generator: removeFunctionParameters}, {name: 'removeArrayElements', generator: removeArrayElements}, {name: 'removeObjectProperties', generator: removeObjectProperties}, {name: 'removeArrayPatternElements', generator: removeArrayPatternElements}, { name: 'removeObjectPatternProperties', generator: removeObjectPatternProperties, }, {name: 'removeJSXAttributes', generator: removeJSXAttributes}, {name: 'removeJSXChildren', generator: removeJSXChildren}, {name: 'removeJSXFragmentChildren', generator: removeJSXFragmentChildren}, {name: 'simplifyCallExpressions', generator: simplifyCallExpressions}, {name: 'simplifyConditionals', generator: simplifyConditionals}, {name: 'simplifyLogicalExpressions', generator: simplifyLogicalExpressions}, {name: 'simplifyBinaryExpressions', generator: simplifyBinaryExpressions}, { name: 'simplifyAssignmentExpressions', generator: simplifyAssignmentExpressions, }, {name: 'simplifySingleElementArrays', generator: simplifySingleElementArrays}, { name: 'simplifySinglePropertyObjects', generator: simplifySinglePropertyObjects, }, {name: 'simplifyMemberExpressions', generator: simplifyMemberExpressions}, {name: 'simplifyOptionalChains', generator: simplifyOptionalChains}, {name: 'simplifyAwaitExpressions', generator: simplifyAwaitExpressions}, {name: 'simplifyIfStatements', generator: simplifyIfStatements}, {name: 'simplifySwitchStatements', generator: simplifySwitchStatements}, {name: 'simplifyWhileStatements', generator: simplifyWhileStatements}, {name: 'simplifyDoWhileStatements', generator: simplifyDoWhileStatements}, {name: 'simplifyForStatements', generator: simplifyForStatements}, {name: 'simplifyForInStatements', generator: simplifyForInStatements}, {name: 'simplifyForOfStatements', generator: simplifyForOfStatements}, { name: 'simplifyVariableDeclarations', generator: simplifyVariableDeclarations, }, {name: 'simplifyTryStatements', generator: simplifyTryStatements}, { name: 'simplifySingleStatementBlocks', generator: simplifySingleStatementBlocks, }, { name: 'simplifyIdentifiersRemoveOnPrefix', generator: simplifyIdentifiersRemoveOnPrefix, }, { name: 'simplifyIdentifiersRemoveRefSuffix', generator: simplifyIdentifiersRemoveRefSuffix, }, { name: 'simplifyIdentifiersRenameRef', generator: simplifyIdentifiersRenameRef, }, ]; type MinimizeResult = | {kind: 'success'} | {kind: 'minimal'} | {kind: 'minimized'; source: string}; /** * Core minimization loop that attempts to reduce the input source code * while preserving the compiler error. */ export function minimize( input: string, filename: string, language: 'flow' | 'typescript', sourceType: 'module' | 'script', ): MinimizeResult { // Load the compiler plugin const importedCompilerPlugin = require(BABEL_PLUGIN_SRC) as Record< string, unknown >; const BabelPluginReactCompiler = importedCompilerPlugin[ 'default' ] as PluginObj; const parseConfigPragmaForTests = importedCompilerPlugin[ PARSE_CONFIG_PRAGMA_IMPORT ] as typeof ParseConfigPragma; // Get the initial error const initialResult = compileAndGetError( input, filename, language, sourceType, BabelPluginReactCompiler, parseConfigPragmaForTests, ); if (initialResult.kind === 'success') { return {kind: 'success'}; } if (initialResult.kind === 'parse_error') { return {kind: 'success'}; } const targetError = initialResult; // Parse the initial AST let currentAst = parseInput(input, filename, language, sourceType); let currentCode = input; let changed = true; let iterations = 0; const maxIterations = 1000; // Safety limit process.stdout.write('\nMinimizing'); while (changed && iterations < maxIterations) { changed = false; iterations++; // Try each simplification strategy for (const strategy of simplificationStrategies) { const generator = strategy.generator(currentAst); for (const candidateAst of generator) { let candidateCode: string; try { candidateCode = astToCode(candidateAst); } catch { // If code generation fails, skip this candidate continue; } const result = compileAndGetError( candidateCode, filename, language, sourceType, BabelPluginReactCompiler, parseConfigPragmaForTests, ); if (errorsMatch(targetError, result)) { // This simplification preserves the error, keep it currentAst = candidateAst; currentCode = candidateCode; changed = true; process.stdout.write('.'); break; // Restart from the beginning with the new AST } } if (changed) { break; // Restart the outer loop } } } console.log('\n'); // Check if any minimization was achieved if (currentCode === input) { return {kind: 'minimal'}; } return {kind: 'minimized', source: currentCode}; } ================================================ FILE: compiler/packages/snap/src/reporter.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import chalk from 'chalk'; import fs from 'fs'; import invariant from 'invariant'; import {diff} from 'jest-diff'; import path from 'path'; function wrapWithTripleBackticks(s: string, ext: string | null = null): string { return `\`\`\`${ext ?? ''} ${s} \`\`\``; } const SPROUT_SEPARATOR = '\n### Eval output\n'; export function writeOutputToString( input: string, compilerOutput: string | null, evaluatorOutput: string | null, logs: string | null, errorMessage: string | null, ) { // leading newline intentional let result = ` ## Input ${wrapWithTripleBackticks(input, 'javascript')} `; // trailing newline + space internional if (compilerOutput != null) { result += ` ## Code ${wrapWithTripleBackticks(compilerOutput, 'javascript')} `; } else { result += '\n'; } if (logs != null) { result += ` ## Logs ${wrapWithTripleBackticks(logs, null)} `; } if (errorMessage != null) { result += ` ## Error ${wrapWithTripleBackticks(errorMessage.replace(/^\/.*?:\s/, ''))} \n`; } result += ` `; if (evaluatorOutput != null) { result += SPROUT_SEPARATOR + evaluatorOutput; } return result; } export type TestResult = { actual: string | null; // null == input did not exist expected: string | null; // null == output did not exist outputPath: string; unexpectedError: string | null; }; export type TestResults = Map; /** * Update the fixtures directory given the compilation results */ export async function update(results: TestResults): Promise { let deleted = 0; let updated = 0; let created = 0; const failed = []; for (const [basename, result] of results) { if (result.unexpectedError != null) { console.log( chalk.red.inverse.bold(' FAILED ') + ' ' + chalk.dim(basename), ); failed.push([basename, result.unexpectedError]); } else if (result.actual == null) { // Input was deleted but the expect file still existed, remove it console.log( chalk.red.inverse.bold(' REMOVE ') + ' ' + chalk.dim(basename), ); try { fs.unlinkSync(result.outputPath); console.log(' remove ' + result.outputPath); deleted++; } catch (e) { console.error( '[Snap tester error]: failed to remove ' + result.outputPath, ); failed.push([basename, result.unexpectedError]); } } else if (result.actual !== result.expected) { // Expected output has changed console.log( chalk.blue.inverse.bold(' UPDATE ') + ' ' + chalk.dim(basename), ); try { fs.writeFileSync(result.outputPath, result.actual, 'utf8'); } catch (e) { if (e?.code === 'ENOENT') { // May have failed to create nested dir, so make a directory and retry fs.mkdirSync(path.dirname(result.outputPath), {recursive: true}); fs.writeFileSync(result.outputPath, result.actual, 'utf8'); } } if (result.expected == null) { created++; } else { updated++; } } else { // Expected output is current console.log( chalk.green.inverse.bold(' OKAY ') + ' ' + chalk.dim(basename), ); } } console.log( `${deleted} Deleted, ${created} Created, ${updated} Updated, ${failed.length} Failed`, ); for (const [basename, errorMsg] of failed) { console.log(`${chalk.red.bold('Fail:')} ${basename}\n${errorMsg}`); } } /** * Report test results to the user * @returns boolean indicatig whether all tests passed */ export function report( results: TestResults, verbose: boolean = false, ): boolean { const failures: Array<[string, TestResult]> = []; for (const [basename, result] of results) { if (result.actual === result.expected && result.unexpectedError == null) { if (verbose) { console.log( chalk.green.inverse.bold(' PASS ') + ' ' + chalk.dim(basename), ); } } else { if (verbose) { console.log( chalk.red.inverse.bold(' FAIL ') + ' ' + chalk.dim(basename), ); } failures.push([basename, result]); } } if (failures.length !== 0) { console.log('\n' + chalk.red.bold('Failures:') + '\n'); for (const [basename, result] of failures) { console.log(chalk.red.bold('FAIL:') + ' ' + basename); if (result.unexpectedError != null) { console.log( ` >> Unexpected error during test: \n${result.unexpectedError}`, ); } else { if (result.expected == null) { invariant(result.actual != null, '[Tester] Internal failure.'); console.log( chalk.red('[ expected fixture output is absent ]') + '\n', ); } else if (result.actual == null) { invariant(result.expected != null, '[Tester] Internal failure.'); console.log( chalk.red(`[ fixture input for ${result.outputPath} is absent ]`) + '\n', ); } else { console.log(diff(result.expected, result.actual) + '\n'); } } } } console.log( `${results.size} Tests, ${results.size - failures.length} Passed, ${ failures.length } Failed`, ); return failures.length === 0; } ================================================ FILE: compiler/packages/snap/src/runner-watch.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import watcher from '@parcel/watcher'; import path from 'path'; import ts from 'typescript'; import {FIXTURES_PATH, BABEL_PLUGIN_ROOT} from './constants'; import {TestFilter, getFixtures} from './fixture-utils'; import {execSync} from 'child_process'; export function watchSrc( onStart: () => void, onComplete: (isSuccess: boolean) => void, ): ts.WatchOfConfigFile { const configPath = ts.findConfigFile( /*searchPath*/ BABEL_PLUGIN_ROOT, ts.sys.fileExists, 'tsconfig.json', ); if (!configPath) { throw new Error("Could not find a valid 'tsconfig.json'."); } const createProgram = ts.createSemanticDiagnosticsBuilderProgram; const host = ts.createWatchCompilerHost( configPath, undefined, ts.sys, createProgram, () => {}, // we manually report errors in afterProgramCreate () => {}, // we manually report watch status ); const origCreateProgram = host.createProgram; host.createProgram = (rootNames, options, host, oldProgram) => { onStart(); return origCreateProgram(rootNames, options, host, oldProgram); }; host.afterProgramCreate = program => { /** * Avoid calling original postProgramCreate because it always emits tsc * compilation output */ // syntactic diagnostics refer to javascript syntax const errors = program .getSyntacticDiagnostics() .filter(diag => diag.category === ts.DiagnosticCategory.Error); // semantic diagnostics refer to typescript semantics errors.push( ...program .getSemanticDiagnostics() .filter(diag => diag.category === ts.DiagnosticCategory.Error), ); if (errors.length > 0) { for (const diagnostic of errors) { let fileLoc: string; if (diagnostic.file) { // https://github.com/microsoft/TypeScript/blob/ddd5084659c423f4003d2176e12d879b6a5bcf30/src/compiler/program.ts#L663-L674 const {line, character} = ts.getLineAndCharacterOfPosition( diagnostic.file, diagnostic.start!, ); const fileName = path.relative( ts.sys.getCurrentDirectory(), diagnostic.file.fileName, ); fileLoc = `${fileName}:${line + 1}:${character + 1} - `; } else { fileLoc = ''; } console.error( `${fileLoc}error TS${diagnostic.code}:`, ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'), ); } console.error( `Compilation failed (${errors.length} ${ errors.length > 1 ? 'errors' : 'error' }).\n`, ); } const isSuccess = errors.length === 0; onComplete(isSuccess); }; // `createWatchProgram` creates an initial program, watches files, and updates // the program over time. return ts.createWatchProgram(host); } /** * Watch mode helpers */ export enum RunnerAction { Test = 'Test', Update = 'Update', } type RunnerMode = { action: RunnerAction; filter: boolean; }; export type RunnerState = { // Monotonically increasing integer to describe the 'version' of the compiler. // This is passed to `compile()` when compiling, so that the worker knows when // to reset its module cache (compared to using its cached compiler version) compilerVersion: number; isCompilerBuildValid: boolean; // timestamp of the last update lastUpdate: number; mode: RunnerMode; filter: TestFilter | null; debug: boolean; // Input mode for interactive pattern entry inputMode: 'none' | 'pattern'; inputBuffer: string; // Autocomplete state allFixtureNames: Array; matchingFixtures: Array; selectedIndex: number; // Track last run status of each fixture (for autocomplete suggestions) fixtureLastRunStatus: Map; }; function subscribeFixtures( state: RunnerState, onChange: (state: RunnerState) => void, ) { // Watch the fixtures directory for changes watcher.subscribe(FIXTURES_PATH, async (err, _events) => { if (err) { console.error(err); process.exit(1); } // Try to ignore changes that occurred as a result of our explicitly updating // fixtures in update(). // Currently keeps a timestamp of last known changes, and ignore events that occurred // around that timestamp. const isRealUpdate = performance.now() - state.lastUpdate > 5000; if (isRealUpdate) { // Fixtures changed, re-run tests state.mode.action = RunnerAction.Test; onChange(state); } }); } function subscribeTsc( state: RunnerState, onChange: (state: RunnerState) => void, ) { // Run TS in incremental watch mode watchSrc( function onStart() { // Notify the user when compilation starts but don't clear the screen yet console.log('\nCompiling...'); }, isTypecheckSuccess => { let isCompilerBuildValid = false; if (isTypecheckSuccess) { try { execSync('yarn build', {cwd: BABEL_PLUGIN_ROOT}); console.log('Built compiler successfully with tsup'); isCompilerBuildValid = true; } catch (e) { console.warn('Failed to build compiler with tsup:', e); } } // Bump the compiler version after a build finishes // and re-run tests if (isCompilerBuildValid) { state.compilerVersion++; } state.isCompilerBuildValid = isCompilerBuildValid; state.mode.action = RunnerAction.Test; onChange(state); }, ); } /** * Levenshtein edit distance between two strings */ function editDistance(a: string, b: string): number { const m = a.length; const n = b.length; // Create a 2D array for memoization const dp: number[][] = Array.from({length: m + 1}, () => Array(n + 1).fill(0), ); // Base cases for (let i = 0; i <= m; i++) dp[i][0] = i; for (let j = 0; j <= n; j++) dp[0][j] = j; // Fill in the rest for (let i = 1; i <= m; i++) { for (let j = 1; j <= n; j++) { if (a[i - 1] === b[j - 1]) { dp[i][j] = dp[i - 1][j - 1]; } else { dp[i][j] = 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]); } } } return dp[m][n]; } function filterFixtures( allNames: Array, pattern: string, ): Array { if (pattern === '') { return allNames; } const lowerPattern = pattern.toLowerCase(); const matches = allNames.filter(name => name.toLowerCase().includes(lowerPattern), ); // Sort by edit distance (lower = better match) matches.sort((a, b) => { const distA = editDistance(lowerPattern, a.toLowerCase()); const distB = editDistance(lowerPattern, b.toLowerCase()); return distA - distB; }); return matches; } const MAX_DISPLAY = 15; function renderAutocomplete(state: RunnerState): void { // Clear terminal console.log('\u001Bc'); // Show current input console.log(`Pattern: ${state.inputBuffer}`); console.log(''); // Get current filter pattern if active const currentFilterPattern = state.mode.filter && state.filter ? state.filter.paths[0] : null; // Show matching fixtures (limit to MAX_DISPLAY) const toShow = state.matchingFixtures.slice(0, MAX_DISPLAY); toShow.forEach((name, i) => { const isSelected = i === state.selectedIndex; const matchesCurrentFilter = currentFilterPattern != null && name.toLowerCase().includes(currentFilterPattern.toLowerCase()); let prefix: string; if (isSelected) { prefix = '> '; } else if (matchesCurrentFilter) { prefix = '* '; } else { prefix = ' '; } console.log(`${prefix}${name}`); }); if (state.matchingFixtures.length > MAX_DISPLAY) { console.log( ` ... and ${state.matchingFixtures.length - MAX_DISPLAY} more`, ); } console.log(''); console.log('↑/↓/Tab navigate | Enter select | Esc cancel'); } function subscribeKeyEvents( state: RunnerState, onChange: (state: RunnerState) => void, ) { process.stdin.on('keypress', async (str, key) => { // Handle input mode (pattern entry with autocomplete) if (state.inputMode !== 'none') { if (key.name === 'return') { // Enter pressed - use selected fixture or typed text let pattern: string; if ( state.selectedIndex >= 0 && state.selectedIndex < state.matchingFixtures.length ) { pattern = state.matchingFixtures[state.selectedIndex]; } else { pattern = state.inputBuffer.trim(); } state.inputMode = 'none'; state.inputBuffer = ''; state.allFixtureNames = []; state.matchingFixtures = []; state.selectedIndex = -1; if (pattern !== '') { state.filter = {paths: [pattern]}; state.mode.filter = true; state.mode.action = RunnerAction.Test; onChange(state); } return; } else if (key.name === 'escape') { // Cancel input mode state.inputMode = 'none'; state.inputBuffer = ''; state.allFixtureNames = []; state.matchingFixtures = []; state.selectedIndex = -1; // Redraw normal UI onChange(state); return; } else if (key.name === 'up' || (key.name === 'tab' && key.shift)) { // Navigate up in autocomplete list if (state.matchingFixtures.length > 0) { if (state.selectedIndex <= 0) { state.selectedIndex = Math.min(state.matchingFixtures.length, MAX_DISPLAY) - 1; } else { state.selectedIndex--; } renderAutocomplete(state); } return; } else if (key.name === 'down' || (key.name === 'tab' && !key.shift)) { // Navigate down in autocomplete list if (state.matchingFixtures.length > 0) { const maxIndex = Math.min(state.matchingFixtures.length, MAX_DISPLAY) - 1; if (state.selectedIndex >= maxIndex) { state.selectedIndex = 0; } else { state.selectedIndex++; } renderAutocomplete(state); } return; } else if (key.name === 'backspace') { if (state.inputBuffer.length > 0) { state.inputBuffer = state.inputBuffer.slice(0, -1); state.matchingFixtures = filterFixtures( state.allFixtureNames, state.inputBuffer, ); state.selectedIndex = -1; renderAutocomplete(state); } return; } else if (str && !key.ctrl && !key.meta) { // Regular character - accumulate, filter, and render state.inputBuffer += str; state.matchingFixtures = filterFixtures( state.allFixtureNames, state.inputBuffer, ); state.selectedIndex = -1; renderAutocomplete(state); return; } return; // Ignore other keys in input mode } // Normal mode keypress handling if (key.name === 'u') { // u => update fixtures state.mode.action = RunnerAction.Update; } else if (key.name === 'q') { process.exit(0); } else if (key.name === 'a') { // a => exit filter mode and run all tests state.mode.filter = false; state.filter = null; state.mode.action = RunnerAction.Test; } else if (key.name === 'd') { // d => toggle debug logging state.debug = !state.debug; state.mode.action = RunnerAction.Test; } else if (key.name === 'p') { // p => enter pattern input mode with autocomplete state.inputMode = 'pattern'; state.inputBuffer = ''; // Load all fixtures for autocomplete const fixtures = await getFixtures(null); state.allFixtureNames = Array.from(fixtures.keys()).sort(); // Show failed fixtures first when no pattern entered const failedFixtures = Array.from(state.fixtureLastRunStatus.entries()) .filter(([_, status]) => status === 'fail') .map(([name]) => name) .sort(); state.matchingFixtures = failedFixtures.length > 0 ? failedFixtures : state.allFixtureNames; state.selectedIndex = -1; renderAutocomplete(state); return; // Don't trigger onChange yet } else { // any other key re-runs tests state.mode.action = RunnerAction.Test; } onChange(state); }); } export async function makeWatchRunner( onChange: (state: RunnerState) => void, debugMode: boolean, initialPattern?: string, ): Promise { // Determine initial filter state let filter: TestFilter | null = null; let filterEnabled = false; if (initialPattern) { filter = {paths: [initialPattern]}; filterEnabled = true; } const state: RunnerState = { compilerVersion: 0, isCompilerBuildValid: false, lastUpdate: -1, mode: { action: RunnerAction.Test, filter: filterEnabled, }, filter, debug: debugMode, inputMode: 'none', inputBuffer: '', allFixtureNames: [], matchingFixtures: [], selectedIndex: -1, fixtureLastRunStatus: new Map(), }; subscribeTsc(state, onChange); subscribeFixtures(state, onChange); subscribeKeyEvents(state, onChange); } ================================================ FILE: compiler/packages/snap/src/runner-worker.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import type {PluginObj} from '@babel/core'; import type {parseConfigPragmaForTests as ParseConfigPragma} from 'babel-plugin-react-compiler/src/Utils/TestUtils'; import type {printFunctionWithOutlined as PrintFunctionWithOutlined} from 'babel-plugin-react-compiler/src/HIR/PrintHIR'; import type {printReactiveFunctionWithOutlined as PrintReactiveFunctionWithOutlined} from 'babel-plugin-react-compiler/src/ReactiveScopes/PrintReactiveFunction'; import {TransformResult, transformFixtureInput} from './compiler'; import { PARSE_CONFIG_PRAGMA_IMPORT, PRINT_HIR_IMPORT, PRINT_REACTIVE_IR_IMPORT, BABEL_PLUGIN_SRC, } from './constants'; import {TestFixture, getBasename, isExpectError} from './fixture-utils'; import {TestResult, writeOutputToString} from './reporter'; import {runSprout} from './sprout'; import type { CompilerPipelineValue, Effect, ValueKind, ValueReason, } from 'babel-plugin-react-compiler/src'; import chalk from 'chalk'; const originalConsoleError = console.error; // Try to avoid clearing the entire require cache, which (as of this PR) // contains ~1250 files. This assumes that no dependencies have global caches // that may need to be invalidated across Forget reloads. const invalidationSubpath = 'packages/babel-plugin-react-compiler/dist'; let version: number | null = null; export function clearRequireCache() { Object.keys(require.cache).forEach(function (path) { if (path.includes(invalidationSubpath)) { delete require.cache[path]; } }); } async function compile( input: string, fixturePath: string, compilerVersion: number, shouldLog: boolean, includeEvaluator: boolean, ): Promise<{ error: string | null; compileResult: TransformResult | null; }> { const seenConsoleErrors: Array = []; console.error = (...messages: Array) => { seenConsoleErrors.push(...messages); }; if (version !== null && compilerVersion !== version) { clearRequireCache(); } version = compilerVersion; let compileResult: TransformResult | null = null; let error: string | null = null; try { const importedCompilerPlugin = require(BABEL_PLUGIN_SRC) as Record< string, unknown >; // NOTE: we intentionally require lazily here so that we can clear the require cache // and load fresh versions of the compiler when `compilerVersion` changes. const BabelPluginReactCompiler = importedCompilerPlugin[ 'default' ] as PluginObj; const EffectEnum = importedCompilerPlugin['Effect'] as typeof Effect; const ValueKindEnum = importedCompilerPlugin[ 'ValueKind' ] as typeof ValueKind; const ValueReasonEnum = importedCompilerPlugin[ 'ValueReason' ] as typeof ValueReason; const printFunctionWithOutlined = importedCompilerPlugin[ PRINT_HIR_IMPORT ] as typeof PrintFunctionWithOutlined; const printReactiveFunctionWithOutlined = importedCompilerPlugin[ PRINT_REACTIVE_IR_IMPORT ] as typeof PrintReactiveFunctionWithOutlined; const parseConfigPragmaForTests = importedCompilerPlugin[ PARSE_CONFIG_PRAGMA_IMPORT ] as typeof ParseConfigPragma; let lastLogged: string | null = null; const debugIRLogger = shouldLog ? (value: CompilerPipelineValue) => { let printed: string; switch (value.kind) { case 'hir': printed = printFunctionWithOutlined(value.value); break; case 'reactive': printed = printReactiveFunctionWithOutlined(value.value); break; case 'debug': printed = value.value; break; case 'ast': // skip printing ast as we already write fixture output JS printed = '(ast)'; break; } if (printed !== lastLogged) { lastLogged = printed; console.log(`${chalk.green(value.name)}:\n ${printed}\n`); } else { console.log(`${chalk.blue(value.name)}: (no change)\n`); } } : () => {}; // only try logging if we filtered out all but one fixture, // since console log order is non-deterministic const result = await transformFixtureInput( input, fixturePath, parseConfigPragmaForTests, BabelPluginReactCompiler, includeEvaluator, debugIRLogger, EffectEnum, ValueKindEnum, ValueReasonEnum, ); if (result.kind === 'err') { error = result.msg; } else { compileResult = result.value; } } catch (e) { if (shouldLog) { console.error(e.stack); } error = e.message.replace(/\u001b[^m]*m/g, ''); } // Promote console errors so they can be recorded in fixture output for (const consoleError of seenConsoleErrors) { if (error != null) { error = `${error}\n\n${consoleError}`; } else { error = `ConsoleError: ${consoleError}`; } } console.error = originalConsoleError; return { error, compileResult, }; } export async function transformFixture( fixture: TestFixture, compilerVersion: number, shouldLog: boolean, includeEvaluator: boolean, ): Promise { const {input, snapshot: expected, snapshotPath: outputPath} = fixture; const basename = getBasename(fixture); const expectError = isExpectError(fixture); // Input will be null if the input file did not exist, in which case the output file // is stale if (input === null) { return { outputPath, actual: null, expected, unexpectedError: null, }; } const {compileResult, error} = await compile( input, fixture.fixturePath, compilerVersion, shouldLog, includeEvaluator, ); let unexpectedError: string | null = null; if (expectError) { if (error === null) { unexpectedError = `Expected an error to be thrown for fixture: \`${basename}\`, remove the 'error.' prefix if an error is not expected.`; } } else { if (error !== null) { unexpectedError = `Expected fixture \`${basename}\` to succeed but it failed with error:\n\n${error}`; } else if (compileResult == null) { unexpectedError = `Expected output for fixture \`${basename}\`.`; } } const snapOutput: string | null = compileResult?.forgetOutput ?? null; let sproutOutput: string | null = null; if (compileResult?.evaluatorCode != null) { const sproutResult = runSprout( compileResult.evaluatorCode.original, compileResult.evaluatorCode.forget, ); if (sproutResult.kind === 'invalid') { unexpectedError ??= ''; unexpectedError += `\n\n${sproutResult.value}`; } else { sproutOutput = sproutResult.value; } } else if (!includeEvaluator && expected != null) { sproutOutput = expected.split('\n### Eval output\n')[1]; } const actualOutput = writeOutputToString( input, snapOutput, sproutOutput, compileResult?.logs ?? null, error, ); return { outputPath, actual: actualOutput, expected, unexpectedError, }; } ================================================ FILE: compiler/packages/snap/src/runner.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import {Worker} from 'jest-worker'; import {cpus} from 'os'; import process from 'process'; import * as readline from 'readline'; import ts from 'typescript'; import yargs from 'yargs'; import {hideBin} from 'yargs/helpers'; import {BABEL_PLUGIN_ROOT, PROJECT_ROOT} from './constants'; import {TestFilter, getFixtures} from './fixture-utils'; import {TestResult, TestResults, report, update} from './reporter'; import { RunnerAction, RunnerState, makeWatchRunner, watchSrc, } from './runner-watch'; import * as runnerWorker from './runner-worker'; import {execSync} from 'child_process'; import fs from 'fs'; import path from 'path'; import {minimize} from './minimize'; import {parseInput, parseLanguage, parseSourceType} from './compiler'; import { PARSE_CONFIG_PRAGMA_IMPORT, PRINT_HIR_IMPORT, PRINT_REACTIVE_IR_IMPORT, BABEL_PLUGIN_SRC, } from './constants'; import chalk from 'chalk'; const WORKER_PATH = require.resolve('./runner-worker.js'); const NUM_WORKERS = cpus().length - 1; readline.emitKeypressEvents(process.stdin); type TestOptions = { sync: boolean; workerThreads: boolean; watch: boolean; update: boolean; pattern?: string; debug: boolean; verbose: boolean; }; type MinimizeOptions = { path: string; update: boolean; }; type CompileOptions = { path: string; debug: boolean; }; async function runTestCommand(opts: TestOptions): Promise { const worker: Worker & typeof runnerWorker = new Worker(WORKER_PATH, { enableWorkerThreads: opts.workerThreads, numWorkers: NUM_WORKERS, }) as any; worker.getStderr().pipe(process.stderr); worker.getStdout().pipe(process.stdout); // Check if watch mode should be enabled const shouldWatch = opts.watch; if (shouldWatch) { makeWatchRunner( state => onChange(worker, state, opts.sync, opts.verbose), opts.debug, opts.pattern, ); if (opts.pattern) { /** * Warm up wormers when in watch mode. Loading the Forget babel plugin * and all of its transitive dependencies takes 1-3s (per worker) on a M1. * As jest-worker dispatches tasks using a round-robin strategy, we can * avoid an additional 1-3s wait on the first num_workers runs by warming * up workers eagerly. */ for (let i = 0; i < NUM_WORKERS - 1; i++) { worker.transformFixture( { fixturePath: 'tmp', snapshotPath: './tmp.expect.md', inputPath: './tmp.js', input: ` function Foo(props) { return identity(props); } `, snapshot: null, }, 0, false, false, ); } } } else { // Non-watch mode. For simplicity we re-use the same watchSrc() function. // After the first build completes run tests and exit const tsWatch: ts.WatchOfConfigFile = watchSrc( () => {}, async (isTypecheckSuccess: boolean) => { let isSuccess = false; if (!isTypecheckSuccess) { console.error( 'Found typescript errors in Forget source code, skipping test fixtures.', ); } else { try { execSync('yarn build', {cwd: BABEL_PLUGIN_ROOT}); console.log('Built compiler successfully with tsup'); // Determine which filter to use let testFilter: TestFilter | null = null; if (opts.pattern) { testFilter = { paths: [opts.pattern], }; } const results = await runFixtures( worker, testFilter, 0, opts.debug, false, // no requireSingleFixture in non-watch mode opts.sync, ); if (opts.update) { update(results); isSuccess = true; } else { isSuccess = report(results, opts.verbose); } } catch (e) { console.warn('Failed to build compiler with tsup:', e); } } tsWatch?.close(); await worker.end(); process.exit(isSuccess ? 0 : 1); }, ); } } async function runMinimizeCommand(opts: MinimizeOptions): Promise { // Resolve the input path const inputPath = path.isAbsolute(opts.path) ? opts.path : path.resolve(PROJECT_ROOT, opts.path); // Check if file exists if (!fs.existsSync(inputPath)) { console.error(`Error: File not found: ${inputPath}`); process.exit(1); } // Read the input file const input = fs.readFileSync(inputPath, 'utf-8'); const filename = path.basename(inputPath); const firstLine = input.substring(0, input.indexOf('\n')); const language = parseLanguage(firstLine); const sourceType = parseSourceType(firstLine); console.log(`Minimizing: ${inputPath}`); const originalLines = input.split('\n').length; // Run the minimization const result = minimize(input, filename, language, sourceType); if (result.kind === 'success') { console.log('Could not minimize: the input compiles successfully.'); process.exit(0); } if (result.kind === 'minimal') { console.log( 'Could not minimize: the input fails but is already minimal and cannot be reduced further.', ); process.exit(0); } // Output the minimized code console.log('--- Minimized Code ---'); console.log(result.source); const minimizedLines = result.source.split('\n').length; console.log( `\nReduced from ${originalLines} lines to ${minimizedLines} lines`, ); if (opts.update) { fs.writeFileSync(inputPath, result.source, 'utf-8'); console.log(`\nUpdated ${inputPath} with minimized code.`); } } async function runCompileCommand(opts: CompileOptions): Promise { // Resolve the input path const inputPath = path.isAbsolute(opts.path) ? opts.path : path.resolve(PROJECT_ROOT, opts.path); // Check if file exists if (!fs.existsSync(inputPath)) { console.error(`Error: File not found: ${inputPath}`); process.exit(1); } // Read the input file const input = fs.readFileSync(inputPath, 'utf-8'); const filename = path.basename(inputPath); const firstLine = input.substring(0, input.indexOf('\n')); const language = parseLanguage(firstLine); const sourceType = parseSourceType(firstLine); // Import the compiler const importedCompilerPlugin = require(BABEL_PLUGIN_SRC) as Record< string, any >; const BabelPluginReactCompiler = importedCompilerPlugin['default']; const parseConfigPragmaForTests = importedCompilerPlugin[PARSE_CONFIG_PRAGMA_IMPORT]; const printFunctionWithOutlined = importedCompilerPlugin[PRINT_HIR_IMPORT]; const printReactiveFunctionWithOutlined = importedCompilerPlugin[PRINT_REACTIVE_IR_IMPORT]; const EffectEnum = importedCompilerPlugin['Effect']; const ValueKindEnum = importedCompilerPlugin['ValueKind']; const ValueReasonEnum = importedCompilerPlugin['ValueReason']; // Setup debug logger let lastLogged: string | null = null; const debugIRLogger = opts.debug ? (value: any) => { let printed: string; switch (value.kind) { case 'hir': printed = printFunctionWithOutlined(value.value); break; case 'reactive': printed = printReactiveFunctionWithOutlined(value.value); break; case 'debug': printed = value.value; break; case 'ast': printed = '(ast)'; break; default: printed = String(value); } if (printed !== lastLogged) { lastLogged = printed; console.log(`${chalk.green(value.name)}:\n${printed}\n`); } else { console.log(`${chalk.blue(value.name)}: (no change)\n`); } } : () => {}; // Parse the input let ast; try { ast = parseInput(input, filename, language, sourceType); } catch (e: any) { console.error(`Parse error: ${e.message}`); process.exit(1); } // Build plugin options const config = parseConfigPragmaForTests(firstLine, {compilationMode: 'all'}); const options = { ...config, environment: { ...config.environment, }, logger: { logEvent: () => {}, debugLogIRs: debugIRLogger, }, enableReanimatedCheck: false, }; // Compile const {transformFromAstSync} = require('@babel/core'); try { const result = transformFromAstSync(ast, input, { filename: '/' + filename, highlightCode: false, retainLines: true, compact: true, plugins: [[BabelPluginReactCompiler, options]], sourceType: 'module', ast: false, cloneInputAst: true, configFile: false, babelrc: false, }); if (result?.code != null) { // Format the output const prettier = require('prettier'); const formatted = await prettier.format(result.code, { semi: true, parser: language === 'typescript' ? 'babel-ts' : 'flow', }); console.log(formatted); } else { console.error('Error: No code emitted from compiler'); process.exit(1); } } catch (e: any) { console.error(e.message); process.exit(1); } } yargs(hideBin(process.argv)) .command( ['test', '$0'], 'Run compiler tests', yargs => { return yargs .boolean('sync') .describe( 'sync', 'Run compiler in main thread (instead of using worker threads or subprocesses). Defaults to false.', ) .default('sync', false) .boolean('worker-threads') .describe( 'worker-threads', 'Run compiler in worker threads (instead of subprocesses). Defaults to true.', ) .default('worker-threads', true) .boolean('watch') .describe( 'watch', 'Run compiler in watch mode, re-running after changes', ) .alias('w', 'watch') .default('watch', false) .boolean('update') .alias('u', 'update') .describe('update', 'Update fixtures') .default('update', false) .string('pattern') .alias('p', 'pattern') .describe( 'pattern', 'Optional glob pattern to filter fixtures (e.g., "error.*", "use-memo")', ) .boolean('debug') .alias('d', 'debug') .describe('debug', 'Enable debug logging to print HIR for each pass') .default('debug', false) .boolean('verbose') .alias('v', 'verbose') .describe('verbose', 'Print individual test results') .default('verbose', false); }, async argv => { await runTestCommand(argv as TestOptions); }, ) .command( 'minimize ', 'Minimize a test case to reproduce a compiler error', yargs => { return yargs .positional('path', { describe: 'Path to the file to minimize', type: 'string', demandOption: true, }) .boolean('update') .alias('u', 'update') .describe( 'update', 'Update the input file in-place with the minimized version', ) .default('update', false); }, async argv => { await runMinimizeCommand(argv as unknown as MinimizeOptions); }, ) .command( 'compile ', 'Compile a file with the React Compiler', yargs => { return yargs .positional('path', { describe: 'Path to the file to compile', type: 'string', demandOption: true, }) .boolean('debug') .alias('d', 'debug') .describe('debug', 'Enable debug logging to print HIR for each pass') .default('debug', false); }, async argv => { await runCompileCommand(argv as unknown as CompileOptions); }, ) .help('help') .strict() .demandCommand() .parse(); /** * Do a test run and return the test results */ async function runFixtures( worker: Worker & typeof runnerWorker, filter: TestFilter | null, compilerVersion: number, debug: boolean, requireSingleFixture: boolean, sync: boolean, ): Promise { // We could in theory be fancy about tracking the contents of the fixtures // directory via our file subscription, but it's simpler to just re-read // the directory each time. const fixtures = await getFixtures(filter); const isOnlyFixture = filter !== null && fixtures.size === 1; const shouldLog = debug && (!requireSingleFixture || isOnlyFixture); let entries: Array<[string, TestResult]>; if (!sync) { // Note: promise.all to ensure parallelism when enabled const work: Array> = []; for (const [fixtureName, fixture] of fixtures) { work.push( worker .transformFixture(fixture, compilerVersion, shouldLog, true) .then(result => [fixtureName, result]), ); } entries = await Promise.all(work); } else { entries = []; for (const [fixtureName, fixture] of fixtures) { let output = await runnerWorker.transformFixture( fixture, compilerVersion, shouldLog, true, ); entries.push([fixtureName, output]); } } return new Map(entries); } // Callback to re-run tests after some change async function onChange( worker: Worker & typeof runnerWorker, state: RunnerState, sync: boolean, verbose: boolean, ) { const {compilerVersion, isCompilerBuildValid, mode, filter, debug} = state; if (isCompilerBuildValid) { const start = performance.now(); // console.clear() only works when stdout is connected to a TTY device. // we're currently piping stdout (see main.ts), so let's do a 'hack' console.log('\u001Bc'); // we don't clear console after this point, since // it may contain debug console logging const results = await runFixtures( worker, mode.filter ? filter : null, compilerVersion, debug, true, // requireSingleFixture in watch mode sync, ); const end = performance.now(); // Track fixture status for autocomplete suggestions for (const [basename, result] of results) { const failed = result.actual !== result.expected || result.unexpectedError != null; state.fixtureLastRunStatus.set(basename, failed ? 'fail' : 'pass'); } if (mode.action === RunnerAction.Update) { update(results); state.lastUpdate = end; } else { report(results, verbose); } console.log(`Completed in ${Math.floor(end - start)} ms`); } else { console.error( `${mode}: Found errors in Forget source code, skipping test fixtures.`, ); } console.log( '\n' + (mode.filter ? `Current mode = FILTER, pattern = "${filter?.paths[0] ?? ''}".` : 'Current mode = NORMAL, run all test fixtures.') + '\nWaiting for input or file changes...\n' + 'u - update all fixtures\n' + `d - toggle (turn ${debug ? 'off' : 'on'}) debug logging\n` + 'p - enter pattern to filter fixtures\n' + (mode.filter ? 'a - run all tests (exit filter mode)\n' : '') + 'q - quit\n' + '[any] - rerun tests\n', ); } ================================================ FILE: compiler/packages/snap/src/sprout/README.md ================================================ ## Sprout 🌱 React Forget test framework that executes compiler fixtures. Currently, Sprout runs each fixture with a known set of inputs and annotations. Sprout compares execution outputs (i.e. return values and console logs) of original source code and the corresponding Forget-transformed version. We hope to add fuzzing capabilities to Sprout, synthesizing sets of program inputs based on type and/or effect annotations. Sprout is now enabled for all fixtures! If Sprout cannot execute your fixture due to some technical limitations, add your fixture to [`SproutTodoFilter.ts`](./src/SproutTodoFilter.ts) with a comment explaining why. ### Sprout CLI Sprout is now run as a part of snap, except when in filter mode. ### Adding fixtures to Sprout #### 1. Annotate fixtures. Each fixture test executed by Sprout needs to export const `FIXTURE_ENTRYPOINT` object with the following type signature. ```js type FixtureEntrypoint = { // function to be invoked fn: ((...params: Array) => any), // params to pass to fn // (if `fn` is a react component, this should be an array // with exactly one element -- props) params: Array, } ``` Example: ```js // test.js function MyComponent(props) { return
{props.a + props.b}
; } export const FIXTURE_ENTRYPOINT = { fn: MyComponent, params: [{a: "hello ", b: "world"}], }; ``` #### 2. Import / define helper functions. - Prefer importing helper functions for readability and simplicity. - Fixtures that require helper functions with specific types or mutability can define their own within the same fixture file. ```js // test.js import { addOne } from 'shared-runtime'; function customHelper(val1, val2) { // This directive is important, as helper functions don't // always follow the rules of React. "use no forget"; // ... } // ... ``` #### Notes - If your fixture needs to import from an external module, we currently only support importing from `react` (see Milestones todo list). - Any fixture can use React hooks, but they need to be first imported. We may later enforce that only `isComponent: true` fixtures can use React hooks. ```ts import {useState} from 'react'; ``` - If your fixture wants to export multiple functions to Sprout to run, please split up the fixture into multiple files (e.g. `test-case-1`, `test-case-2`, etc). - Sprout currently runs each fixture in an iife to prevent variable collisions, but it does not run fixtures in isolation. Please do not mutate any external state in fixtures. - Sprout does not run fixtures listed in [`SproutTodoFilter.ts`](./src/SproutTodoFilter.ts), even in filter mode. ### Milestones: - [✅] Render fixtures with React runtime / `testing-library/react`. - [✅] Make Sprout CLI -runnable and report results in process exit code. - [✅] Enable Sprout by default and run it in the Github Actions pipeline. - [🚧] Make all existing test fixtures Sprout compatible (see `SproutTodoFilter.ts`). This involves each fixture being annotated with `FIXTURE_ENTRYPOINT` and using shared functions and/or defining its own helpers. - 77 done, ~410 to go - [✅] *(optional)* Store Sprout output as snapshot files. i.e. each fixture could have a `fixture.js`, `fixture.snap.md`, and `fixture.sprout.md`. - [✅] Add support for `fbt`. ================================================ FILE: compiler/packages/snap/src/sprout/ReactForgetFeatureFlag.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ export function isForgetEnabled_Fixtures(): boolean { return true; } ================================================ FILE: compiler/packages/snap/src/sprout/evaluator.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import {render} from '@testing-library/react'; import {JSDOM} from 'jsdom'; import React, {MutableRefObject} from 'react'; import util from 'util'; import {z} from 'zod/v4'; import {fromZodError} from 'zod-validation-error/v4'; import {initFbt, toJSON} from './shared-runtime'; /** * Set up the global environment for JSDOM tests. * This is a hack to let us share code and setup between the test * and runner environments. As an alternative, we could evaluate all setup * in the jsdom test environment (which provides more isolation), but that * may be slower. */ const {window: testWindow} = new JSDOM(undefined); (globalThis as any).document = testWindow.document; (globalThis as any).window = testWindow.window; (globalThis as any).React = React; (globalThis as any).render = render; initFbt(); (globalThis as any).placeholderFn = function (..._args: Array) { throw new Error('Fixture not implemented!'); }; export type EvaluatorResult = { kind: 'ok' | 'exception' | 'UnexpectedError'; value: string; logs: Array; }; /** * Define types and schemas for fixture entrypoint */ const EntrypointSchema = z.strictObject({ fn: z.union([z.function(), z.object({})]), params: z.array(z.any()), // DEPRECATED, unused isComponent: z.optional(z.boolean()), // if enabled, the `fn` is assumed to be a component and this is assumed // to be an array of props. the component is mounted once and rendered // once per set of props in this array. sequentialRenders: z.optional(z.nullable(z.array(z.any()))).default(null), }); const ExportSchema = z.object({ FIXTURE_ENTRYPOINT: EntrypointSchema, }); const NO_ERROR_SENTINEL = Symbol(); /** * Wraps WrapperTestComponent in an error boundary to simplify re-rendering * when an exception is thrown. * A simpler alternative may be to re-mount test components manually. */ class WrapperTestComponentWithErrorBoundary extends React.Component< {fn: any; params: Array}, {errorFromLastRender: any} > { /** * Limit retries of the child component by caching seen errors. */ propsErrorMap: Map; lastProps: any | null; // lastProps: object | null; constructor(props: any) { super(props); this.lastProps = null; this.propsErrorMap = new Map(); this.state = { errorFromLastRender: NO_ERROR_SENTINEL, }; } static getDerivedStateFromError(error: any) { // Reschedule a second render that immediately returns the cached error return {errorFromLastRender: error}; } override componentDidUpdate() { if (this.state.errorFromLastRender !== NO_ERROR_SENTINEL) { // Reschedule a third render that immediately returns the cached error this.setState({errorFromLastRender: NO_ERROR_SENTINEL}); } } override render() { if ( this.state.errorFromLastRender !== NO_ERROR_SENTINEL && this.props === this.lastProps ) { /** * The last render errored, cache the error message to avoid running the * test fixture more than once */ const errorMsg = `[[ (exception in render) ${this.state.errorFromLastRender?.toString()} ]]`; this.propsErrorMap.set(this.lastProps, errorMsg); return errorMsg; } this.lastProps = this.props; const cachedError = this.propsErrorMap.get(this.props); if (cachedError != null) { return cachedError; } return React.createElement(WrapperTestComponent, this.props); } } function WrapperTestComponent(props: {fn: any; params: Array}) { const result = props.fn(...props.params); // Hacky solution to determine whether the fixture returned jsx (which // needs to passed through to React's runtime as-is) or a non-jsx value // (which should be converted to a string). if (typeof result === 'object' && result != null && '$$typeof' in result) { return result; } else { return toJSON(result); } } function renderComponentSequentiallyForEachProps( fn: any, sequentialRenders: Array, ): string { if (sequentialRenders.length === 0) { throw new Error( 'Expected at least one set of props when using `sequentialRenders`', ); } const initialProps = sequentialRenders[0]!; const results = []; const {rerender, container} = render( React.createElement(WrapperTestComponentWithErrorBoundary, { fn, params: [initialProps], }), ); results.push(container.innerHTML); for (let i = 1; i < sequentialRenders.length; i++) { rerender( React.createElement(WrapperTestComponentWithErrorBoundary, { fn, params: [sequentialRenders[i]], }), ); results.push(container.innerHTML); } return results.join('\n'); } type FixtureEvaluatorResult = Omit; (globalThis as any).evaluateFixtureExport = function ( exports: unknown, ): FixtureEvaluatorResult { const parsedExportResult = ExportSchema.safeParse(exports); if (!parsedExportResult.success) { const exportDetail = typeof exports === 'object' && exports != null ? `object ${util.inspect(exports)}` : `${exports}`; return { kind: 'UnexpectedError', value: `${fromZodError(parsedExportResult.error)}\nFound ` + exportDetail, }; } const entrypoint = parsedExportResult.data.FIXTURE_ENTRYPOINT; if (entrypoint.sequentialRenders !== null) { const result = renderComponentSequentiallyForEachProps( entrypoint.fn, entrypoint.sequentialRenders, ); return { kind: 'ok', value: result ?? 'null', }; } else if (typeof entrypoint.fn === 'object') { // Try to run fixture as a react component. This is necessary because not // all components are functions (some are ForwardRef or Memo objects). const result = render( React.createElement(entrypoint.fn as any, entrypoint.params[0]), ).container.innerHTML; return { kind: 'ok', value: result ?? 'null', }; } else { const result = render(React.createElement(WrapperTestComponent, entrypoint)) .container.innerHTML; return { kind: 'ok', value: result ?? 'null', }; } }; export function doEval(source: string): EvaluatorResult { 'use strict'; const originalConsole = globalThis.console; const logs: Array = []; const mockedLog = (...args: Array) => { logs.push( `${args.map(arg => { if (arg instanceof Error) { return arg.toString(); } else { return util.inspect(arg); } })}`, ); }; (globalThis.console as any) = { info: mockedLog, log: mockedLog, warn: mockedLog, error: (...args: Array) => { if ( typeof args[0] === 'string' && args[0].includes('ReactDOMTestUtils.act` is deprecated') ) { // remove this once @testing-library/react is upgraded to React 19. return; } const stack = new Error().stack?.split('\n', 5) ?? []; for (const stackFrame of stack) { // React warns on exceptions thrown during render, we avoid printing // here to reduce noise in test fixture outputs. if ( (stackFrame.includes('at logCaughtError') && stackFrame.includes('react-dom-client.development.js')) || (stackFrame.includes('at defaultOnRecoverableError') && stackFrame.includes('react-dom-client.development.js')) ) { return; } } mockedLog(...args); }, table: mockedLog, trace: () => {}, }; try { // source needs to be evaluated in the same scope as invoke const evalResult: any = eval(` (() => { // Exports should be overwritten by source let exports = { FIXTURE_ENTRYPOINT: { fn: globalThis.placeholderFn, params: [], }, }; let reachedInvoke = false; try { // run in an iife to avoid naming collisions (() => {${source}})(); reachedInvoke = true; if (exports.FIXTURE_ENTRYPOINT?.fn === globalThis.placeholderFn) { return { kind: "exception", value: "Fixture not implemented", }; } return evaluateFixtureExport(exports); } catch (e) { if (!reachedInvoke) { return { kind: "UnexpectedError", value: e.message, }; } else { return { kind: "exception", value: e.message, }; } } })()`); const result = { ...evalResult, logs, }; return result; } catch (e) { // syntax errors will cause the eval to throw and bubble up here return { kind: 'UnexpectedError', value: 'Unexpected error during eval, possible syntax error?\n' + e.message + '\n\nsource:\n' + source, logs, }; } finally { globalThis.console = originalConsole; } } ================================================ FILE: compiler/packages/snap/src/sprout/index.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import {EvaluatorResult, doEval} from './evaluator'; export type SproutResult = | {kind: 'success'; value: string} | {kind: 'invalid'; value: string}; function stringify(result: EvaluatorResult): string { return `(kind: ${result.kind}) ${result.value}${ result.logs.length > 0 ? `\nlogs: [${result.logs.toString()}]` : '' }`; } function makeError(description: string, value: string): SproutResult { return { kind: 'invalid', value: description + '\n' + value, }; } function logsEqual(a: Array, b: Array) { if (a.length !== b.length) { return false; } return a.every((val, idx) => val === b[idx]); } export function runSprout( originalCode: string, forgetCode: string, ): SproutResult { let forgetResult; try { (globalThis as any).__SNAP_EVALUATOR_MODE = 'forget'; forgetResult = doEval(forgetCode); } catch (e) { throw e; } finally { (globalThis as any).__SNAP_EVALUATOR_MODE = undefined; } if (forgetResult.kind === 'UnexpectedError') { return makeError('Unexpected error in Forget runner', forgetResult.value); } if (originalCode.indexOf('@disableNonForgetInSprout') === -1) { const nonForgetResult = doEval(originalCode); if (nonForgetResult.kind === 'UnexpectedError') { return makeError( 'Unexpected error in non-forget runner', nonForgetResult.value, ); } else if ( forgetResult.kind !== nonForgetResult.kind || forgetResult.value !== nonForgetResult.value || !logsEqual(forgetResult.logs, nonForgetResult.logs) ) { return makeError( 'Found differences in evaluator results', `Non-forget (expected): ${stringify(nonForgetResult)} Forget: ${stringify(forgetResult)} `, ); } } return { kind: 'success', value: stringify(forgetResult), }; } ================================================ FILE: compiler/packages/snap/src/sprout/shared-runtime-type-provider.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import type { Effect, ValueKind, ValueReason, } from 'babel-plugin-react-compiler/src'; import type {TypeConfig} from 'babel-plugin-react-compiler/src/HIR/TypeSchema'; export function makeSharedRuntimeTypeProvider({ EffectEnum, ValueKindEnum, ValueReasonEnum, }: { EffectEnum: typeof Effect; ValueKindEnum: typeof ValueKind; ValueReasonEnum: typeof ValueReason; }) { return function sharedRuntimeTypeProvider( moduleName: string, ): TypeConfig | null { if (moduleName === 'shared-runtime') { return { kind: 'object', properties: { default: { kind: 'function', calleeEffect: EffectEnum.Read, positionalParams: [], restParam: EffectEnum.Read, returnType: {kind: 'type', name: 'Primitive'}, returnValueKind: ValueKindEnum.Primitive, }, graphql: { kind: 'function', calleeEffect: EffectEnum.Read, positionalParams: [], restParam: EffectEnum.Read, returnType: {kind: 'type', name: 'Primitive'}, returnValueKind: ValueKindEnum.Primitive, }, typedArrayPush: { kind: 'function', calleeEffect: EffectEnum.Read, positionalParams: [EffectEnum.Store, EffectEnum.Capture], restParam: EffectEnum.Capture, returnType: {kind: 'type', name: 'Primitive'}, returnValueKind: ValueKindEnum.Primitive, }, typedLog: { kind: 'function', calleeEffect: EffectEnum.Read, positionalParams: [], restParam: EffectEnum.Read, returnType: {kind: 'type', name: 'Primitive'}, returnValueKind: ValueKindEnum.Primitive, }, useFreeze: { kind: 'hook', returnType: {kind: 'type', name: 'Any'}, }, useFragment: { kind: 'hook', returnType: {kind: 'type', name: 'MixedReadonly'}, noAlias: true, }, useNoAlias: { kind: 'hook', returnType: {kind: 'type', name: 'Any'}, returnValueKind: ValueKindEnum.Mutable, noAlias: true, }, typedIdentity: { kind: 'function', positionalParams: [EffectEnum.Read], restParam: null, calleeEffect: EffectEnum.Read, returnType: {kind: 'type', name: 'Any'}, returnValueKind: ValueKindEnum.Mutable, aliasing: { receiver: '@receiver', params: ['@value'], rest: null, returns: '@return', temporaries: [], effects: [{kind: 'Assign', from: '@value', into: '@return'}], }, }, typedAssign: { kind: 'function', positionalParams: [EffectEnum.Read], restParam: null, calleeEffect: EffectEnum.Read, returnType: {kind: 'type', name: 'Any'}, returnValueKind: ValueKindEnum.Mutable, aliasing: { receiver: '@receiver', params: ['@value'], rest: null, returns: '@return', temporaries: [], effects: [{kind: 'Assign', from: '@value', into: '@return'}], }, }, typedAlias: { kind: 'function', positionalParams: [EffectEnum.Read], restParam: null, calleeEffect: EffectEnum.Read, returnType: {kind: 'type', name: 'Any'}, returnValueKind: ValueKindEnum.Mutable, aliasing: { receiver: '@receiver', params: ['@value'], rest: null, returns: '@return', temporaries: [], effects: [ { kind: 'Create', into: '@return', value: ValueKindEnum.Mutable, reason: ValueReasonEnum.KnownReturnSignature, }, {kind: 'Alias', from: '@value', into: '@return'}, ], }, }, typedCapture: { kind: 'function', positionalParams: [EffectEnum.Read], restParam: null, calleeEffect: EffectEnum.Read, returnType: {kind: 'type', name: 'Array'}, returnValueKind: ValueKindEnum.Mutable, aliasing: { receiver: '@receiver', params: ['@value'], rest: null, returns: '@return', temporaries: [], effects: [ { kind: 'Create', into: '@return', value: ValueKindEnum.Mutable, reason: ValueReasonEnum.KnownReturnSignature, }, {kind: 'Capture', from: '@value', into: '@return'}, ], }, }, typedCreateFrom: { kind: 'function', positionalParams: [EffectEnum.Read], restParam: null, calleeEffect: EffectEnum.Read, returnType: {kind: 'type', name: 'Any'}, returnValueKind: ValueKindEnum.Mutable, aliasing: { receiver: '@receiver', params: ['@value'], rest: null, returns: '@return', temporaries: [], effects: [{kind: 'CreateFrom', from: '@value', into: '@return'}], }, }, typedMutate: { kind: 'function', positionalParams: [EffectEnum.Read, EffectEnum.Capture], restParam: null, calleeEffect: EffectEnum.Store, returnType: {kind: 'type', name: 'Primitive'}, returnValueKind: ValueKindEnum.Primitive, aliasing: { receiver: '@receiver', params: ['@object', '@value'], rest: null, returns: '@return', temporaries: [], effects: [ { kind: 'Create', into: '@return', value: ValueKindEnum.Primitive, reason: ValueReasonEnum.KnownReturnSignature, }, {kind: 'Mutate', value: '@object'}, {kind: 'Capture', from: '@value', into: '@object'}, ], }, }, PanResponder: { kind: 'object', properties: { create: { kind: 'function', positionalParams: [EffectEnum.Freeze], restParam: null, calleeEffect: EffectEnum.Read, returnType: {kind: 'type', name: 'Any'}, returnValueKind: ValueKindEnum.Frozen, aliasing: { receiver: '@receiver', params: ['@config'], rest: null, returns: '@returns', temporaries: [], effects: [ { kind: 'Freeze', value: '@config', reason: ValueReasonEnum.KnownReturnSignature, }, { kind: 'Create', into: '@returns', value: ValueKindEnum.Frozen, reason: ValueReasonEnum.KnownReturnSignature, }, { kind: 'ImmutableCapture', from: '@config', into: '@returns', }, ], }, }, }, }, }, }; } else if (moduleName === 'ReactCompilerKnownIncompatibleTest') { /** * Fake module used for testing validation of known incompatible * API validation */ return { kind: 'object', properties: { useKnownIncompatible: { kind: 'hook', positionalParams: [], restParam: EffectEnum.Read, returnType: {kind: 'type', name: 'Any'}, knownIncompatible: `useKnownIncompatible is known to be incompatible`, }, useKnownIncompatibleIndirect: { kind: 'hook', positionalParams: [], restParam: EffectEnum.Read, returnType: { kind: 'object', properties: { incompatible: { kind: 'function', positionalParams: [], restParam: EffectEnum.Read, calleeEffect: EffectEnum.Read, returnType: {kind: 'type', name: 'Any'}, returnValueKind: ValueKindEnum.Mutable, knownIncompatible: `useKnownIncompatibleIndirect returns an incompatible() function that is known incompatible`, }, }, }, }, knownIncompatible: { kind: 'function', positionalParams: [], restParam: EffectEnum.Read, calleeEffect: EffectEnum.Read, returnType: {kind: 'type', name: 'Any'}, returnValueKind: ValueKindEnum.Mutable, knownIncompatible: `useKnownIncompatible is known to be incompatible`, }, }, }; } else if (moduleName === 'ReactCompilerTest') { /** * Fake module used for testing validation that type providers return hook * types for hook names and non-hook types for non-hook names */ return { kind: 'object', properties: { useHookNotTypedAsHook: { kind: 'type', name: 'Any', }, notAhookTypedAsHook: { kind: 'hook', returnType: {kind: 'type', name: 'Any'}, }, }, }; } else if (moduleName === 'useDefaultExportNotTypedAsHook') { /** * Fake module used for testing validation that type providers return hook * types for hook names and non-hook types for non-hook names */ return { kind: 'object', properties: { default: { kind: 'type', name: 'Any', }, }, }; } return null; }; } ================================================ FILE: compiler/packages/snap/src/sprout/shared-runtime.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import {IntlVariations, IntlViewerContext, init} from 'fbt'; import React, {FunctionComponent} from 'react'; /** * This file is meant for use by `runner-evaluator` and fixture tests. * * Any fixture test can import constants or functions exported here. * However, the import path must be the relative path from `runner-evaluator` * (which calls `eval` on each fixture) to this file. * * ```js * // test.js * import {CONST_STRING0} from './shared-runtime'; * * // ... * ``` */ export type StringKeyedObject = {[key: string]: unknown}; export const CONST_STRING0 = 'global string 0'; export const CONST_STRING1 = 'global string 1'; export const CONST_STRING2 = 'global string 2'; export const CONST_NUMBER0 = 0; export const CONST_NUMBER1 = 1; export const CONST_NUMBER2 = 2; export const CONST_TRUE = true; export const CONST_FALSE = false; export function initFbt(): void { const viewerContext: IntlViewerContext = { GENDER: IntlVariations.GENDER_UNKNOWN, locale: 'en_US', }; init({ translations: {}, hooks: { getViewerContext: () => viewerContext, }, }); } export function mutate(arg: any): void { // don't mutate primitive if (arg == null || typeof arg !== 'object') { return; } else if (Array.isArray(arg)) { arg.push('joe'); } let count: number = 0; let key; while (true) { key = 'wat' + count; if (!Object.hasOwn(arg, key)) { arg[key] = 'joe'; return; } count++; } } export function mutateAndReturn(arg: T): T { mutate(arg); return arg; } export function mutateAndReturnNewValue(arg: T): string { mutate(arg); return 'hello!'; } export function setProperty(arg: any, property: any): void { // don't mutate primitive if (arg == null || typeof arg !== 'object') { return arg; } let count: number = 0; let key; while (true) { key = 'wat' + count; if (!Object.hasOwn(arg, key)) { arg[key] = property; return arg; } count++; } } export function setPropertyByKey< T, TKey extends keyof T, TProperty extends T[TKey], >(arg: T, key: TKey, property: TProperty): T { arg[key] = property; return arg; } export function arrayPush(arr: Array, ...values: Array): Array { arr.push(...values); return arr; } export function graphql(value: string): string { return value; } export function identity(x: T): T { return x; } export function getNumber(): number { return 4; } export function getNull(): null { return null; } export function getTrue(): true { return true; } export function getFalse(): false { return false; } export function calculateExpensiveNumber(x: number): number { return x; } /** * Functions that do not mutate their parameters */ export function shallowCopy(obj: T): T { return Object.assign({}, obj); } export function makeObject_Primitives(): StringKeyedObject { return {a: 0, b: 'value1', c: true}; } export function makeArray(...values: Array): Array { return [...values]; } export function addOne(value: number): number { return value + 1; } /* * Alias console.log, as it is defined as a global and may have * different compiler handling than unknown functions */ export function print(...args: Array): void { console.log(...args); } export function sum(...args: Array): number { return args.reduce((result, arg) => result + arg, 0); } export function throwErrorWithMessage(message: string): never { throw new Error(message); } export function throwInput(x: object): never { throw x; } export function throwErrorWithMessageIf(cond: boolean, message: string): void { if (cond) { throw new Error(message); } } export function logValue(value: T): void { console.log(value); } export function useHook(): object { return makeObject_Primitives(); } const noAliasObject = Object.freeze({}); export function useNoAlias(..._args: Array): object { return noAliasObject; } export function useIdentity(arg: T): T { return arg; } export function invoke, ReturnType>( fn: (...input: T) => ReturnType, ...params: T ): ReturnType { return fn(...params); } export function conditionalInvoke, ReturnType>( shouldInvoke: boolean, fn: (...input: T) => ReturnType, ...params: T ): ReturnType | null { if (shouldInvoke) { return fn(...params); } else { return null; } } /** * React Components */ export function Text(props: { value: string; children?: Array; }): React.ReactElement { return React.createElement('div', null, props.value, props.children); } export function StaticText1(props: { children?: Array; }): React.ReactElement { return React.createElement('div', null, 'StaticText1', props.children); } export function StaticText2(props: { children?: Array; }): React.ReactElement { return React.createElement('div', null, 'StaticText2', props.children); } export function RenderPropAsChild(props: { items: Array<() => React.ReactNode>; }): React.ReactElement { return React.createElement( 'div', null, 'HigherOrderComponent', props.items.map(item => item()), ); } export function Stringify(props: any): React.ReactElement { return React.createElement( 'div', null, toJSON(props, props?.shouldInvokeFns), ); } export function Throw() { throw new Error(); } export function ValidateMemoization({ inputs, output: rawOutput, onlyCheckCompiled = false, }: { inputs: Array; output: any; onlyCheckCompiled?: boolean; }): React.ReactElement { 'use no forget'; // Wrap rawOutput as it might be a function, which useState would invoke. const output = {value: rawOutput}; const [previousInputs, setPreviousInputs] = React.useState(inputs); const [previousOutput, setPreviousOutput] = React.useState(output); if ( !onlyCheckCompiled || (onlyCheckCompiled && (globalThis as any).__SNAP_EVALUATOR_MODE === 'forget') ) { if ( inputs.length !== previousInputs.length || inputs.some((item, i) => item !== previousInputs[i]) ) { // Some input changed, we expect the output to change setPreviousInputs(inputs); setPreviousOutput(output); } else if (output.value !== previousOutput.value) { // Else output should be stable throw new Error('Output identity changed but inputs did not'); } } return React.createElement(Stringify, {inputs, output: rawOutput}); } export function createHookWrapper( useMaybeHook: (props: TProps) => TRet, ): FunctionComponent { return function Component(props: TProps): React.ReactElement { const result = useMaybeHook(props); return Stringify({ result: result, shouldInvokeFns: true, }); }; } // helper functions export function toJSON(value: any, invokeFns: boolean = false): string { const seen = new Map(); return JSON.stringify(value, (_key: string, val: any) => { if (typeof val === 'function') { if (val.length === 0 && invokeFns) { return { kind: 'Function', result: val(), }; } else { return `[[ function params=${val.length} ]]`; } } else if (typeof val === 'object') { let id = seen.get(val); if (id != null) { return `[[ cyclic ref *${id} ]]`; } else if (val instanceof Map) { return { kind: 'Map', value: Array.from(val.entries()), }; } else if (val instanceof Set) { return { kind: 'Set', value: Array.from(val.values()), }; } seen.set(val, seen.size); } return val; }); } export class Builder { vals: Array = []; static makeBuilder(isNull: boolean, ...args: Array): Builder | null { if (isNull) { return null; } else { const builder = new Builder(); builder.push(...args); return builder; } } push(...args: Array): Builder { this.vals.push(...args); return this; } } export const ObjectWithHooks = { useFoo(): number { return 0; }, useMakeArray(): Array { return [1, 2, 3]; }, useIdentity(arg: T): T { return arg; }, }; export function useFragment(..._args: Array): object { return { a: [1, 2, 3], b: {c: {d: 4}}, }; } export function useSpecialEffect( fn: () => any, _secondArg: any, deps: Array, ) { React.useEffect(fn, deps); } export function typedArrayPush(array: Array, item: T): void { array.push(item); } export function typedLog(...values: Array): void { console.log(...values); } export function typedIdentity(value: T): T { return value; } export function typedAssign(x: T): T { return x; } export function typedAlias(x: T): T { return x; } export function typedCapture(x: T): Array { return [x]; } export function typedCreateFrom(array: Array): T { return array[0]; } export function typedMutate(x: any, v: any = null): void { x.property = v; } export const PanResponder = { create(obj: any): any { return obj; }, }; export default typedLog; ================================================ FILE: compiler/packages/snap/src/sprout/useEffectWrapper.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ /* This file is used to test the effect auto-deps configuration, which * allows you to specify functions that should have dependencies added to * callsites. */ import {useEffect} from 'react'; export default function useEffectWrapper(f: () => void | (() => void)): void { useEffect(() => { f(); }, [f]); } ================================================ FILE: compiler/packages/snap/src/types.d.ts ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ // v0.17.1 declare module 'hermes-parser' { type HermesParserOptions = { allowReturnOutsideFunction?: boolean; babel?: boolean; flow?: 'all' | 'detect'; enableExperimentalComponentSyntax?: boolean; sourceFilename?: string; sourceType?: 'module' | 'script' | 'unambiguous'; tokens?: boolean; }; export function parse(code: string, options: Partial); } ================================================ FILE: compiler/packages/snap/tsconfig.json ================================================ { "extends": "@tsconfig/strictest/tsconfig.json", "compilerOptions": { "module": "NodeNext", "moduleResolution": "NodeNext", "declaration": true, "outDir": "dist", "jsx": "react-jsxdev", "lib": ["ES2022"], // weaken strictness from preset "importsNotUsedAsValues": "remove", "noUncheckedIndexedAccess": false, "noUnusedParameters": false, "useUnknownInCatchVariables": false, "target": "ES2015", // ideally turn off only during dev, or on a per-file basis "noUnusedLocals": false, "sourceMap": true }, "exclude": ["node_modules"], "include": ["src/**/*.ts"], } ================================================ FILE: compiler/scripts/anonymize.js ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ 'use strict'; const fs = require('fs'); const HermesParser = require('hermes-parser'); const BabelParser = require('@babel/parser'); const BabelCore = require('@babel/core'); const invariant = require('invariant'); const {argv, stdin} = require('process'); const prettier = require('prettier'); const {JSXText} = require('hermes-parser/dist/generated/ESTreeVisitorKeys'); function runPlugin(text, file, language) { let ast; if (language === 'flow') { ast = HermesParser.parse(text, { babel: true, flow: 'all', sourceFilename: file, sourceType: 'module', enableExperimentalComponentSyntax: true, }); } else { ast = BabelParser.parse(text, { sourceFilename: file, plugins: ['typescript', 'jsx'], sourceType: 'module', }); } const result = BabelCore.transformFromAstSync(ast, text, { ast: false, filename: file, highlightCode: false, retainLines: true, plugins: [[AnonymizePlugin]], sourceType: 'module', configFile: false, babelrc: false, }); invariant( result?.code != null, `Expected BabelPluginReactForget to codegen successfully, got: ${result}` ); return result.code; } async function format(code, language) { return await prettier.format(code, { semi: true, parser: language === 'typescript' ? 'babel-ts' : 'flow', }); } const TAG_NAMES = new Set([ 'a', 'body', 'button', 'div', 'form', 'head', 'html', 'input', 'label', 'select', 'span', 'textarea', // property/attribute names 'value', 'checked', 'onClick', 'onSubmit', 'name', ]); const BUILTIN_HOOKS = new Set([ 'useContext', 'useEffect', 'useInsertionEffect', 'useLayoutEffect', 'useReducer', 'useState', ]); const GLOBALS = new Set([ 'String', 'Object', 'Function', 'Number', 'RegExp', 'Date', 'Error', 'Function', 'TypeError', 'RangeError', 'ReferenceError', 'SyntaxError', 'URIError', 'EvalError', 'Boolean', 'DataView', 'Float32Array', 'Float64Array', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Set', 'WeakMap', 'Uint8Array', 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'ArrayBuffer', 'JSON', 'parseFloat', 'parseInt', 'console', 'isNaN', 'eval', 'isFinite', 'encodeURI', 'decodeURI', 'encodeURIComponent', 'decodeURIComponent', // common method/property names of globals 'map', 'push', 'at', 'filter', 'slice', 'splice', 'add', 'get', 'set', 'has', 'size', 'length', 'toString', ]); function AnonymizePlugin(_babel) { let index = 0; const identifiers = new Map(); const literals = new Map(); return { name: 'anonymize', visitor: { JSXNamespacedName(path) { throw error('TODO: handle JSXNamedspacedName'); }, JSXIdentifier(path) { const name = path.node.name; if (TAG_NAMES.has(name)) { return; } let nextName = identifiers.get(name); if (nextName == null) { const isCapitalized = name.slice(0, 1).toUpperCase() === name.slice(0, 1); nextName = isCapitalized ? `Component${(index++).toString(16).toUpperCase()}` : `c${(index++).toString(16)}`; identifiers.set(name, nextName); } path.node.name = nextName; }, Identifier(path) { const name = path.node.name; if (BUILTIN_HOOKS.has(name) || GLOBALS.has(name)) { return; } let nextName = identifiers.get(name); if (nextName == null) { const isCapitalized = name.slice(0, 1).toUpperCase() === name.slice(0, 1); const prefix = isCapitalized ? 'V' : 'v'; nextName = `${prefix}${(index++).toString(16)}`; if (name.startsWith('use')) { nextName = 'use' + nextName.slice(0, 1).toUpperCase() + nextName.slice(1); } identifiers.set(name, nextName); } path.node.name = nextName; }, JSXText(path) { const value = path.node.value; let nextValue = literals.get(value); if (nextValue == null) { let string = ''; while (string.length < value.length) { string += String.fromCharCode(Math.round(Math.random() * 25) + 97); } nextValue = string; literals.set(value, nextValue); } path.node.value = nextValue; }, StringLiteral(path) { const value = path.node.value; let nextValue = literals.get(value); if (nextValue == null) { let string = ''; while (string.length < value.length) { string += String.fromCharCode(Math.round(Math.random() * 58) + 65); } nextValue = string; literals.set(value, nextValue); } path.node.value = nextValue; }, NumericLiteral(path) { const value = path.node.value; let nextValue = literals.get(value); if (nextValue == null) { nextValue = Number.isInteger(value) ? Math.round(Math.random() * Number.MAX_SAFE_INTEGER) : Math.random() * Number.MAX_VALUE; literals.set(value, nextValue); } path.node.value = nextValue; }, }, }; } let file; let text; if (argv.length >= 3) { file = argv[2]; text = fs.readFileSync(file, 'utf8'); } else { // read from stdin file = 'stdin.js'; text = fs.readFileSync(stdin.fd, 'utf8'); } const language = file.endsWith('.ts') || file.endsWith('.tsx') ? 'typescript' : 'flow'; const result = runPlugin(text, file, language); format(result, language).then(formatted => { console.log(formatted); }); ================================================ FILE: compiler/scripts/build-eslint-docs.js ================================================ const ReactCompiler = require('../packages/babel-plugin-react-compiler/dist'); const combinedRules = [ { name: 'rules-of-hooks', recommended: true, description: 'Validates that components and hooks follow the [Rules of Hooks](https://react.dev/reference/rules/rules-of-hooks)', }, { name: 'exhaustive-deps', recommended: true, description: 'Validates that hooks which accept dependency arrays (`useMemo()`, `useCallback()`, `useEffect()`, etc) ' + 'list all referenced variables in their dependency array. Referencing a value without including it in the ' + 'dependency array can lead to stale UI or callbacks.', }, ...ReactCompiler.LintRules, ]; const printed = combinedRules .filter( ruleConfig => ruleConfig.rule.recommended && ruleConfig.severity !== 'Off' ) .map(ruleConfig => { return ` ## \`react-hooks/${ruleConfig.rule.name}\` ${ruleConfig.rule.description} `.trim(); }) .join('\n\n'); console.log(printed); ================================================ FILE: compiler/scripts/copyright.js ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ 'use strict'; const fs = require('fs'); const glob = require('glob'); const META_COPYRIGHT_COMMENT_BLOCK = `/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */`.trim() + '\n\n'; const files = glob.sync('**/*.{js,ts,tsx,jsx,rs}', { ignore: [ '**/dist/**', '**/node_modules/**', '**/tests/fixtures/**', '**/__tests__/fixtures/**', ], }); const updatedFiles = new Map(); let hasErrors = false; files.forEach(file => { try { const result = processFile(file); if (result != null) { updatedFiles.set(file, result); } } catch (e) { console.error(e); hasErrors = true; } }); if (hasErrors) { console.error('Update failed'); process.exit(1); } else { for (const [file, source] of updatedFiles) { fs.writeFileSync(file, source, 'utf8'); } console.log('Update complete'); } function processFile(file) { if (fs.lstatSync(file).isDirectory()) { return; } let source = fs.readFileSync(file, 'utf8'); if (source.indexOf(META_COPYRIGHT_COMMENT_BLOCK) === 0) { return null; } if (/^\/\*\*/.test(source)) { source = source.replace(/\/\*\*[^\/]+\/\s+/, META_COPYRIGHT_COMMENT_BLOCK); } else { source = `${META_COPYRIGHT_COMMENT_BLOCK}${source}`; } return source; } ================================================ FILE: compiler/scripts/enable-feature-flag.js ================================================ #!/usr/bin/env node /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ 'use strict'; const fs = require('fs'); const path = require('path'); const {execSync} = require('child_process'); const yargs = require('yargs/yargs'); const {hideBin} = require('yargs/helpers'); // Constants const COMPILER_ROOT = path.resolve(__dirname, '..'); const ENVIRONMENT_TS_PATH = path.join( COMPILER_ROOT, 'packages/babel-plugin-react-compiler/src/HIR/Environment.ts' ); const FIXTURES_PATH = path.join( COMPILER_ROOT, 'packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler' ); const FIXTURE_EXTENSIONS = ['.js', '.jsx', '.ts', '.tsx']; /** * Parse command line arguments */ function parseArgs() { const argv = yargs(hideBin(process.argv)) .usage('Usage: $0 ') .command('$0 ', 'Enable a feature flag by default', yargs => { yargs.positional('flag-name', { describe: 'Name of the feature flag to enable', type: 'string', }); }) .example( '$0 validateExhaustiveMemoizationDependencies', 'Enable the validateExhaustiveMemoizationDependencies flag' ) .help('h') .alias('h', 'help') .strict() .parseSync(); return argv['flag-name']; } /** * Enable a feature flag in Environment.ts by changing default(false) to default(true) */ function enableFlagInEnvironment(flagName) { console.log(`\nEnabling flag "${flagName}" in Environment.ts...`); const content = fs.readFileSync(ENVIRONMENT_TS_PATH, 'utf8'); // Check if the flag exists with default(false) const flagPatternFalse = new RegExp( `(${escapeRegex(flagName)}:\\s*z\\.boolean\\(\\)\\.default\\()false(\\))`, 'g' ); if (!flagPatternFalse.test(content)) { // Check if flag exists at all const flagExistsPattern = new RegExp( `${escapeRegex(flagName)}:\\s*z\\.boolean\\(\\)`, 'g' ); if (flagExistsPattern.test(content)) { // Check if it's already true const flagPatternTrue = new RegExp( `${escapeRegex(flagName)}:\\s*z\\.boolean\\(\\)\\.default\\(true\\)`, 'g' ); if (flagPatternTrue.test(content)) { console.error(`Error: Flag "${flagName}" already has default(true)`); process.exit(1); } console.error( `Error: Flag "${flagName}" exists but doesn't have default(false)` ); process.exit(1); } console.error(`Error: Flag "${flagName}" not found in Environment.ts`); process.exit(1); } // Perform the replacement const newContent = content.replace(flagPatternFalse, '$1true$2'); // Verify the replacement worked if (content === newContent) { console.error(`Error: Failed to replace flag "${flagName}"`); process.exit(1); } fs.writeFileSync(ENVIRONMENT_TS_PATH, newContent, 'utf8'); console.log(`Successfully enabled "${flagName}" in Environment.ts`); } /** * Helper to escape regex special characters */ function escapeRegex(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } /** * Run yarn snap and capture output */ function runTests() { console.log('\nRunning test suite (yarn snap)...'); try { const output = execSync('yarn snap', { cwd: COMPILER_ROOT, encoding: 'utf8', stdio: 'pipe', maxBuffer: 10 * 1024 * 1024, // 10MB buffer }); return {success: true, output}; } catch (error) { // yarn snap exits with code 1 when tests fail, which throws an error return {success: false, output: error.stdout || error.message}; } } /** * Parse failing test names from test output */ function parseFailingTests(output) { const failingTests = []; // Look for lines that contain "FAIL:" followed by the test name // Format: "FAIL: test-name" or with ANSI codes const lines = output.split('\n'); for (const line of lines) { // Remove ANSI codes for easier parsing const cleanLine = line.replace(/\x1b\[[0-9;]*m/g, ''); // Match "FAIL: test-name" const match = cleanLine.match(/^FAIL:\s*(.+)$/); if (match) { failingTests.push(match[1].trim()); } } return failingTests; } /** * Find the fixture file for a given test name */ function findFixtureFile(testName) { const basePath = path.join(FIXTURES_PATH, testName); for (const ext of FIXTURE_EXTENSIONS) { const filePath = basePath + ext; if (fs.existsSync(filePath)) { return filePath; } } return null; } /** * Add pragma to disable the feature flag in a fixture file */ function addPragmaToFixture(filePath, flagName) { const content = fs.readFileSync(filePath, 'utf8'); const lines = content.split('\n'); if (lines.length === 0) { console.warn(`Warning: Empty file ${filePath}`); return false; } const firstLine = lines[0]; const pragma = `@${flagName}:false`; // Check if pragma already exists if (firstLine.includes(pragma)) { return false; // Already has the pragma } // Check if first line is a single-line comment if (firstLine.trim().startsWith('//')) { // Append pragma to existing comment lines[0] = firstLine + ' ' + pragma; } else if (firstLine.trim().startsWith('/*')) { // Multi-line comment - insert new line before it lines.unshift('// ' + pragma); } else { // No comment - insert new comment as first line lines.unshift('// ' + pragma); } fs.writeFileSync(filePath, lines.join('\n'), 'utf8'); return true; } /** * Update snapshot files */ function updateSnapshots() { console.log('\nUpdating snapshots (yarn snap -u)...'); try { execSync('yarn snap -u', { cwd: COMPILER_ROOT, encoding: 'utf8', stdio: 'pipe', maxBuffer: 10 * 1024 * 1024, }); console.log('Snapshots updated successfully'); return true; } catch (error) { console.error('Error updating snapshots:', error.message); return false; } } /** * Verify all tests pass */ function verifyAllTestsPass() { console.log('\nRunning final verification (yarn snap)...'); const {success, output} = runTests(); // Parse summary line: "N Tests, N Passed, N Failed" const summaryMatch = output.match( /(\d+)\s+Tests,\s+(\d+)\s+Passed,\s+(\d+)\s+Failed/ ); if (summaryMatch) { const [, total, passed, failed] = summaryMatch; console.log( `\nTest Results: ${total} Tests, ${passed} Passed, ${failed} Failed` ); if (failed === '0') { console.log('All tests passed!'); return true; } else { console.error(`${failed} tests still failing`); const failingTests = parseFailingTests(output); if (failingTests.length > 0) { console.error('\nFailing tests:'); failingTests.forEach(test => console.error(` - ${test}`)); } return false; } } return success; } /** * Main function */ async function main() { const flagName = parseArgs(); console.log(`\nEnabling flag: '${flagName}'`); try { // Step 1: Enable flag in Environment.ts enableFlagInEnvironment(flagName); // Step 2: Run tests to find failures const {output} = runTests(); const failingTests = parseFailingTests(output); console.log(`\nFound ${failingTests.length} failing tests`); if (failingTests.length === 0) { console.log('No failing tests! Feature flag enabled successfully.'); process.exit(0); } // Step 3: Add pragma to each failing fixture console.log(`\nAdding '@${flagName}:false' pragma to failing fixtures...`); const notFound = []; let notFoundCount = 0; for (const testName of failingTests) { const fixturePath = findFixtureFile(testName); if (!fixturePath) { console.warn(`Could not find fixture file for: ${testName}`); notFound.push(fixturePath); continue; } const updated = addPragmaToFixture(fixturePath, flagName); if (updated) { updatedCount++; console.log(` Updated: ${testName}`); } } console.log( `\nSummary: Updated ${updatedCount} fixtures, ${notFoundCount} not found` ); if (notFoundCount.length !== 0) { console.error( '\nFailed to update snapshots, could not find:\n' + notFound.join('\n') ); process.exit(1); } // Step 4: Update snapshots if (!updateSnapshots()) { console.error('\nFailed to update snapshots'); process.exit(1); } // Step 5: Verify all tests pass if (!verifyAllTestsPass()) { console.error('\nVerification failed: Some tests are still failing'); process.exit(1); } console.log('\nSuccess! Feature flag enabled and all tests passing.'); console.log(`\nSummary:`); console.log(` - Enabled "${flagName}" in Environment.ts`); console.log(` - Updated ${updatedCount} fixture files with pragma`); console.log(` - All tests passing`); process.exit(0); } catch (error) { console.error('\nFatal error:', error.message); console.error(error.stack); process.exit(1); } } // Run the script main(); ================================================ FILE: compiler/scripts/hash.sh ================================================ #!/usr/bin/env bash # Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. set -eo pipefail # Hashes JS files in the provided directory to create a cache-breaker find $1 -name '*.js' | sort | xargs shasum | shasum | awk '{ print $1 }' ================================================ FILE: compiler/scripts/release/ci-npmrc ================================================ //registry.npmjs.org/:_authToken=${NPM_TOKEN} ================================================ FILE: compiler/scripts/release/prompt-for-otp.js ================================================ #!/usr/bin/env node /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ const prompt = require('prompt-promise'); const run = async () => { while (true) { const otp = await prompt('NPM 2-factor auth code: '); prompt.done(); if (otp) { return otp; } else { console.error('\nTwo-factor auth is required to publish.'); // (Ask again.) } } }; module.exports = run; ================================================ FILE: compiler/scripts/release/publish.js ================================================ #!/usr/bin/env node /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ 'use strict'; const ora = require('ora'); const path = require('path'); const yargs = require('yargs'); const {hashElement} = require('folder-hash'); const promptForOTP = require('./prompt-for-otp'); const {PUBLISHABLE_PACKAGES} = require('./shared/packages'); const { execHelper, getDateStringForCommit, spawnHelper, } = require('./shared/utils'); const {buildPackages} = require('./shared/build-packages'); const {readJson, writeJson} = require('fs-extra'); /** * Script for publishing PUBLISHABLE_PACKAGES to npm. By default, this runs in tarball mode, meaning * the script will only print out what the contents of the files included in the npm tarball would * be. * * Please run this first (ie `yarn npm:publish`) and double check the contents of the files that * will be pushed to npm. * * If it looks good, you can run `yarn npm:publish --for-real` to really publish to npm. You must * have 2FA enabled first and the script will prompt you to enter a 2FA code before proceeding. * There's a small annoying delay before the packages are actually pushed to give you time to panic * cancel. In this mode, we will bump the version field of each package's package.json, and git * commit it. Then, the packages will be published to npm. * * Optionally, you can add the `--debug` flag to `yarn npm:publish --debug --for-real` to run all * steps, but the final npm publish step will have the `--dry-run` flag added to it. This will make * the command only report what it would have done, instead of actually publishing to npm. */ async function main() { const argv = yargs(process.argv.slice(2)) .option('packages', { description: 'which packages to publish, defaults to all', choices: PUBLISHABLE_PACKAGES, default: PUBLISHABLE_PACKAGES, }) .option('for-real', { alias: 'frfr', description: 'whether to publish to npm (npm publish) or dryrun (npm publish --dry-run)', type: 'boolean', default: false, }) .option('debug', { description: 'If enabled, will always run npm commands in dry run mode irregardless of the for-real flag', type: 'boolean', default: false, }) .option('ci', { description: 'Publish packages via CI', type: 'boolean', default: false, }) .option('tag', { description: 'Tag to publish to npm', type: 'choices', choices: ['experimental', 'beta', 'rc', 'latest'], default: 'experimental', }) .option('tag-version', { description: 'Optional tag version to append to tag name, eg `1` becomes 0.0.0-rc.1', type: 'number', default: null, }) .option('version-name', { description: 'Version name', type: 'string', default: '0.0.0', }) .help('help') .strict() .parseSync(); if (argv.debug === false) { const currBranchName = await execHelper('git rev-parse --abbrev-ref HEAD'); const isPristine = (await execHelper('git status --porcelain')) === ''; if (currBranchName !== 'main' || isPristine === false) { throw new Error( 'This script must be run from the `main` branch with no uncommitted changes' ); } } let pkgNames = argv.packages; if (Array.isArray(argv.packages) === false) { pkgNames = [argv.packages]; } const spinner = ora( `Preparing to publish ${argv.versionName}@${argv.tag} ${ argv.forReal === true ? '(for real)' : '(dry run)' } [debug=${argv.debug}]` ).info(); await buildPackages(pkgNames); if (argv.forReal === false) { spinner.info('Dry run: Report tarball contents'); for (const pkgName of pkgNames) { console.log(`\n========== ${pkgName} ==========\n`); spinner.start(`Running npm pack --dry-run\n`); try { await spawnHelper('npm', ['pack', '--dry-run'], { cwd: path.resolve(__dirname, `../../packages/${pkgName}`), stdio: 'inherit', }); } catch (e) { spinner.fail(e.toString()); throw e; } spinner.stop(`Successfully packed ${pkgName} (dry run)`); } spinner.succeed( 'Please confirm contents of packages before publishing. You can run this command again with --for-real to publish to npm' ); } if (argv.forReal === true) { const commit = await execHelper( 'git show -s --no-show-signature --format=%h', { cwd: path.resolve(__dirname, '..'), } ); const dateString = await getDateStringForCommit(commit); const otp = argv.ci === false && argv.debug === false ? await promptForOTP() : null; const {hash} = await hashElement(path.resolve(__dirname, '../..'), { encoding: 'hex', folders: {exclude: ['node_modules']}, files: {exclude: ['.DS_Store']}, }); const truncatedHash = hash.slice(0, 7); let newVersion; if (argv.tag === 'latest') { newVersion = argv.versionName; } else { newVersion = argv.tagVersion == null || argv.tagVersion === '' ? `${argv.versionName}-${argv.tag}` : `${argv.versionName}-${argv.tag}.${argv.tagVersion}`; } if (argv.tag === 'experimental' || argv.tag === 'beta') { newVersion = `${newVersion}-${truncatedHash}-${dateString}`; } for (const pkgName of pkgNames) { const pkgDir = path.resolve(__dirname, `../../packages/${pkgName}`); const pkgJsonPath = path.resolve( __dirname, `../../packages/${pkgName}/package.json` ); spinner.start(`Writing package.json for ${pkgName}@${newVersion}`); await writeJson( pkgJsonPath, { ...(await readJson(pkgJsonPath)), version: newVersion, }, {spaces: 2} ); spinner.succeed(`Wrote package.json for ${pkgName}@${newVersion}`); console.log(`\n========== ${pkgName} ==========\n`); spinner.start(`Publishing ${pkgName}@${newVersion} to npm\n`); let opts = []; if (argv.debug === true) { opts.push('--dry-run'); } if (otp != null) { opts.push(`--otp=${otp}`); } opts.push(`--tag=${argv.tag}`); try { await spawnHelper( 'npm', ['publish', ...opts, '--registry=https://registry.npmjs.org'], { cwd: pkgDir, stdio: 'inherit', } ); console.log('\n'); } catch (e) { spinner.fail(e.toString()); throw e; } spinner.succeed(`Successfully published ${pkgName} to npm`); spinner.start('Pushing tags to npm'); if (typeof argv.tag === 'string') { try { let opts = ['dist-tag', 'add', `${pkgName}@${newVersion}`, argv.tag]; if (otp != null) { opts.push(`--otp=${otp}`); } if (argv.debug === true) { spinner.info(`dry-run: npm ${opts.join(' ')}`); } else { await spawnHelper('npm', opts, { cwd: pkgDir, stdio: 'inherit', }); } } catch (e) { spinner.fail(e.toString()); throw e; } spinner.succeed( `Successfully pushed dist-tag ${argv.tag} for ${pkgName} to npm` ); } } console.log('\n\n✅ All done'); } } main(); ================================================ FILE: compiler/scripts/release/shared/build-packages.js ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ const ora = require('ora'); const {execHelper} = require('./utils'); async function buildPackages(pkgNames) { const spinner = ora(`Building packages`).info(); for (const pkgName of pkgNames) { const command = `NODE_ENV=production yarn workspace ${pkgName} run build --dts`; spinner.start(`Running: ${command}\n`); try { await execHelper(command); } catch (e) { spinner.fail(e.toString()); throw e; } spinner.succeed(`Successfully built ${pkgName}`); } spinner.stop(); } module.exports = { buildPackages, }; ================================================ FILE: compiler/scripts/release/shared/packages.js ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ const PUBLISHABLE_PACKAGES = [ 'babel-plugin-react-compiler', 'react-compiler-healthcheck', 'react-compiler-runtime', ]; module.exports = { PUBLISHABLE_PACKAGES, }; ================================================ FILE: compiler/scripts/release/shared/utils.js ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ const cp = require('child_process'); const util = require('util'); function execHelper(command, options, streamStdout = false) { return new Promise((resolve, reject) => { const proc = cp.exec(command, options, (error, stdout) => error ? reject(error) : resolve(stdout.trim()) ); if (streamStdout) { proc.stdout.pipe(process.stdout); } }); } function _spawn(command, args, options, cb) { const child = cp.spawn(command, args, options); child.on('close', exitCode => { cb(null, exitCode); }); return child; } const spawnHelper = util.promisify(_spawn); async function getDateStringForCommit(commit) { let dateString = await execHelper( `git show -s --no-show-signature --format=%cd --date=format:%Y%m%d ${commit}` ); // On CI environment, this string is wrapped with quotes '...'s if (dateString.startsWith("'")) { dateString = dateString.slice(1, 9); } return dateString; } module.exports = { execHelper, spawnHelper, getDateStringForCommit, }; ================================================ FILE: compiler/scripts/update-commit-message.js ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * INSTALLATION: * - `$ npm install octokit * - Get a token from https://github.com/settings/tokens for use in the command below, * set the token value as the GITHUB_AUTH_TOKEN environment variable * * USAGE: * - $ GITHUB_AUTH_TOKEN="..." git filter-branch -f --msg-filter "node update-commit-message.js" 2364096862b72cf4d801ef2008c54252335a2df9..HEAD */ const {Octokit, App} = require('octokit'); const fs = require('fs'); const OWNER = 'facebook'; const REPO = 'react-forget'; const octokit = new Octokit({auth: process.env.GITHUB_AUTH_TOKEN}); const fetchPullRequest = async pullNumber => { const response = await octokit.request( 'GET /repos/{owner}/{repo}/pulls/{pull_number}', { owner: OWNER, repo: REPO, pull_number: pullNumber, headers: { 'X-GitHub-Api-Version': '2022-11-28', }, } ); return {body: response.data.body, title: response.data.title}; }; function formatCommitMessage(str) { let formattedStr = ''; let line = ''; const trim = str.replace(/(\r\n|\n|\r)/gm, ' ').trim(); if (!trim) { return ''; } // Split the string into words const words = trim.split(' '); // Iterate over each word for (let i = 0; i < words.length; i++) { // If adding the next word doesn't exceed the line length limit, add it to the line if ((line + words[i]).length <= 80) { line += words[i] + ' '; } else { // Otherwise, add the line to the formatted string and start a new line formattedStr += line + '\n'; line = words[i] + ' '; } } // Add the last line to the formatted string formattedStr += line; return formattedStr; } function filterMsg(response) { const {body, title} = response; const msgs = body.split('\n\n').flatMap(x => x.split('\r\n')); const newMessage = []; // Add title msgs.unshift(title); for (const msg of msgs) { // remove "Stack from [ghstack] blurb" if (msg.startsWith('Stack from ')) { continue; } // remove "* #1234" if (msg.startsWith('* #')) { continue; } // remove "* __->__ #1234" if (msg.startsWith('* __')) { continue; } const formattedStr = formatCommitMessage(msg); if (!formattedStr) { continue; } newMessage.push(formattedStr); } const updatedMsg = newMessage.join('\n\n'); return updatedMsg; } function parsePullRequestNumber(text) { if (!text) { return null; } const ghstackUrlRegex = /https:\/\/github\.com\/[\w.-]+\/[\w.-]+\/pull\/(\d+)/; const ghstackMatch = text.match(ghstackUrlRegex); if (ghstackMatch) { return ghstackMatch[1]; } const firstLine = text.split('\n').filter(text => text.trim().length > 0)[0]; if (firstLine == null) { return null; } const prNumberRegex = /\(#(\d{3,})\)\s*$/; const prNumberMatch = firstLine.match(prNumberRegex); if (prNumberMatch) { return prNumberMatch[1]; } return null; } async function main() { const data = fs.readFileSync(0, 'utf-8'); const pr = parsePullRequestNumber(data); if (pr) { try { const response = await fetchPullRequest(pr); if (!response.body) { console.log(data); return; } const newMessage = filterMsg(response); console.log(newMessage); return; } catch (e) { console.log(data); return; } } console.log(data); } main(); ================================================ FILE: dangerfile.js ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ 'use strict'; /* eslint-disable no-for-of-loops/no-for-of-loops */ // Hi, if this is your first time editing/reading a Dangerfile, here's a summary: // It's a JS runtime which helps you provide continuous feedback inside GitHub. // // You can see the docs here: http://danger.systems/js/ // // If you want to test changes Danger, I'd recommend checking out an existing PR // and then running the `danger pr` command. // // You'll need a GitHub token, you can re-use this one: // // 0a7d5c3cad9a6dbec2d9 9a5222cf49062a4c1ef7 // // (Just remove the space) // // So, for example: // // `DANGER_GITHUB_API_TOKEN=[ENV_ABOVE] yarn danger pr https://github.com/facebook/react/pull/11865 const {markdown, danger, warn} = require('danger'); const {promisify} = require('util'); const glob = promisify(require('glob')); const gzipSize = require('gzip-size'); const {writeFileSync} = require('fs'); const {readFileSync, statSync} = require('fs'); const BASE_DIR = 'base-build'; const HEAD_DIR = 'build'; const CRITICAL_THRESHOLD = 0.02; const SIGNIFICANCE_THRESHOLD = 0.002; const CRITICAL_ARTIFACT_PATHS = new Set([ // We always report changes to these bundles, even if the change is // insignificant or non-existent. 'oss-stable/react-dom/cjs/react-dom.production.js', 'oss-stable/react-dom/cjs/react-dom-client.production.js', 'oss-experimental/react-dom/cjs/react-dom.production.js', 'oss-experimental/react-dom/cjs/react-dom-client.production.js', 'facebook-www/ReactDOM-prod.classic.js', 'facebook-www/ReactDOM-prod.modern.js', ]); const kilobyteFormatter = new Intl.NumberFormat('en', { style: 'unit', unit: 'kilobyte', minimumFractionDigits: 2, maximumFractionDigits: 2, }); function kbs(bytes) { return kilobyteFormatter.format(bytes / 1000); } const percentFormatter = new Intl.NumberFormat('en', { style: 'percent', signDisplay: 'exceptZero', minimumFractionDigits: 2, maximumFractionDigits: 2, }); function change(decimal) { if (decimal === Infinity) { return 'New file'; } if (decimal === -1) { return 'Deleted'; } if (decimal < 0.0001) { return '='; } return percentFormatter.format(decimal); } const header = ` | Name | +/- | Base | Current | +/- gzip | Base gzip | Current gzip | | ---- | --- | ---- | ------- | -------- | --------- | ------------ |`; function row(result, baseSha, headSha) { const diffViewUrl = `https://react-builds.vercel.app/commits/${headSha}/files/${result.path}?compare=${baseSha}`; const rowArr = [ `| [${result.path}](${diffViewUrl})`, `**${change(result.change)}**`, `${kbs(result.baseSize)}`, `${kbs(result.headSize)}`, `${change(result.changeGzip)}`, `${kbs(result.baseSizeGzip)}`, `${kbs(result.headSizeGzip)}`, ]; return rowArr.join(' | '); } (async function () { // Use git locally to grab the commit which represents the place // where the branches differ const upstreamRepo = danger.github.pr.base.repo.full_name; if (upstreamRepo !== 'facebook/react') { // Exit unless we're running in the main repo return; } let headSha; let baseSha; try { headSha = String(readFileSync(HEAD_DIR + '/COMMIT_SHA')).trim(); baseSha = String(readFileSync(BASE_DIR + '/COMMIT_SHA')).trim(); } catch { warn( "Failed to read build artifacts. It's possible a build configuration " + 'has changed upstream. Try pulling the latest changes from the ' + 'main branch.' ); return; } // Disable sizeBot in a Devtools Pull Request. Because that doesn't affect production bundle size. const commitFiles = [ ...danger.git.created_files, ...danger.git.deleted_files, ...danger.git.modified_files, ]; if ( commitFiles.every(filename => filename.includes('packages/react-devtools')) ) return; const resultsMap = new Map(); // Find all the head (current) artifacts paths. const headArtifactPaths = await glob('**/*.js', {cwd: 'build'}); for (const artifactPath of headArtifactPaths) { try { // This will throw if there's no matching base artifact const baseSize = statSync(BASE_DIR + '/' + artifactPath).size; const baseSizeGzip = gzipSize.fileSync(BASE_DIR + '/' + artifactPath); const headSize = statSync(HEAD_DIR + '/' + artifactPath).size; const headSizeGzip = gzipSize.fileSync(HEAD_DIR + '/' + artifactPath); resultsMap.set(artifactPath, { path: artifactPath, headSize, headSizeGzip, baseSize, baseSizeGzip, change: (headSize - baseSize) / baseSize, changeGzip: (headSizeGzip - baseSizeGzip) / baseSizeGzip, }); } catch { // There's no matching base artifact. This is a new file. const baseSize = 0; const baseSizeGzip = 0; const headSize = statSync(HEAD_DIR + '/' + artifactPath).size; const headSizeGzip = gzipSize.fileSync(HEAD_DIR + '/' + artifactPath); resultsMap.set(artifactPath, { path: artifactPath, headSize, headSizeGzip, baseSize, baseSizeGzip, change: Infinity, changeGzip: Infinity, }); } } // Check for base artifacts that were deleted in the head. const baseArtifactPaths = await glob('**/*.js', {cwd: 'base-build'}); for (const artifactPath of baseArtifactPaths) { if (!resultsMap.has(artifactPath)) { const baseSize = statSync(BASE_DIR + '/' + artifactPath).size; const baseSizeGzip = gzipSize.fileSync(BASE_DIR + '/' + artifactPath); const headSize = 0; const headSizeGzip = 0; resultsMap.set(artifactPath, { path: artifactPath, headSize, headSizeGzip, baseSize, baseSizeGzip, change: -1, changeGzip: -1, }); } } const results = Array.from(resultsMap.values()); results.sort((a, b) => b.change - a.change); let criticalResults = []; for (const artifactPath of CRITICAL_ARTIFACT_PATHS) { const result = resultsMap.get(artifactPath); if (result === undefined) { throw new Error( 'Missing expected bundle. If this was an intentional change to the ' + 'build configuration, update Dangerfile.js accordingly: ' + artifactPath ); } criticalResults.push(row(result, baseSha, headSha)); } let significantResults = []; for (const result of results) { // If result exceeds critical threshold, add to top section. if ( (result.change > CRITICAL_THRESHOLD || 0 - result.change > CRITICAL_THRESHOLD || // New file result.change === Infinity || // Deleted file result.change === -1) && // Skip critical artifacts. We added those earlier, in a fixed order. !CRITICAL_ARTIFACT_PATHS.has(result.path) ) { criticalResults.push(row(result, baseSha, headSha)); } // Do the same for results that exceed the significant threshold. These // will go into the bottom, collapsed section. Intentionally including // critical artifacts in this section, too. if ( result.change > SIGNIFICANCE_THRESHOLD || 0 - result.change > SIGNIFICANCE_THRESHOLD || result.change === Infinity || result.change === -1 ) { significantResults.push(row(result, baseSha, headSha)); } } const message = ` Comparing: ${baseSha}...${headSha} ## Critical size changes Includes critical production bundles, as well as any change greater than ${ CRITICAL_THRESHOLD * 100 }%: ${header} ${criticalResults.join('\n')} ## Significant size changes Includes any change greater than ${SIGNIFICANCE_THRESHOLD * 100}%: ${ significantResults.length > 0 ? `
Expand to show ${header} ${significantResults.join('\n')}
` : '(No significant changes)' } `; // GitHub comments are limited to 65536 characters. if (message.length > 65536) { // Make message available as an artifact writeFileSync('sizebot-message.md', message); markdown( 'The size diff is too large to display in a single comment. ' + `The GitHub action for this pull request contains an artifact called 'sizebot-message.md' with the full message.` ); } else { markdown(message); } })(); ================================================ FILE: fixtures/art/.gitignore ================================================ bundle.js ================================================ FILE: fixtures/art/README.md ================================================ # VectorWidget example To try this example, run: ``` yarn yarn build ``` in this directory, then open index.html in your browser. ================================================ FILE: fixtures/art/VectorWidget.js ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ 'use strict'; var Circle = require('react-art/Circle'); var React = require('react'); var ReactART = require('react-art'); var Group = ReactART.Group; var Shape = ReactART.Shape; var Surface = ReactART.Surface; var Transform = ReactART.Transform; var MOUSE_UP_DRAG = 0.978; var MOUSE_DOWN_DRAG = 0.9; var MAX_VEL = 11; var CLICK_ACCEL = 3; var BASE_VEL = 0.15; /** * An animated SVG component. */ class VectorWidget extends React.Component { /** * Initialize state members. */ state = {degrees: 0, velocity: 0, drag: MOUSE_UP_DRAG}; /** * When the component is mounted into the document - this is similar to a * constructor, but invoked when the instance is actually mounted into the * document. Here, we'll just set up an animation loop that invokes our * method. Binding of `this.onTick` is not needed because all React methods * are automatically bound before being mounted. */ componentDidMount() { this._interval = window.setInterval(this.onTick, 20); } componentWillUnmount() { window.clearInterval(this._interval); } onTick = () => { var nextDegrees = this.state.degrees + BASE_VEL + this.state.velocity; var nextVelocity = this.state.velocity * this.state.drag; this.setState({degrees: nextDegrees, velocity: nextVelocity}); }; /** * When mousing down, we increase the friction down the velocity. */ handleMouseDown = () => { this.setState({drag: MOUSE_DOWN_DRAG}); }; /** * Cause the rotation to "spring". */ handleMouseUp = () => { var nextVelocity = Math.min(this.state.velocity + CLICK_ACCEL, MAX_VEL); this.setState({velocity: nextVelocity, drag: MOUSE_UP_DRAG}); }; /** * This is the "main" method for any component. The React API allows you to * describe the structure of your UI component at *any* point in time. */ render() { return ( {this.renderGraphic(this.state.degrees)} ); } /** * Better SVG support for React coming soon. */ renderGraphic = rotation => { return ( ); }; } var BORDER_PATH = 'M3.00191459,4 C1.34400294,4 0,5.34785514 0,7.00550479 L0,220.994495 C0,222.65439 1.34239483,224 3.00191459,224 L276.998085,224 C278.655997,224 280,222.652145 280,220.994495 L280,7.00550479 C280,5.34561033 278.657605,4 276.998085,4 L3.00191459,4 Z M3.00191459,4'; var BG_PATH = 'M3.00191459,1 C1.34400294,1 0,2.34785514 0,4.00550479 L0,217.994495 C0,219.65439 1.34239483,221 3.00191459,221 L276.998085,221 C278.655997,221 280,219.652145 280,217.994495 L280,4.00550479 C280,2.34561033 278.657605,1 276.998085,1 L3.00191459,1 Z M3.00191459,1'; var BAR_PATH = 'M3.00191459,0 C1.34400294,0 0,1.34559019 0,3.00878799 L0,21 C0,21 0,21 0,21 L280,21 C280,21 280,21 280,21 L280,3.00878799 C280,1.34708027 278.657605,0 276.998085,0 L3.00191459,0 Z M3.00191459,0'; var RED_DOT_PATH = 'M12.5,17 C16.0898511,17 19,14.0898511 19,10.5 C19,6.91014895 16.0898511,4 12.5,4 C8.91014895,4 6,6.91014895 6,10.5 C6,14.0898511 8.91014895,17 12.5,17 Z M12.5,17'; var YELLOW_DOT_PATH = 'M31.5,17 C35.0898511,17 38,14.0898511 38,10.5 C38,6.91014895 35.0898511,4 31.5,4 C27.9101489,4 25,6.91014895 25,10.5 C25,14.0898511 27.9101489,17 31.5,17 Z M31.5,17'; var GREEN_DOT_PATH = 'M50.5,17 C54.0898511,17 57,14.0898511 57,10.5 C57,6.91014895 54.0898511,4 50.5,4 C46.9101489,4 44,6.91014895 44,10.5 C44,14.0898511 46.9101489,17 50.5,17 Z M50.5,17'; var RING_ONE_PATH = 'M84,121 C130.391921,121 168,106.673113 168,89 C168,71.3268871 130.391921,57 84,57 C37.6080787,57 0,71.3268871 0,89 C0,106.673113 37.6080787,121 84,121 Z M84,121'; var RING_TWO_PATH = 'M84,121 C130.391921,121 168,106.673113 168,89 C168,71.3268871 130.391921,57 84,57 C37.6080787,57 0,71.3268871 0,89 C0,106.673113 37.6080787,121 84,121 Z M84,121'; var RING_THREE_PATH = 'M84,121 C130.391921,121 168,106.673113 168,89 C168,71.3268871 130.391921,57 84,57 C37.6080787,57 0,71.3268871 0,89 C0,106.673113 37.6080787,121 84,121 Z M84,121'; var RING_TWO_ROTATE = new Transform() .translate(84.0, 89.0) .rotate(-240.0) .translate(-84.0, -89.0); var RING_THREE_ROTATE = new Transform() .translate(84.0, 89.0) .rotate(-300.0) .translate(-84.0, -89.0); module.exports = VectorWidget; ================================================ FILE: fixtures/art/app.js ================================================ 'use strict'; var React = require('react'); var ReactDOM = require('react-dom'); var VectorWidget = require('./VectorWidget'); ReactDOM.render(, document.getElementById('container')); ================================================ FILE: fixtures/art/index.html ================================================ VectorWidget

If you're seeing this message, it means you haven't generated the bundle file for this example. Try running:


    npm install
    npm run build
    

then reload the page.

================================================ FILE: fixtures/art/package.json ================================================ { "devDependencies": { "@babel/core": "^7.10.5", "@babel/plugin-proposal-class-properties": "^7.10.4", "@babel/preset-env": "^7.10.4", "@babel/preset-react": "^7.10.4", "babel-loader": "^8.1.0", "react": "^19.0.0", "react-art": "^19.0.0", "react-dom": "^19.0.0", "webpack": "^1.14.0" }, "scripts": { "prebuild": "cp -r ../../build/oss-experimental/* ./node_modules/", "build": "webpack app.js bundle.js" } } ================================================ FILE: fixtures/art/webpack.config.js ================================================ var webpack = require('webpack'); module.exports = { context: __dirname, entry: './app.js', module: { loaders: [ { loader: require.resolve('babel-loader'), test: /\.js$/, exclude: /node_modules/, query: { presets: [ require.resolve('@babel/preset-env'), require.resolve('@babel/preset-react'), ], plugins: [require.resolve('@babel/plugin-proposal-class-properties')], }, }, ], }, plugins: [ new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify('development'), }, }), ], resolve: { alias: { react: require.resolve('react'), }, }, }; ================================================ FILE: fixtures/attribute-behavior/.gitignore ================================================ # See https://help.github.com/ignore-files/ for more about ignoring files. # dependencies /node_modules # testing /coverage # production /build /public/react.development.js /public/react-dom.development.js /public/react-dom-server.browser.development.js # misc .DS_Store .env.local .env.development.local .env.test.local .env.production.local npm-debug.log* yarn-debug.log* yarn-error.log* ================================================ FILE: fixtures/attribute-behavior/AttributeTableSnapshot.md ================================================ ## `about` (on `
` inside `
`) | Test Case | Flags | Result | | --- | --- | --- | | `about=(string)`| (changed)| `"a string"` | | `about=(empty string)`| (changed)| `` | | `about=(array with string)`| (changed)| `"string"` | | `about=(empty array)`| (changed)| `` | | `about=(object)`| (changed)| `"result of toString()"` | | `about=(numeric string)`| (changed)| `"42"` | | `about=(-1)`| (changed)| `"-1"` | | `about=(0)`| (changed)| `"0"` | | `about=(integer)`| (changed)| `"1"` | | `about=(NaN)`| (changed, warning)| `"NaN"` | | `about=(float)`| (changed)| `"99.99"` | | `about=(true)`| (initial, warning)| `` | | `about=(false)`| (initial, warning)| `` | | `about=(string 'true')`| (changed)| `"true"` | | `about=(string 'false')`| (changed)| `"false"` | | `about=(string 'on')`| (changed)| `"on"` | | `about=(string 'off')`| (changed)| `"off"` | | `about=(symbol)`| (initial, warning)| `` | | `about=(function)`| (initial, warning)| `` | | `about=(null)`| (initial)| `` | | `about=(undefined)`| (initial)| `` | ## `aBoUt` (on `
` inside `
`) | Test Case | Flags | Result | | --- | --- | --- | | `aBoUt=(string)`| (changed, warning)| `"a string"` | | `aBoUt=(empty string)`| (changed, warning)| `` | | `aBoUt=(array with string)`| (changed, warning)| `"string"` | | `aBoUt=(empty array)`| (changed, warning)| `` | | `aBoUt=(object)`| (changed, warning)| `"result of toString()"` | | `aBoUt=(numeric string)`| (changed, warning)| `"42"` | | `aBoUt=(-1)`| (changed, warning)| `"-1"` | | `aBoUt=(0)`| (changed, warning)| `"0"` | | `aBoUt=(integer)`| (changed, warning)| `"1"` | | `aBoUt=(NaN)`| (changed, warning)| `"NaN"` | | `aBoUt=(float)`| (changed, warning)| `"99.99"` | | `aBoUt=(true)`| (initial, warning)| `` | | `aBoUt=(false)`| (initial, warning)| `` | | `aBoUt=(string 'true')`| (changed, warning)| `"true"` | | `aBoUt=(string 'false')`| (changed, warning)| `"false"` | | `aBoUt=(string 'on')`| (changed, warning)| `"on"` | | `aBoUt=(string 'off')`| (changed, warning)| `"off"` | | `aBoUt=(symbol)`| (initial, warning)| `` | | `aBoUt=(function)`| (initial, warning)| `` | | `aBoUt=(null)`| (initial, warning)| `` | | `aBoUt=(undefined)`| (initial, warning)| `` | ## `accent-Height` (on `` inside ``) | Test Case | Flags | Result | | --- | --- | --- | | `accent-Height=(string)`| (initial, warning, ssr mismatch)| `` | | `accent-Height=(empty string)`| (initial, warning, ssr mismatch)| `` | | `accent-Height=(array with string)`| (initial, warning, ssr mismatch)| `` | | `accent-Height=(empty array)`| (initial, warning, ssr mismatch)| `` | | `accent-Height=(object)`| (initial, warning, ssr mismatch)| `` | | `accent-Height=(numeric string)`| (initial, warning, ssr mismatch)| `` | | `accent-Height=(-1)`| (initial, warning, ssr mismatch)| `` | | `accent-Height=(0)`| (initial, warning, ssr mismatch)| `` | | `accent-Height=(integer)`| (initial, warning, ssr mismatch)| `` | | `accent-Height=(NaN)`| (initial, warning, ssr mismatch)| `` | | `accent-Height=(float)`| (initial, warning, ssr mismatch)| `` | | `accent-Height=(true)`| (initial, warning)| `` | | `accent-Height=(false)`| (initial, warning)| `` | | `accent-Height=(string 'true')`| (initial, warning, ssr mismatch)| `` | | `accent-Height=(string 'false')`| (initial, warning, ssr mismatch)| `` | | `accent-Height=(string 'on')`| (initial, warning, ssr mismatch)| `` | | `accent-Height=(string 'off')`| (initial, warning, ssr mismatch)| `` | | `accent-Height=(symbol)`| (initial, warning)| `` | | `accent-Height=(function)`| (initial, warning)| `` | | `accent-Height=(null)`| (initial, warning)| `` | | `accent-Height=(undefined)`| (initial, warning)| `` | ## `accent-height` (on `` inside ``) | Test Case | Flags | Result | | --- | --- | --- | | `accent-height=(string)`| (changed, warning)| `"a string"` | | `accent-height=(empty string)`| (changed, warning)| `` | | `accent-height=(array with string)`| (changed, warning)| `"string"` | | `accent-height=(empty array)`| (changed, warning)| `` | | `accent-height=(object)`| (changed, warning)| `"result of toString()"` | | `accent-height=(numeric string)`| (changed, warning)| `"42"` | | `accent-height=(-1)`| (changed, warning)| `"-1"` | | `accent-height=(0)`| (changed, warning)| `"0"` | | `accent-height=(integer)`| (changed, warning)| `"1"` | | `accent-height=(NaN)`| (changed, warning)| `"NaN"` | | `accent-height=(float)`| (changed, warning)| `"99.99"` | | `accent-height=(true)`| (initial, warning)| `` | | `accent-height=(false)`| (initial, warning)| `` | | `accent-height=(string 'true')`| (changed, warning)| `"true"` | | `accent-height=(string 'false')`| (changed, warning)| `"false"` | | `accent-height=(string 'on')`| (changed, warning)| `"on"` | | `accent-height=(string 'off')`| (changed, warning)| `"off"` | | `accent-height=(symbol)`| (initial, warning)| `` | | `accent-height=(function)`| (initial, warning)| `` | | `accent-height=(null)`| (initial, warning)| `` | | `accent-height=(undefined)`| (initial, warning)| `` | ## `accentHeight` (on `` inside ``) | Test Case | Flags | Result | | --- | --- | --- | | `accentHeight=(string)`| (changed)| `"a string"` | | `accentHeight=(empty string)`| (changed)| `` | | `accentHeight=(array with string)`| (changed)| `"string"` | | `accentHeight=(empty array)`| (changed)| `` | | `accentHeight=(object)`| (changed)| `"result of toString()"` | | `accentHeight=(numeric string)`| (changed)| `"42"` | | `accentHeight=(-1)`| (changed)| `"-1"` | | `accentHeight=(0)`| (changed)| `"0"` | | `accentHeight=(integer)`| (changed)| `"1"` | | `accentHeight=(NaN)`| (changed, warning)| `"NaN"` | | `accentHeight=(float)`| (changed)| `"99.99"` | | `accentHeight=(true)`| (initial, warning)| `` | | `accentHeight=(false)`| (initial, warning)| `` | | `accentHeight=(string 'true')`| (changed)| `"true"` | | `accentHeight=(string 'false')`| (changed)| `"false"` | | `accentHeight=(string 'on')`| (changed)| `"on"` | | `accentHeight=(string 'off')`| (changed)| `"off"` | | `accentHeight=(symbol)`| (initial, warning)| `` | | `accentHeight=(function)`| (initial, warning)| `` | | `accentHeight=(null)`| (initial)| `` | | `accentHeight=(undefined)`| (initial)| `` | ## `accept` (on `
`) | Test Case | Flags | Result | | --- | --- | --- | | `accept=(string)`| (changed)| `"a string"` | | `accept=(empty string)`| (initial)| `` | | `accept=(array with string)`| (changed)| `"string"` | | `accept=(empty array)`| (initial)| `` | | `accept=(object)`| (changed)| `"result of toString()"` | | `accept=(numeric string)`| (changed)| `"42"` | | `accept=(-1)`| (changed)| `"-1"` | | `accept=(0)`| (changed)| `"0"` | | `accept=(integer)`| (changed)| `"1"` | | `accept=(NaN)`| (changed, warning)| `"NaN"` | | `accept=(float)`| (changed)| `"99.99"` | | `accept=(true)`| (initial, warning)| `` | | `accept=(false)`| (initial, warning)| `` | | `accept=(string 'true')`| (changed)| `"true"` | | `accept=(string 'false')`| (changed)| `"false"` | | `accept=(string 'on')`| (changed)| `"on"` | | `accept=(string 'off')`| (changed)| `"off"` | | `accept=(symbol)`| (initial, warning)| `` | | `accept=(function)`| (initial, warning)| `` | | `accept=(null)`| (initial)| `` | | `accept=(undefined)`| (initial)| `` | ## `accept-charset` (on `
` inside `
`) | Test Case | Flags | Result | | --- | --- | --- | | `accept-charset=(string)`| (changed, warning)| `"a string"` | | `accept-charset=(empty string)`| (initial, warning)| `` | | `accept-charset=(array with string)`| (changed, warning)| `"string"` | | `accept-charset=(empty array)`| (initial, warning)| `` | | `accept-charset=(object)`| (changed, warning)| `"result of toString()"` | | `accept-charset=(numeric string)`| (changed, warning)| `"42"` | | `accept-charset=(-1)`| (changed, warning)| `"-1"` | | `accept-charset=(0)`| (changed, warning)| `"0"` | | `accept-charset=(integer)`| (changed, warning)| `"1"` | | `accept-charset=(NaN)`| (changed, warning)| `"NaN"` | | `accept-charset=(float)`| (changed, warning)| `"99.99"` | | `accept-charset=(true)`| (initial, warning)| `` | | `accept-charset=(false)`| (initial, warning)| `` | | `accept-charset=(string 'true')`| (changed, warning)| `"true"` | | `accept-charset=(string 'false')`| (changed, warning)| `"false"` | | `accept-charset=(string 'on')`| (changed, warning)| `"on"` | | `accept-charset=(string 'off')`| (changed, warning)| `"off"` | | `accept-charset=(symbol)`| (initial, warning)| `` | | `accept-charset=(function)`| (initial, warning)| `` | | `accept-charset=(null)`| (initial, warning)| `` | | `accept-charset=(undefined)`| (initial, warning)| `` | ## `accept-Charset` (on `` inside `
`) | Test Case | Flags | Result | | --- | --- | --- | | `accept-Charset=(string)`| (changed, warning)| `"a string"` | | `accept-Charset=(empty string)`| (initial, warning)| `` | | `accept-Charset=(array with string)`| (changed, warning)| `"string"` | | `accept-Charset=(empty array)`| (initial, warning)| `` | | `accept-Charset=(object)`| (changed, warning)| `"result of toString()"` | | `accept-Charset=(numeric string)`| (changed, warning)| `"42"` | | `accept-Charset=(-1)`| (changed, warning)| `"-1"` | | `accept-Charset=(0)`| (changed, warning)| `"0"` | | `accept-Charset=(integer)`| (changed, warning)| `"1"` | | `accept-Charset=(NaN)`| (changed, warning)| `"NaN"` | | `accept-Charset=(float)`| (changed, warning)| `"99.99"` | | `accept-Charset=(true)`| (initial, warning)| `` | | `accept-Charset=(false)`| (initial, warning)| `` | | `accept-Charset=(string 'true')`| (changed, warning)| `"true"` | | `accept-Charset=(string 'false')`| (changed, warning)| `"false"` | | `accept-Charset=(string 'on')`| (changed, warning)| `"on"` | | `accept-Charset=(string 'off')`| (changed, warning)| `"off"` | | `accept-Charset=(symbol)`| (initial, warning)| `` | | `accept-Charset=(function)`| (initial, warning)| `` | | `accept-Charset=(null)`| (initial, warning)| `` | | `accept-Charset=(undefined)`| (initial, warning)| `` | ## `acceptCharset` (on `` inside `
`) | Test Case | Flags | Result | | --- | --- | --- | | `acceptCharset=(string)`| (changed)| `"a string"` | | `acceptCharset=(empty string)`| (initial)| `` | | `acceptCharset=(array with string)`| (changed)| `"string"` | | `acceptCharset=(empty array)`| (initial)| `` | | `acceptCharset=(object)`| (changed)| `"result of toString()"` | | `acceptCharset=(numeric string)`| (changed)| `"42"` | | `acceptCharset=(-1)`| (changed)| `"-1"` | | `acceptCharset=(0)`| (changed)| `"0"` | | `acceptCharset=(integer)`| (changed)| `"1"` | | `acceptCharset=(NaN)`| (changed, warning)| `"NaN"` | | `acceptCharset=(float)`| (changed)| `"99.99"` | | `acceptCharset=(true)`| (initial, warning)| `` | | `acceptCharset=(false)`| (initial, warning)| `` | | `acceptCharset=(string 'true')`| (changed)| `"true"` | | `acceptCharset=(string 'false')`| (changed)| `"false"` | | `acceptCharset=(string 'on')`| (changed)| `"on"` | | `acceptCharset=(string 'off')`| (changed)| `"off"` | | `acceptCharset=(symbol)`| (initial, warning)| `` | | `acceptCharset=(function)`| (initial, warning)| `` | | `acceptCharset=(null)`| (initial)| `` | | `acceptCharset=(undefined)`| (initial)| `` | ## `accessKey` (on `
` inside `
`) | Test Case | Flags | Result | | --- | --- | --- | | `accessKey=(string)`| (changed)| `"a string"` | | `accessKey=(empty string)`| (initial)| `` | | `accessKey=(array with string)`| (changed)| `"string"` | | `accessKey=(empty array)`| (initial)| `` | | `accessKey=(object)`| (changed)| `"result of toString()"` | | `accessKey=(numeric string)`| (changed)| `"42"` | | `accessKey=(-1)`| (changed)| `"-1"` | | `accessKey=(0)`| (changed)| `"0"` | | `accessKey=(integer)`| (changed)| `"1"` | | `accessKey=(NaN)`| (changed, warning)| `"NaN"` | | `accessKey=(float)`| (changed)| `"99.99"` | | `accessKey=(true)`| (initial, warning)| `` | | `accessKey=(false)`| (initial, warning)| `` | | `accessKey=(string 'true')`| (changed)| `"true"` | | `accessKey=(string 'false')`| (changed)| `"false"` | | `accessKey=(string 'on')`| (changed)| `"on"` | | `accessKey=(string 'off')`| (changed)| `"off"` | | `accessKey=(symbol)`| (initial, warning)| `` | | `accessKey=(function)`| (initial, warning)| `` | | `accessKey=(null)`| (initial)| `` | | `accessKey=(undefined)`| (initial)| `` | ## `accumulate` (on `` inside ``) | Test Case | Flags | Result | | --- | --- | --- | | `accumulate=(string)`| (changed)| `"a string"` | | `accumulate=(empty string)`| (changed)| `` | | `accumulate=(array with string)`| (changed)| `"string"` | | `accumulate=(empty array)`| (changed)| `` | | `accumulate=(object)`| (changed)| `"result of toString()"` | | `accumulate=(numeric string)`| (changed)| `"42"` | | `accumulate=(-1)`| (changed)| `"-1"` | | `accumulate=(0)`| (changed)| `"0"` | | `accumulate=(integer)`| (changed)| `"1"` | | `accumulate=(NaN)`| (changed, warning)| `"NaN"` | | `accumulate=(float)`| (changed)| `"99.99"` | | `accumulate=(true)`| (initial, warning)| `` | | `accumulate=(false)`| (initial, warning)| `` | | `accumulate=(string 'true')`| (changed)| `"true"` | | `accumulate=(string 'false')`| (changed)| `"false"` | | `accumulate=(string 'on')`| (changed)| `"on"` | | `accumulate=(string 'off')`| (changed)| `"off"` | | `accumulate=(symbol)`| (initial, warning)| `` | | `accumulate=(function)`| (initial, warning)| `` | | `accumulate=(null)`| (initial)| `` | | `accumulate=(undefined)`| (initial)| `` | ## `action` (on `
` inside `
`) | Test Case | Flags | Result | | --- | --- | --- | | `action=(string)`| (changed)| `"https://reactjs.com/"` | | `action=(empty string)`| (initial)| `"http://localhost:3000/"` | | `action=(array with string)`| (changed)| `"https://reactjs.com/"` | | `action=(empty array)`| (initial)| `"http://localhost:3000/"` | | `action=(object)`| (changed)| `"http://localhost:3000/result%20of%20toString()"` | | `action=(numeric string)`| (changed)| `"http://localhost:3000/42"` | | `action=(-1)`| (changed)| `"http://localhost:3000/-1"` | | `action=(0)`| (changed)| `"http://localhost:3000/0"` | | `action=(integer)`| (changed)| `"http://localhost:3000/1"` | | `action=(NaN)`| (changed, warning)| `"http://localhost:3000/NaN"` | | `action=(float)`| (changed)| `"http://localhost:3000/99.99"` | | `action=(true)`| (initial, warning)| `"http://localhost:3000/"` | | `action=(false)`| (initial, warning)| `"http://localhost:3000/"` | | `action=(string 'true')`| (changed)| `"http://localhost:3000/true"` | | `action=(string 'false')`| (changed)| `"http://localhost:3000/false"` | | `action=(string 'on')`| (changed)| `"http://localhost:3000/on"` | | `action=(string 'off')`| (changed)| `"http://localhost:3000/off"` | | `action=(symbol)`| (initial, warning)| `"http://localhost:3000/"` | | `action=(function)`| (changed, ssr error, ssr mismatch)| `"javascript:throw new Error('A React form was unexpectedly submitted. If you called form.submit() manually, consider using form.requestSubmit() instead. If you\'re trying to use event.stopPropagation() in a submit event handler, consider also calling event.preventDefault().')"` | | `action=(null)`| (initial)| `"http://localhost:3000/"` | | `action=(undefined)`| (initial)| `"http://localhost:3000/"` | ## `additive` (on `` inside ``) | Test Case | Flags | Result | | --- | --- | --- | | `additive=(string)`| (changed)| `"a string"` | | `additive=(empty string)`| (changed)| `` | | `additive=(array with string)`| (changed)| `"string"` | | `additive=(empty array)`| (changed)| `` | | `additive=(object)`| (changed)| `"result of toString()"` | | `additive=(numeric string)`| (changed)| `"42"` | | `additive=(-1)`| (changed)| `"-1"` | | `additive=(0)`| (changed)| `"0"` | | `additive=(integer)`| (changed)| `"1"` | | `additive=(NaN)`| (changed, warning)| `"NaN"` | | `additive=(float)`| (changed)| `"99.99"` | | `additive=(true)`| (initial, warning)| `` | | `additive=(false)`| (initial, warning)| `` | | `additive=(string 'true')`| (changed)| `"true"` | | `additive=(string 'false')`| (changed)| `"false"` | | `additive=(string 'on')`| (changed)| `"on"` | | `additive=(string 'off')`| (changed)| `"off"` | | `additive=(symbol)`| (initial, warning)| `` | | `additive=(function)`| (initial, warning)| `` | | `additive=(null)`| (initial)| `` | | `additive=(undefined)`| (initial)| `` | ## `alignment-baseline` (on `` inside ``) | Test Case | Flags | Result | | --- | --- | --- | | `alignment-baseline=(string)`| (changed, warning)| `"a string"` | | `alignment-baseline=(empty string)`| (changed, warning)| `` | | `alignment-baseline=(array with string)`| (changed, warning)| `"string"` | | `alignment-baseline=(empty array)`| (changed, warning)| `` | | `alignment-baseline=(object)`| (changed, warning)| `"result of toString()"` | | `alignment-baseline=(numeric string)`| (changed, warning)| `"42"` | | `alignment-baseline=(-1)`| (changed, warning)| `"-1"` | | `alignment-baseline=(0)`| (changed, warning)| `"0"` | | `alignment-baseline=(integer)`| (changed, warning)| `"1"` | | `alignment-baseline=(NaN)`| (changed, warning)| `"NaN"` | | `alignment-baseline=(float)`| (changed, warning)| `"99.99"` | | `alignment-baseline=(true)`| (initial, warning)| `` | | `alignment-baseline=(false)`| (initial, warning)| `` | | `alignment-baseline=(string 'true')`| (changed, warning)| `"true"` | | `alignment-baseline=(string 'false')`| (changed, warning)| `"false"` | | `alignment-baseline=(string 'on')`| (changed, warning)| `"on"` | | `alignment-baseline=(string 'off')`| (changed, warning)| `"off"` | | `alignment-baseline=(symbol)`| (initial, warning)| `` | | `alignment-baseline=(function)`| (initial, warning)| `` | | `alignment-baseline=(null)`| (initial, warning)| `` | | `alignment-baseline=(undefined)`| (initial, warning)| `` | ## `alignmentBaseline` (on `` inside ``) | Test Case | Flags | Result | | --- | --- | --- | | `alignmentBaseline=(string)`| (changed)| `"a string"` | | `alignmentBaseline=(empty string)`| (changed)| `` | | `alignmentBaseline=(array with string)`| (changed)| `"string"` | | `alignmentBaseline=(empty array)`| (changed)| `` | | `alignmentBaseline=(object)`| (changed)| `"result of toString()"` | | `alignmentBaseline=(numeric string)`| (changed)| `"42"` | | `alignmentBaseline=(-1)`| (changed)| `"-1"` | | `alignmentBaseline=(0)`| (changed)| `"0"` | | `alignmentBaseline=(integer)`| (changed)| `"1"` | | `alignmentBaseline=(NaN)`| (changed, warning)| `"NaN"` | | `alignmentBaseline=(float)`| (changed)| `"99.99"` | | `alignmentBaseline=(true)`| (initial, warning)| `` | | `alignmentBaseline=(false)`| (initial, warning)| `` | | `alignmentBaseline=(string 'true')`| (changed)| `"true"` | | `alignmentBaseline=(string 'false')`| (changed)| `"false"` | | `alignmentBaseline=(string 'on')`| (changed)| `"on"` | | `alignmentBaseline=(string 'off')`| (changed)| `"off"` | | `alignmentBaseline=(symbol)`| (initial, warning)| `` | | `alignmentBaseline=(function)`| (initial, warning)| `` | | `alignmentBaseline=(null)`| (initial)| `` | | `alignmentBaseline=(undefined)`| (initial)| `` | ## `allowFullScreen` (on `
`) | Test Case | Flags | Result | | --- | --- | --- | | `allowFullScreen=(string)`| (changed)| `` | | `allowFullScreen=(empty string)`| (initial)| `` | | `allowFullScreen=(array with string)`| (changed)| `` | | `allowFullScreen=(empty array)`| (changed)| `` | | `allowFullScreen=(object)`| (changed)| `` | | `allowFullScreen=(numeric string)`| (changed)| `` | | `allowFullScreen=(-1)`| (changed)| `` | | `allowFullScreen=(0)`| (initial)| `` | | `allowFullScreen=(integer)`| (changed)| `` | | `allowFullScreen=(NaN)`| (initial, warning)| `` | | `allowFullScreen=(float)`| (changed)| `` | | `allowFullScreen=(true)`| (changed)| `` | | `allowFullScreen=(false)`| (initial)| `` | | `allowFullScreen=(string 'true')`| (changed, warning)| `` | | `allowFullScreen=(string 'false')`| (changed, warning)| `` | | `allowFullScreen=(string 'on')`| (changed)| `` | | `allowFullScreen=(string 'off')`| (changed)| `` | | `allowFullScreen=(symbol)`| (initial, warning)| `` | | `allowFullScreen=(function)`| (initial, warning)| `` | | `allowFullScreen=(null)`| (initial)| `` | | `allowFullScreen=(undefined)`| (initial)| `` | ## `allowfullscreen` (on ` ================================================ FILE: fixtures/devtools/regression/next.html ================================================ React next
If you are seeing this message, you are likely viewing this file using the file protocol which does not support cross origin requests.

Use the server script instead:

node ./fixtures/devtools/regression/server.js
open http://localhost:3000/next.html
================================================ FILE: fixtures/devtools/regression/server.js ================================================ #!/usr/bin/env node const finalhandler = require('finalhandler'); const http = require('http'); const serveStatic = require('serve-static'); // Serve fixtures folder const serve = serveStatic(__dirname, {index: 'index.html'}); // Create server const server = http.createServer(function onRequest(req, res) { serve(req, res, finalhandler(req, res)); }); // Listen server.listen(3000); ================================================ FILE: fixtures/devtools/regression/shared.js ================================================ /* eslint-disable react/react-in-jsx-scope, react/jsx-no-undef */ /* global React ReactCache ReactDOM SchedulerTracing ScheduleTracing */ const apps = []; const pieces = React.version.split('.'); const major = pieces[0] === '0' ? parseInt(pieces[1], 10) : parseInt(pieces[0], 10); const minor = pieces[0] === '0' ? parseInt(pieces[2], 10) : parseInt(pieces[1], 10); // Convenience wrapper to organize API features in DevTools. function Feature({children, label, version}) { return (
{label} {version}
{children}
); } // Simplify interaction tracing for tests below. let trace = null; if (typeof SchedulerTracing !== 'undefined') { trace = SchedulerTracing.unstable_trace; } else if (typeof ScheduleTracing !== 'undefined') { trace = ScheduleTracing.unstable_trace; } else { trace = (_, __, callback) => callback(); } // https://github.com/facebook/react/blob/main/CHANGELOG.md switch (major) { case 16: switch (minor) { case 7: if (typeof React.useState === 'function') { // Hooks function Hooks() { const [count, setCount] = React.useState(0); const incrementCount = React.useCallback( () => setCount(count + 1), [count] ); return (
count: {count}{' '}
); } apps.push( ); } case 6: // memo function LabelComponent({label}) { return ; } const AnonymousMemoized = React.memo(({label}) => ( )); const Memoized = React.memo(LabelComponent); const CustomMemoized = React.memo(LabelComponent); CustomMemoized.displayName = 'MemoizedLabelFunction'; apps.push( ); // Suspense const loadResource = ([text, ms]) => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(text); }, ms); }); }; const getResourceKey = ([text, ms]) => text; const Resource = ReactCache.unstable_createResource( loadResource, getResourceKey ); class Suspending extends React.Component { state = {useSuspense: false}; useSuspense = () => this.setState({useSuspense: true}); render() { if (this.state.useSuspense) { const text = Resource.read(['loaded', 2000]); return text; } else { return ; } } } apps.push( loading...
}> ); // lazy const LazyWithDefaultProps = React.lazy( () => new Promise(resolve => { function FooWithDefaultProps(props) { return (

{props.greeting}, {props.name}

); } FooWithDefaultProps.defaultProps = { name: 'World', greeting: 'Bonjour', }; resolve({ default: FooWithDefaultProps, }); }) ); apps.push( loading...
}> ); case 5: case 4: // unstable_Profiler class ProfilerChild extends React.Component { state = {count: 0}; incrementCount = () => this.setState(prevState => ({count: prevState.count + 1})); render() { return (
count: {this.state.count}{' '}
); } } const onRender = (...args) => {}; const Profiler = React.unstable_Profiler || React.Profiler; apps.push(
); case 3: // createContext() const LocaleContext = React.createContext(); LocaleContext.displayName = 'LocaleContext'; const ThemeContext = React.createContext(); apps.push( {theme =>
theme: {theme}
}
{locale =>
locale: {locale}
}
); // forwardRef() const AnonymousFunction = React.forwardRef((props, ref) => (
{props.children}
)); const NamedFunction = React.forwardRef(function named(props, ref) { return
{props.children}
; }); const CustomName = React.forwardRef((props, ref) => (
{props.children}
)); CustomName.displayName = 'CustomNameForwardRef'; apps.push( AnonymousFunction NamedFunction CustomName ); // StrictMode class StrictModeChild extends React.Component { render() { return 'StrictModeChild'; } } apps.push( ); // unstable_AsyncMode (later renamed to unstable_ConcurrentMode, then ConcurrentMode) const ConcurrentMode = React.ConcurrentMode || React.unstable_ConcurrentMode || React.unstable_AsyncMode; apps.push(
unstable_AsyncMode was added in 16.3, renamed to unstable_ConcurrentMode in 16.5, and then renamed to ConcurrentMode in 16.7
); case 2: // Fragment apps.push(
one
two
); case 1: case 0: default: break; } break; case 15: break; case 14: break; default: break; } function Even() { return (even); } // Simple stateful app shared by all React versions class SimpleApp extends React.Component { state = {count: 0}; incrementCount = () => { const updaterFn = prevState => ({count: prevState.count + 1}); trace('Updating count', performance.now(), () => this.setState(updaterFn)); }; render() { const {count} = this.state; return (
{count % 2 === 0 ? ( count: {count} ) : ( count: {count} )}{' '}
); } } apps.push( ); // This component, with the version prop, helps organize DevTools at a glance. function TopLevelWrapperForDevTools({version}) { let header =

React {version}

; if (version.includes('canary')) { const commitSha = version.match(/.+canary-(.+)/)[1]; header = (

React canary{' '} {commitSha}

); } else if (version.includes('alpha')) { header =

React next

; } return (
{header} {apps}
); } TopLevelWrapperForDevTools.displayName = 'React'; ReactDOM.render( , document.getElementById('root') ); ================================================ FILE: fixtures/devtools/regression/styles.css ================================================ body { font-family: sans-serif; font-size: 12px; } h1 { margin: 0; font-size: 20px; } h2 { margin: 1rem 0 0; } iframe { border: 1px solid #ddd; border-radius: 0.5rem; } code { white-space: nowrap; } .Feature { margin: 1rem 0; border-bottom: 1px solid #eee; padding-bottom: 1rem; } .FeatureHeader { font-size: 16px; margin-bottom: 0.5rem; } .FeatureCode { background-color: #eee; padding: 0.25rem; border-radius: 0.25rem; } ================================================ FILE: fixtures/devtools/scheduling-profiler/.gitignore ================================================ dependencies ================================================ FILE: fixtures/devtools/scheduling-profiler/README.md ================================================ # Test fixture for `packages/react-devtools-scheduling-profiler` 1. First, run the fixture: ```sh # In the root directory # Download the latest *experimental* React build scripts/release/download-experimental-build.js # Run this fixtures fixtures/devtools/scheduling-profiler/run.js ``` 2. Then open [localhost:8000/](http://localhost:8000/) and use the Performance tab in Chrome to reload-and-profile. 3. Now stop profiling and export JSON. 4. Lastly, open [react-scheduling-profiler.vercel.app](https://react-scheduling-profiler.vercel.app/) and upload the performance JSON data you just recorded. ================================================ FILE: fixtures/devtools/scheduling-profiler/app.js ================================================ const {createElement, useLayoutEffect, useState} = React; const {createRoot} = ReactDOM; function App() { const [isMounted, setIsMounted] = useState(false); useLayoutEffect(() => { setIsMounted(true); }, []); return createElement('div', null, `isMounted? ${isMounted}`); } const container = document.getElementById('container'); const root = createRoot(container); root.render(createElement(App)); ================================================ FILE: fixtures/devtools/scheduling-profiler/index.html ================================================ Scheduling Profiler Fixture
================================================ FILE: fixtures/devtools/scheduling-profiler/run.js ================================================ #!/usr/bin/env node 'use strict'; const { copyFileSync, existsSync, mkdirSync, readFileSync, rmdirSync, } = require('fs'); const {join} = require('path'); const http = require('http'); const DEPENDENCIES = [ ['scheduler/umd/scheduler.development.js', 'scheduler.js'], ['react/umd/react.development.js', 'react.js'], ['react-dom/umd/react-dom.development.js', 'react-dom.js'], ]; const BUILD_DIRECTORY = '../../../build/oss-experimental/'; const DEPENDENCIES_DIRECTORY = 'dependencies'; function initDependencies() { if (existsSync(DEPENDENCIES_DIRECTORY)) { rmdirSync(DEPENDENCIES_DIRECTORY, {recursive: true}); } mkdirSync(DEPENDENCIES_DIRECTORY); DEPENDENCIES.forEach(([from, to]) => { const fromPath = join(__dirname, BUILD_DIRECTORY, from); const toPath = join(__dirname, DEPENDENCIES_DIRECTORY, to); console.log(`Copying ${fromPath} => ${toPath}`); copyFileSync(fromPath, toPath); }); } function initServer() { const host = 'localhost'; const port = 8000; const requestListener = function (request, response) { let contents; switch (request.url) { case '/react.js': case '/react-dom.js': case '/scheduler.js': response.setHeader('Content-Type', 'text/javascript'); response.writeHead(200); contents = readFileSync( join(__dirname, DEPENDENCIES_DIRECTORY, request.url) ); response.end(contents); break; case '/app.js': response.setHeader('Content-Type', 'text/javascript'); response.writeHead(200); contents = readFileSync(join(__dirname, 'app.js')); response.end(contents); break; case '/index.html': default: response.setHeader('Content-Type', 'text/html'); response.writeHead(200); contents = readFileSync(join(__dirname, 'index.html')); response.end(contents); break; } }; const server = http.createServer(requestListener); server.listen(port, host, () => { console.log(`Server is running on http://${host}:${port}`); }); } initDependencies(); initServer(); ================================================ FILE: fixtures/devtools/standalone/index.html ================================================ TODO List
================================================ FILE: fixtures/dom/.gitignore ================================================ # See http://help.github.com/ignore-files/ for more about ignoring files. # dependencies node_modules # testing coverage # production build public/scheduler-unstable_mock.development.js public/scheduler-unstable_mock.production.min.js public/react.development.js public/react.production.min.js public/react-dom.development.js public/react-dom.production.min.js public/react-dom-server.browser.development.js public/react-dom-server.browser.production.min.js public/react-dom-test-utils.development.js public/react-dom-test-utils.production.min.js # misc .DS_Store .env npm-debug.log ================================================ FILE: fixtures/dom/README.md ================================================ # DOM Fixtures A set of DOM test cases for quickly identifying browser issues. ## Setup To reference a local build of React, first run `yarn build` at the root of the React project. Then: ``` cd fixtures/dom yarn yarn dev ``` The `dev` command runs a script that copies over the local build of react into the public directory. ================================================ FILE: fixtures/dom/package.json ================================================ { "name": "react-fixtures", "version": "0.1.0", "private": true, "devDependencies": { "react-scripts": "^1.0.11" }, "dependencies": { "@babel/standalone": "^7.0.0", "art": "^0.10.3", "classnames": "^2.2.5", "codemirror": "^5.40.0", "core-js": "^2.4.1", "jest-diff": "^29.4.1", "prop-types": "^15.6.0", "query-string": "^4.2.3", "react": "^19.0.0", "react-dom": "^19.0.0", "semver": "^5.5.0" }, "scripts": { "dev": "react-scripts start", "predev": "cp -a ../../build/oss-experimental/. node_modules", "build": "react-scripts build && cp build/index.html build/200.html", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" } } ================================================ FILE: fixtures/dom/public/act-dom.html ================================================ sanity test for ReactTestUtils.act this page tests whether act runs properly in a browser.
your console should say "5" ================================================ FILE: fixtures/dom/public/index.html ================================================ React App
================================================ FILE: fixtures/dom/public/renderer.html ================================================ Renderer

Loading

================================================ FILE: fixtures/dom/public/renderer.js ================================================ /** * Supports render.html, a piece of the hydration fixture. See /hydration */ 'use strict'; (function () { var Fixture = null; var output = document.getElementById('output'); var status = document.getElementById('status'); var hydrate = document.getElementById('hydrate'); var reload = document.getElementById('reload'); var renders = 0; var failed = false; var needsReactDOM = getBooleanQueryParam('needsReactDOM'); var needsCreateElement = getBooleanQueryParam('needsCreateElement'); function unmountComponent(node) { // ReactDOM was moved into a separate package in 0.14 if (needsReactDOM) { ReactDOM.unmountComponentAtNode(node); } else if (React.unmountComponentAtNode) { React.unmountComponentAtNode(node); } else { // Unmounting for React 0.4 and lower React.unmountAndReleaseReactRootNode(node); } } function createElement(value) { // React.createElement replaced function invocation in 0.12 if (needsCreateElement) { return React.createElement(value); } else { return value(); } } function getQueryParam(key) { var pattern = new RegExp(key + '=([^&]+)(&|$)'); var matches = window.location.search.match(pattern); if (matches) { return decodeURIComponent(matches[1]); } handleError(new Error('No key found for' + key)); } function getBooleanQueryParam(key) { return getQueryParam(key) === 'true'; } function setStatus(label) { status.innerHTML = label; } function prerender() { setStatus('Generating markup'); return Promise.resolve() .then(function () { const element = createElement(Fixture); // Server rendering moved to a separate package along with ReactDOM // in 0.14.0 if (needsReactDOM) { return ReactDOMServer.renderToString(element); } // React.renderComponentToString was renamed in 0.12 if (React.renderToString) { return React.renderToString(element); } // React.renderComponentToString became synchronous in React 0.9.0 if (React.renderComponentToString.length === 1) { return React.renderComponentToString(element); } // Finally, React 0.4 and lower emits markup in a callback return new Promise(function (resolve) { React.renderComponentToString(element, resolve); }); }) .then(function (string) { output.innerHTML = string; setStatus('Markup only (No React)'); }) .catch(handleError); } function render() { setStatus('Hydrating'); var element = createElement(Fixture); // ReactDOM was split out into another package in 0.14 if (needsReactDOM) { // Hydration changed to a separate method in React 16 if (ReactDOM.hydrate) { ReactDOM.hydrate(element, output); } else { ReactDOM.render(element, output); } } else if (React.render) { // React.renderComponent was renamed in 0.12 React.render(element, output); } else { React.renderComponent(element, output); } setStatus(renders > 0 ? 'Re-rendered (' + renders + 'x)' : 'Hydrated'); renders += 1; hydrate.innerHTML = 'Re-render'; } function handleError(error) { console.log(error); failed = true; setStatus('Javascript Error'); output.innerHTML = error; } function loadScript(src) { return new Promise(function (resolve, reject) { var script = document.createElement('script'); script.async = true; script.src = src; script.onload = resolve; script.onerror = function (error) { reject(new Error('Unable to load ' + src)); }; document.body.appendChild(script); }); } function injectFixture(src) { Fixture = new Function(src + '\nreturn Fixture;')(); if (typeof Fixture === 'undefined') { setStatus('Failed'); output.innerHTML = 'Please name your root component "Fixture"'; } else { prerender().then(function () { if (getBooleanQueryParam('hydrate')) { render(); } }); } } function reloadFixture(code) { renders = 0; unmountComponent(output); injectFixture(code); } window.onerror = handleError; reload.onclick = function () { window.location.reload(); }; hydrate.onclick = render; loadScript(getQueryParam('reactPath')) .then(function () { if (needsReactDOM) { return Promise.all([ loadScript(getQueryParam('reactDOMPath')), loadScript(getQueryParam('reactDOMServerPath')), ]); } }) .then(function () { if (failed) { return; } window.addEventListener('message', function (event) { var data = JSON.parse(event.data); switch (data.type) { case 'code': reloadFixture(data.payload); break; default: throw new Error( 'Renderer Error: Unrecognized message "' + data.type + '"' ); } }); window.parent.postMessage(JSON.stringify({type: 'ready'}), '*'); }) .catch(handleError); })(); ================================================ FILE: fixtures/dom/src/__tests__/nested-act-test.js ================================================ /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @emails react-core */ let React; let DOMAct; let TestRenderer; let TestAct; global.__DEV__ = process.env.NODE_ENV !== 'production'; describe('unmocked scheduler', () => { beforeEach(() => { jest.resetModules(); React = require('react'); DOMAct = React.act; TestRenderer = require('react-test-renderer'); TestAct = TestRenderer.act; }); it('flushes work only outside the outermost act() corresponding to its own renderer', () => { let log = []; function Effecty() { React.useEffect(() => { log.push('called'); }, []); return null; } // in legacy mode, this tests whether an act only flushes its own effects TestAct(() => { DOMAct(() => { TestRenderer.create(); }); expect(log).toEqual([]); }); expect(log).toEqual(['called']); log = []; // for doublechecking, we flip it inside out, and assert on the outermost DOMAct(() => { TestAct(() => { TestRenderer.create(); }); expect(log).toEqual([]); }); expect(log).toEqual(['called']); }); }); describe('mocked scheduler', () => { beforeEach(() => { jest.resetModules(); jest.mock('scheduler', () => require.requireActual('scheduler/unstable_mock') ); React = require('react'); DOMAct = React.act; TestRenderer = require('react-test-renderer'); TestAct = TestRenderer.act; }); afterEach(() => { jest.unmock('scheduler'); }); it('flushes work only outside the outermost act()', () => { let log = []; function Effecty() { React.useEffect(() => { log.push('called'); }, []); return null; } // with a mocked scheduler, this tests whether it flushes all work only on the outermost act TestAct(() => { DOMAct(() => { TestRenderer.create(); }); expect(log).toEqual([]); }); expect(log).toEqual(['called']); log = []; // for doublechecking, we flip it inside out, and assert on the outermost DOMAct(() => { TestAct(() => { TestRenderer.create(); }); expect(log).toEqual([]); }); expect(log).toEqual(['called']); }); }); ================================================ FILE: fixtures/dom/src/components/App.js ================================================ import Header from './Header'; import Fixtures from './fixtures'; import '../style.css'; const React = window.React; class App extends React.Component { render() { return (
); } } export default App; ================================================ FILE: fixtures/dom/src/components/Fixture.js ================================================ import PropTypes from 'prop-types'; const React = window.React; const propTypes = { children: PropTypes.node.isRequired, }; class Fixture extends React.Component { render() { const {children} = this.props; return
{children}
; } } Fixture.propTypes = propTypes; export default Fixture; Fixture.Controls = function FixtureControls({children}) { return
{children}
; }; ================================================ FILE: fixtures/dom/src/components/FixtureSet.js ================================================ import PropTypes from 'prop-types'; const React = window.React; const propTypes = { title: PropTypes.node.isRequired, description: PropTypes.node, }; class FixtureSet extends React.Component { render() { const {title, description, children} = this.props; return (

{title}

{description &&

{description}

} {children}
); } } FixtureSet.propTypes = propTypes; export default FixtureSet; ================================================ FILE: fixtures/dom/src/components/Header.js ================================================ import {parse, stringify} from 'query-string'; import VersionPicker from './VersionPicker'; const React = window.React; class Header extends React.Component { constructor(props, context) { super(props, context); const query = parse(window.location.search); const version = query.version || 'local'; const production = query.production || false; const versions = [version]; this.state = {version, versions, production}; } handleVersionChange(version) { const query = parse(window.location.search); query.version = version; if (query.version === 'local') { delete query.version; } window.location.search = stringify(query); } handleProductionChange(event) { const query = parse(window.location.search); query.production = event.target.checked; if (!query.production) { delete query.production; } window.location.search = stringify(query); } handleFixtureChange(event) { window.location.pathname = event.target.value; } render() { return (
React DOM Test Fixtures (v {React.version})
); } } export default Header; ================================================ FILE: fixtures/dom/src/components/Iframe.js ================================================ const React = window.React; const ReactDOM = window.ReactDOM; class IframePortal extends React.Component { iframeRef = null; handleRef = ref => { if (ref !== this.iframeRef) { this.iframeRef = ref; if (ref) { if (ref.contentDocument && this.props.head) { ref.contentDocument.head.innerHTML = this.props.head; } // Re-render must take place in the next tick (Firefox) setTimeout(() => { this.forceUpdate(); }); } } }; render() { const ref = this.iframeRef; let portal = null; if (ref && ref.contentDocument) { portal = ReactDOM.createPortal( this.props.children, ref.contentDocument.body ); } return (
); } } export default class OnSelectEventTestCase extends React.Component { render() { return (
  • Highlight some of the text in the input below
  • Move the cursor around using the arrow keys
  • The displayed count should increase as you highlight or move the cursor
    ); } } ================================================ FILE: fixtures/dom/src/components/fixtures/selection-events/ReorderedInputsTestCase.js ================================================ import TestCase from '../../TestCase'; import Iframe from '../../Iframe'; const React = window.React; export default class ReorderedInputsTestCase extends React.Component { state = {count: 0}; componentDidMount() { this.interval = setInterval(() => { this.setState({count: this.state.count + 1}); }, 2000); } componentWillUnmount() { clearInterval(this.interval); } renderInputs() { const inputs = [ , , ]; if (this.state.count % 2 === 0) { inputs.reverse(); } return inputs; } render() { return (
  • The two inputs below swap positions every two seconds
  • Select the text in either of them
  • Wait for the swap to occur
  • The selection you made should be maintained
    ); } } ================================================ FILE: fixtures/dom/src/components/fixtures/selection-events/index.js ================================================ import FixtureSet from '../../FixtureSet'; import ReorderedInputsTestCase from './ReorderedInputsTestCase'; import OnSelectEventTestCase from './OnSelectEventTestCase'; const React = window.React; export default function SelectionEvents() { return ( ); } ================================================ FILE: fixtures/dom/src/components/fixtures/selects/index.js ================================================ import FixtureSet from '../../FixtureSet'; import TestCase from '../../TestCase'; const React = window.React; const ReactDOM = window.ReactDOM; class SelectFixture extends React.Component { state = {value: ''}; _nestedDOMNode = null; _singleFormDOMNode = null; _multipleFormDOMNode = null; onChange = event => { this.setState({value: event.target.value}); }; resetSingleOptionForm = event => { event.preventDefault(); this._singleFormDOMNode.reset(); }; resetMultipleOptionForm = event => { event.preventDefault(); this._multipleFormDOMNode.reset(); }; componentDidMount() { this._renderNestedSelect(); } componentDidUpdate() { this._renderNestedSelect(); } _renderNestedSelect() { ReactDOM.render( , this._nestedDOMNode ); } render() { return (
    Controlled Value: {this.state.value}
    Uncontrolled
    Controlled in nested subtree
    (this._nestedDOMNode = node)} /> This should synchronize in both direction with the "Controlled".
  • Open the select
  • Select "1"
  • Attempt to reselect "Please select an item"
  • The initial picked option should be "Please select an item", however it should not be a selectable option.
    The initial picked option value should "0": the first non-disabled option.
  • Open the select
  • Select "baz" or "foo"
  • Click the "Reset" button
  • The select should be reset to the initial value, "bar"
    (this._singleFormDOMNode = n)}>
  • Select any combination of options
  • Click the "Reset" button
  • The select should be reset to the initial values "foo" and "baz"
    (this._multipleFormDOMNode = n)}>
    First selected option should be visible
  • Select any option
  • Option should be set
    No options should be selected.

    Notes: This happens if size is assigned after options are selected. The select element picks the first item by default, then it is expanded to show more options when{' '} size is assigned, preserving the default selection.

    This was introduced in React 16.0.0 when options were added before select attribute assignment.

    ); } } export default SelectFixture; ================================================ FILE: fixtures/dom/src/components/fixtures/suspense/index.js ================================================ import Fixture from '../../Fixture'; import FixtureSet from '../../FixtureSet'; import TestCase from '../../TestCase'; const React = window.React; const ReactDOM = window.ReactDOM; const Suspense = React.Suspense; let cache = new Set(); function AsyncStep({text, ms}) { if (!cache.has(text)) { throw new Promise(resolve => setTimeout(() => { cache.add(text); resolve(); }, ms) ); } return null; } let suspendyTreeIdCounter = 0; class SuspendyTreeChild extends React.Component { id = suspendyTreeIdCounter++; state = { step: 1, isHidden: false, }; increment = () => this.setState(s => ({step: s.step + 1})); componentDidMount() { document.addEventListener('keydown', this.onKeydown); } componentWillUnmount() { document.removeEventListener('keydown', this.onKeydown); } onKeydown = event => { if (event.metaKey && event.key === 'Enter') { this.increment(); } }; render() { return ( <> (display: none)
    }>
    {this.props.children}
    ); } } class SuspendyTree extends React.Component { parentContainer = React.createRef(null); container = React.createRef(null); componentDidMount() { this.setState({}); document.addEventListener('keydown', this.onKeydown); } componentWillUnmount() { document.removeEventListener('keydown', this.onKeydown); } onKeydown = event => { if (event.metaKey && event.key === '/') { this.removeAndRestore(); } }; removeAndRestore = () => { const parentContainer = this.parentContainer.current; const container = this.container.current; parentContainer.removeChild(container); parentContainer.textContent = '(removed from DOM)'; setTimeout(() => { parentContainer.textContent = ''; parentContainer.appendChild(container); }, 500); }; render() { return ( <>
    {this.container.current !== null ? ReactDOM.createPortal( <> {this.props.children} , this.container.current ) : null}
    ); } } class TextInputFixtures extends React.Component { render() { return (

    Clicking "Hide" will hide the fixture context using{' '} display: none for 0.5 seconds, then restore. This is the built-in behavior for timed-out children. Each fixture tests whether the state of the DOM is preserved. Clicking "Remove" will remove the fixture content from the DOM for 0.5 seconds, then restore. This is{' '} not how timed-out children are hidden, but is included for comparison purposes.

    As a shortcut, you can use Command + Enter (or Control + Enter on Windows, Linux) to "Hide" all the fixtures, or Command + / to "Remove" them.
  • Use your cursor to select the text below.
  • Click "Hide" or "Remove".
  • Text selection is preserved when hiding, but not when removing. Select this entire sentence (and only this sentence).
  • Use your cursor to select a range that includes both the text and the "Go" button.
  • Click "Hide" or "Remove".
  • Text selection is preserved when hiding, but not when removing. Select a range that includes both this sentence and the "Go" button.
  • Use your cursor to select a range that includes both the text and the "Go" button.
  • Instead of clicking "Go", which switches focus, press Command + Enter (or Control + Enter on Windows, Linux).
  • The ideal behavior is that the focus would not be lost, but currently it is (both when hiding and removing).
  • Type something ("Hello") into the text input.
  • Click "Hide" or "Remove".
  • Input is preserved when hiding, but not when removing.
  • Click "Hide" or "Remove".
  • The image should reappear without flickering. The text should not reflow. React is cool
  • The iframe shows a nested version of this fixtures app. Navigate to the "Text inputs" page.
  • Select one of the checkboxes.
  • Click "Hide" or "Remove".
  • When removing, the iframe is reloaded. When hiding, the iframe should still be on the "Text inputs" page. The checkbox should still be checked. (Unfortunately, scroll position is lost.)

    globals (dev)

    globals (prod)

    requirejs (dev)

    requirejs (prod)

    systemjs (dev)

    systemjs (prod)

    browserify (dev)

    browserify (prod)

    brunch (dev)

    brunch (prod)

    rjs (dev)

    rjs (prod)

    systemjs-builder (dev)

    systemjs-builder (prod)

    webpack (dev)

    webpack (prod)

    webpack-alias (dev)

    webpack-alias (prod)

    ================================================ FILE: fixtures/packaging/requirejs/dev.html ================================================
    ================================================ FILE: fixtures/packaging/requirejs/prod.html ================================================
    ================================================ FILE: fixtures/packaging/rjs/dev/.gitignore ================================================ output.js ================================================ FILE: fixtures/packaging/rjs/dev/config.js ================================================ module.exports = { baseUrl: '.', name: 'input', out: 'output.js', optimize: 'none', paths: { react: '../../../../build/oss-experimental/react/umd/react.development', 'react-dom': '../../../../build/oss-experimental/react-dom/umd/react-dom.development', schedule: '../../../../build/oss-experimental/scheduler/umd/schedule.development', }, }; ================================================ FILE: fixtures/packaging/rjs/dev/index.html ================================================
    ================================================ FILE: fixtures/packaging/rjs/dev/input.js ================================================ require(['react', 'react-dom'], function (React, ReactDOM) { ReactDOM.render( React.createElement('h1', null, 'Hello World!'), document.getElementById('container') ); }); ================================================ FILE: fixtures/packaging/rjs/dev/package.json ================================================ { "private": true, "name": "rjs-dev-fixture", "dependencies": { "requirejs": "^2.3.2" }, "scripts": { "build": "rm -f output.js && r.js -o config.js" } } ================================================ FILE: fixtures/packaging/rjs/prod/.gitignore ================================================ output.js ================================================ FILE: fixtures/packaging/rjs/prod/config.js ================================================ module.exports = { baseUrl: '.', name: 'input', out: 'output.js', optimize: 'none', paths: { react: '../../../../build/oss-experimental/react/umd/react.production.min', 'react-dom': '../../../../build/oss-experimental/react-dom/umd/react-dom.production.min', schedule: '../../../../build/oss-experimental/scheduler/umd/schedule.development', }, }; ================================================ FILE: fixtures/packaging/rjs/prod/index.html ================================================
    ================================================ FILE: fixtures/packaging/rjs/prod/input.js ================================================ require(['react', 'react-dom'], function (React, ReactDOM) { ReactDOM.render( React.createElement('h1', null, 'Hello World!'), document.getElementById('container') ); }); ================================================ FILE: fixtures/packaging/rjs/prod/package.json ================================================ { "private": true, "name": "rjs-prod-fixture", "dependencies": { "requirejs": "^2.3.2" }, "scripts": { "build": "rm -f output.js && r.js -o config.js" } } ================================================ FILE: fixtures/packaging/systemjs/dev.html ================================================
    ================================================ FILE: fixtures/packaging/systemjs/prod.html ================================================
    ================================================ FILE: fixtures/packaging/systemjs-builder/dev/.gitignore ================================================ output.js ================================================ FILE: fixtures/packaging/systemjs-builder/dev/build.js ================================================ var Builder = require('systemjs-builder'); var builder = new Builder('/', './config.js'); builder .buildStatic('./input.js', './output.js') .then(function () { console.log('Build complete'); }) .catch(function (err) { console.log('Build error'); console.log(err); }); ================================================ FILE: fixtures/packaging/systemjs-builder/dev/config.js ================================================ System.config({ paths: { react: '../../../../build/oss-experimental/react/umd/react.development.js', 'react-dom': '../../../../build/oss-experimental/react-dom/umd/react-dom.development.js', schedule: '../../../../build/oss-experimental/scheduler/umd/schedule.development', }, }); ================================================ FILE: fixtures/packaging/systemjs-builder/dev/index.html ================================================
    ================================================ FILE: fixtures/packaging/systemjs-builder/dev/input.js ================================================ import React from 'react'; import ReactDOM from 'react-dom'; ReactDOM.render( React.createElement('h1', null, 'Hello World!'), document.getElementById('container') ); ================================================ FILE: fixtures/packaging/systemjs-builder/dev/package.json ================================================ { "private": true, "name": "systemjs-dev-fixture", "dependencies": { "systemjs-builder": "^0.15.34" }, "scripts": { "build": "rm -f output.js && node build.js" } } ================================================ FILE: fixtures/packaging/systemjs-builder/prod/.gitignore ================================================ output.js ================================================ FILE: fixtures/packaging/systemjs-builder/prod/build.js ================================================ var Builder = require('systemjs-builder'); var builder = new Builder('/', './config.js'); builder .buildStatic('./input.js', './output.js') .then(function () { console.log('Build complete'); }) .catch(function (err) { console.log('Build error'); console.log(err); }); ================================================ FILE: fixtures/packaging/systemjs-builder/prod/config.js ================================================ System.config({ paths: { react: '../../../../build/oss-experimental/react/umd/react.production.min.js', 'react-dom': '../../../../build/oss-experimental/react-dom/umd/react-dom.production.min.js', schedule: '../../../../build/oss-experimental/scheduler/umd/schedule.development', }, }); ================================================ FILE: fixtures/packaging/systemjs-builder/prod/index.html ================================================
    ================================================ FILE: fixtures/packaging/systemjs-builder/prod/input.js ================================================ import React from 'react'; import ReactDOM from 'react-dom'; ReactDOM.render( React.createElement('h1', null, 'Hello World!'), document.getElementById('container') ); ================================================ FILE: fixtures/packaging/systemjs-builder/prod/package.json ================================================ { "private": true, "name": "systemjs-prod-fixture", "dependencies": { "systemjs-builder": "^0.15.34" }, "scripts": { "build": "rm -f output.js && node build.js" } } ================================================ FILE: fixtures/packaging/webpack/dev/.gitignore ================================================ output.js ================================================ FILE: fixtures/packaging/webpack/dev/config.js ================================================ var path = require('path'); module.exports = { entry: './input', output: { filename: 'output.js', }, resolve: { root: path.resolve('../../../../build/oss-experimental/'), }, }; ================================================ FILE: fixtures/packaging/webpack/dev/index.html ================================================
    ================================================ FILE: fixtures/packaging/webpack/dev/input.js ================================================ var React = require('react'); var ReactDOM = require('react-dom'); ReactDOM.render( React.createElement('h1', null, 'Hello World!'), document.getElementById('container') ); ================================================ FILE: fixtures/packaging/webpack/dev/package.json ================================================ { "private": true, "name": "webpack-dev-fixture", "dependencies": { "webpack": "^1.14.0" }, "scripts": { "build": "rm -f output.js && webpack --config config.js" } } ================================================ FILE: fixtures/packaging/webpack/prod/.gitignore ================================================ output.js ================================================ FILE: fixtures/packaging/webpack/prod/config.js ================================================ var path = require('path'); var webpack = require('webpack'); module.exports = { entry: './input', output: { filename: 'output.js', }, resolve: { root: path.resolve('../../../../build/oss-experimental/'), }, plugins: [ new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify('production'), }, }), ], }; ================================================ FILE: fixtures/packaging/webpack/prod/index.html ================================================
    ================================================ FILE: fixtures/packaging/webpack/prod/input.js ================================================ var React = require('react'); var ReactDOM = require('react-dom'); ReactDOM.render( React.createElement('h1', null, 'Hello World!'), document.getElementById('container') ); ================================================ FILE: fixtures/packaging/webpack/prod/package.json ================================================ { "private": true, "name": "webpack-prod-fixture", "dependencies": { "webpack": "^1.14.0" }, "scripts": { "build": "rm -f output.js && webpack --config config.js" } } ================================================ FILE: fixtures/packaging/webpack-alias/dev/.gitignore ================================================ output.js ================================================ FILE: fixtures/packaging/webpack-alias/dev/config.js ================================================ var path = require('path'); module.exports = { entry: './input', output: { filename: 'output.js', }, resolve: { root: path.resolve('../../../../build/oss-experimental'), alias: { react: 'react/umd/react.development', 'react-dom': 'react-dom/umd/react-dom.development', }, }, }; ================================================ FILE: fixtures/packaging/webpack-alias/dev/index.html ================================================
    ================================================ FILE: fixtures/packaging/webpack-alias/dev/input.js ================================================ var React = require('react'); var ReactDOM = require('react-dom'); ReactDOM.render( React.createElement('h1', null, 'Hello World!'), document.getElementById('container') ); ================================================ FILE: fixtures/packaging/webpack-alias/dev/package.json ================================================ { "private": true, "name": "webpack-alias-dev-fixture", "dependencies": { "webpack": "^1.14.0" }, "scripts": { "build": "rm -f output.js && webpack --config config.js" } } ================================================ FILE: fixtures/packaging/webpack-alias/prod/.gitignore ================================================ output.js ================================================ FILE: fixtures/packaging/webpack-alias/prod/config.js ================================================ var path = require('path'); module.exports = { entry: './input', output: { filename: 'output.js', }, resolve: { root: path.resolve('../../../../build/oss-experimental'), alias: { react: 'react/umd/react.production.min', 'react-dom': 'react-dom/umd/react-dom.production.min', }, }, }; ================================================ FILE: fixtures/packaging/webpack-alias/prod/index.html ================================================
    ================================================ FILE: fixtures/packaging/webpack-alias/prod/input.js ================================================ var React = require('react'); var ReactDOM = require('react-dom'); ReactDOM.render( React.createElement('h1', null, 'Hello World!'), document.getElementById('container') ); ================================================ FILE: fixtures/packaging/webpack-alias/prod/package.json ================================================ { "private": true, "name": "webpack-alias-prod-fixture", "dependencies": { "webpack": "^1.14.0" }, "scripts": { "build": "rm -f output.js && webpack --config config.js" } } ================================================ FILE: fixtures/scheduler/index.html ================================================ Scheduler Test Page

    Scheduler Fixture

    This fixture is for manual testing purposes, and the patterns used in implementing it should not be used as a model. This is mainly for anyone working on making changes to the `schedule` module.

    Tests:

    1. Calls the callback within the frame when not blocked:

      Expected:
      -------------------------------------------------
      If you see the same above and below it's correct.
      -------------------------------------------------
      Actual:
    2. Accepts multiple callbacks and calls within frame when not blocked

      Expected:
      -------------------------------------------------
      If you see the same above and below it's correct.
      -------------------------------------------------
      Actual:
    3. Schedules callbacks in correct order when they use scheduleCallback to schedule themselves

      Expected:
      -------------------------------------------------
      If you see the same above and below it's correct.
      -------------------------------------------------
      Actual:
    4. Calls timed out callbacks and then any more pending callbacks, defers others if time runs out

      Expected:
      -------------------------------------------------
      If you see the same above and below it's correct.
      -------------------------------------------------
      Actual:
    5. When some callbacks throw errors, still calls them all within the same frame

      IMPORTANT: Open the console when you run this! Inspect the logs there!

    6. When some callbacks throw errors and some also time out, still calls them all within the same frame

      IMPORTANT: Open the console when you run this! Inspect the logs there!

    7. Continues calling callbacks even when user switches away from this tab

      Click the button above, observe the counter, then switch to another tab and switch back:
      If the counter advanced while you were away from this tab, it's correct.
    8. Test Eight Removed

      Test 8 was removed because it was testing a feature that was removed from the scheduler.

    9. Can force a specific framerate

      IMPORTANT: This test may be flaky if other tests have been run in this js instance. To get a clean test refresh the page before running test 9

      Expected:
      -------------------------------------------------
      If you see the same above and below it's correct.
      -------------------------------------------------
      Actual:
    10. Runs scheduled JS work for 99% of the frame time when nothing else is using the thread.

      NOTE: Try this test both when nothing else is running and when something is using the compositor thread in another visible tab with video or WebGL content (Shift+Click).

      Expected:
      -------------------------------------------------
      If you see the same above and below it's correct.
      -------------------------------------------------
      Actual:
    11. Runs scheduled JS work more than 95% of the frame time when inserting DOM nodes.

      NOTE: Try this test both when nothing else is running and when something is using the compositor thread in another visible tab with video or WebGL content (Shift+Click).

      Expected:
      -------------------------------------------------
      If you see the same above and below it's correct.
      -------------------------------------------------
      Actual:
    ================================================ FILE: fixtures/ssr/README.md ================================================ # SSR Fixtures A set of test cases for quickly identifying issues with server-side rendering. ## Setup To reference a local build of React, first run `npm run build` at the root of the React project. Then: ``` cd fixtures/ssr yarn yarn start ``` The `start` command runs a webpack dev server and a server-side rendering server in development mode with hot reloading. **Note: whenever you make changes to React and rebuild it, you need to re-run `yarn` in this folder:** ``` yarn ``` If you want to try the production mode instead run: ``` yarn start:prod ``` This will pre-build all static resources and then start a server-side rendering HTTP server that hosts the React app and service the static resources (without hot reloading). ================================================ FILE: fixtures/ssr/package.json ================================================ { "name": "react-fixtures-ssr", "version": "0.1.0", "private": true, "devDependencies": { "concurrently": "3.1.0", "http-proxy-middleware": "0.17.3", "react-scripts": "0.9.5" }, "dependencies": { "express": "^4.14.0", "ignore-styles": "^5.0.1", "import-export": "^1.0.1", "node-fetch": "^1.6.3", "react": "^19.0.0", "react-dom": "^19.0.0" }, "scripts": { "predev": "cp -r ../../build/oss-experimental/* ./node_modules/", "prestart": "cp -r ../../build/oss-experimental/* ./node_modules/", "prebuild": "cp -r ../../build/oss-experimental/* ./node_modules/", "dev": "concurrently \"npm run dev:server\" \"npm run dev:client\"", "dev:client": "BROWSER=none PORT=3001 react-scripts start", "dev:server": "NODE_ENV=development node server", "start": "react-scripts build && NODE_ENV=production node server", "build": "react-scripts build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" } } ================================================ FILE: fixtures/ssr/public/index.html ================================================ ================================================ FILE: fixtures/ssr/server/index.js ================================================ require('ignore-styles'); const babelRegister = require('babel-register'); const proxy = require('http-proxy-middleware'); babelRegister({ ignore: /\/(build|node_modules)\//, presets: ['react-app'], }); const express = require('express'); const path = require('path'); const app = express(); // Application if (process.env.NODE_ENV === 'development') { app.get('/', function (req, res) { // In development mode we clear the module cache between each request to // get automatic hot reloading. for (var key in require.cache) { delete require.cache[key]; } const render = require('./render').default; render(req.url, res); }); } else { const render = require('./render').default; app.get('/', function (req, res) { render(req.url, res); }); } // Static resources app.use(express.static(path.resolve(__dirname, '..', 'build'))); // Proxy everything else to create-react-app's webpack development server if (process.env.NODE_ENV === 'development') { app.use( '/', proxy({ ws: true, target: 'http://localhost:3001', }) ); } app.listen(3000, () => { console.log('Listening on port 3000...'); }); app.on('error', function (error) { if (error.syscall !== 'listen') { throw error; } var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port; switch (error.code) { case 'EACCES': console.error(bind + ' requires elevated privileges'); process.exit(1); break; case 'EADDRINUSE': console.error(bind + ' is already in use'); process.exit(1); break; default: throw error; } }); ================================================ FILE: fixtures/ssr/server/render.js ================================================ import React from 'react'; import {renderToPipeableStream} from 'react-dom/server'; import {Writable} from 'stream'; import App from '../src/components/App'; let assets; if (process.env.NODE_ENV === 'development') { // Use the bundle from create-react-app's server in development mode. assets = { 'main.js': '/static/js/bundle.js', 'main.css': '', }; } else { assets = require('../build/asset-manifest.json'); } class ThrottledWritable extends Writable { constructor(destination) { super(); this.destination = destination; this.delay = 10; } _write(chunk, encoding, callback) { let o = 0; const write = () => { this.destination.write(chunk.slice(o, o + 100), encoding, x => { o += 100; if (o < chunk.length) { setTimeout(write, this.delay); } else { callback(x); } }); }; setTimeout(write, this.delay); } _final(callback) { setTimeout(() => { this.destination.end(callback); }, this.delay); } } export default function render(url, res) { res.socket.on('error', error => { // Log fatal errors console.error('Fatal', error); }); let didError = false; const {pipe, abort} = renderToPipeableStream(, { bootstrapScripts: [assets['main.js']], progressiveChunkSize: 1024, onShellReady() { // If something errored before we started streaming, we set the error code appropriately. res.statusCode = didError ? 500 : 200; res.setHeader('Content-type', 'text/html'); // To test the actual chunks taking time to load over the network, we throttle // the stream a bit. const throttledResponse = new ThrottledWritable(res); pipe(throttledResponse); }, onShellError(x) { // Something errored before we could complete the shell so we emit an alternative shell. res.statusCode = 500; res.send('

    Error

    '); }, onError(x) { didError = true; console.error(x); }, }); // Abandon and switch to client rendering after 5 seconds. // Try lowering this to see the client recover. setTimeout(abort, 5000); } ================================================ FILE: fixtures/ssr/src/components/App.js ================================================ import React, {useContext, useState, Suspense} from 'react'; import Chrome from './Chrome'; import Page from './Page'; import Page2 from './Page2'; import Theme from './Theme'; function LoadingIndicator() { let theme = useContext(Theme); return
    Loading...
    ; } function Content() { let [CurrentPage, switchPage] = useState(() => Page); return ( ); } export default function App({assets}) { return ( ); } ================================================ FILE: fixtures/ssr/src/components/Chrome.css ================================================ body { margin: 10px; padding: 0; font-family: sans-serif; } body.light { background-color: #FFFFFF; color: #333333; } body.dark { background-color: #000000; color: #CCCCCC; } .light-loading { margin: 10px 0; padding: 10px; background-color: #CCCCCC; color: #666666; } .dark-loading { margin: 10px 0; padding: 10px; background-color: #333333; color: #999999; } ================================================ FILE: fixtures/ssr/src/components/Chrome.js ================================================ import React, {Component, Suspense, startTransition} from 'react'; import Theme, {ThemeToggleButton} from './Theme'; import './Chrome.css'; import LargeContent from './LargeContent'; export default class Chrome extends Component { state = {theme: 'light'}; render() { const assets = this.props.assets; return ( {this.props.title}