Skip to content

[compiler] Phase 2+7: Wrap pipeline passes in tryRecord for fault tolerance#591

Closed
everettbu wants to merge 2 commits into
mainfrom
pr35874
Closed

[compiler] Phase 2+7: Wrap pipeline passes in tryRecord for fault tolerance#591
everettbu wants to merge 2 commits into
mainfrom
pr35874

Conversation

@everettbu

@everettbu everettbu commented Feb 23, 2026

Copy link
Copy Markdown

Mirror of facebook/react#35874
Original author: josephsavona


  • Change runWithEnvironment/run/compileFn to return Result<CodegenFunction, CompilerError>
  • Wrap all pipeline passes in env.tryRecord() to catch and record CompilerErrors
  • Record inference pass errors via env.recordErrors() instead of throwing
  • Handle codegen Result explicitly, returning Err on failure
  • Add final error check: return Err(env.aggregateErrors()) if any errors accumulated
  • Update tryCompileFunction and retryCompileFunction in Program.ts to handle Result
  • Keep lint-only passes using env.logErrors() (non-blocking)
  • Update 52 test fixture expectations that now report additional errors

This is the core integration that enables fault tolerance: errors are caught,
recorded, and the pipeline continues to discover more errors.


Stack created with Sapling. Best reviewed with ReviewStack.

  • #35888
  • #35884
  • #35883
  • #35882
  • #35881
  • #35880
  • #35879
  • #35878
  • #35877
  • #35876
  • #35875
  • -> #35874

@everettbu everettbu added CLA Signed React Core Team Opened by a member of the React Core Team labels Feb 23, 2026
@greptile-apps

greptile-apps Bot commented Feb 23, 2026

Copy link
Copy Markdown

Greptile Summary

This PR implements Phases 2 and 7 of the fault tolerance plan for the React Compiler. It changes the compilation pipeline to accumulate errors via env.tryRecord() and env.recordErrors() instead of throwing on the first error, enabling the compiler to continue and discover multiple errors in a single pass. The return types of run/runWithEnvironment/compileFn are changed from CodegenFunction to Result<CodegenFunction, CompilerError>, and tryCompileFunction in Program.ts is updated to handle the Result.

  • Environment.ts adds the error accumulation infrastructure (#errors field, recordError, recordErrors, tryRecord, hasErrors, aggregateErrors), with invariant errors correctly re-thrown immediately
  • Pipeline.ts wraps validation and inference passes in env.tryRecord(), changes inference error handling from throw to env.recordErrors(), handles codegen Result explicitly, and adds a final env.hasErrors() check before returning
  • validateNoImpureFunctionsInRender is removed from the pipeline since inferMutationAliasingEffects already validates the same condition (at line 2332 of InferMutationAliasingEffects.ts)
  • 52 test fixtures updated to reflect additional errors now surfaced — most are genuinely useful additional diagnostics (e.g., "Cannot modify local variables after render" alongside "Cannot reassign variable")
  • ESLint plugin tests updated to expect the additional errors, and a TODO comment about surfacing multiple diagnostics is resolved
  • Lint-only passes (validateNoDerivedComputationsInEffects_exp, validateNoSetStateInEffects, validateNoJSXInTryStatement, validateStaticComponents) correctly continue using env.logErrors() instead of tryRecord

Confidence Score: 3/5

  • The core fault tolerance mechanism is well-designed, but there are known error regression cases (discussed in prior threads) where user-facing errors degrade into internal invariants — these should be addressed before or shortly after merging.
  • Score of 3 reflects that the fundamental architecture is sound (invariants re-thrown, lint-only passes preserved, Result type propagated correctly), but several known issues were identified in prior threads: the reactiveFunction! definite assignment assertion could mask failures, the error.invalid-hook-for fixture now shows an opaque invariant instead of actionable hook errors, and there are duplicate error reporting patterns. The additional errors surfaced in 52 fixtures are mostly beneficial, but a few represent regressions in error quality. This is documented as a transitional step in the fault tolerance plan.
  • compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts (core pipeline changes, definite assignment assertion pattern), compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-for.expect.md (error regression to internal invariant)

Important Files Changed

Filename Overview
compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts Core change: wraps pipeline passes in env.tryRecord() for fault tolerance. Return type changed from CodegenFunction to Result<CodegenFunction, CompilerError>. Removes validateNoImpureFunctionsInRender call (now handled by inferMutationAliasingEffects). Uses definite assignment assertion (!) on reactiveFunction — discussed in prior threads.
compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts Updated tryCompileFunction to handle Result from compileFn — unwraps Ok as compiled fn, maps Err to error kind. Clean and straightforward adaptation.
compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts Adds error accumulation infrastructure: #errors field, recordError/recordErrors/tryRecord/hasErrors/aggregateErrors methods. Invariant errors are correctly re-thrown immediately. Clean implementation.
compiler/fault-tolerance-overview.md Design document updated: marks Phase 1, 2, and 7 items as complete. Adds "Key Learnings" section documenting findings from this implementation.
compiler/packages/babel-plugin-react-compiler/src/tests/fixtures/compiler/rules-of-hooks/error.invalid-hook-for.expect.md Error regression: previously reported 2 actionable "Hooks must always be called in a consistent order" errors. Now reports 1 opaque Invariant: Unexpected empty block with goto terminal — discussed in prior thread.
compiler/packages/babel-plugin-react-compiler/src/tests/fixtures/compiler/use-no-forget-multiple-with-eslint-suppression.expect.md New unused import { c as _c } from "react/compiler-runtime" added to output. With fault tolerance, more functions now complete compilation, triggering the import even though no memoization occurs.
compiler/packages/eslint-plugin-react-compiler/tests/PluginTest-test.ts Updated ESLint plugin tests to expect additional errors now surfaced by fault tolerance. Removes TODO comment that's now resolved. Clean updates.

Last reviewed commit: 5c6649f

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

34 files reviewed, 4 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +493 to +496
let reactiveFunction!: ReactiveFunction;
env.tryRecord(() => {
reactiveFunction = buildReactiveFunction(hir);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unsafe definite assignment assertion

let reactiveFunction!: ReactiveFunction uses TypeScript's definite assignment assertion (!), which tells the compiler the variable will be assigned. However, if buildReactiveFunction throws inside tryRecord, the error is caught and reactiveFunction remains uninitialized (undefined at runtime). Subsequent code that accesses reactiveFunction (e.g., assertWellFormedBreakTargets(reactiveFunction) on line 503) will then operate on undefined, likely causing a confusing runtime error or invariant violation.

The same pattern applies to fbtOperands (line 374) and uniqueIdentifiers (line 604), though those have safe empty-set defaults. For reactiveFunction, there's no safe default. Consider checking env.hasErrors() and returning Err(env.aggregateErrors()) immediately after this tryRecord block if buildReactiveFunction fails, since subsequent passes all depend on a valid ReactiveFunction.

Prompt To Fix With AI
This is a comment left during a code review.
Path: compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts
Line: 493-496

Comment:
**Unsafe definite assignment assertion**

`let reactiveFunction!: ReactiveFunction` uses TypeScript's definite assignment assertion (`!`), which tells the compiler the variable will be assigned. However, if `buildReactiveFunction` throws inside `tryRecord`, the error is caught and `reactiveFunction` remains uninitialized (`undefined` at runtime). Subsequent code that accesses `reactiveFunction` (e.g., `assertWellFormedBreakTargets(reactiveFunction)` on line 503) will then operate on `undefined`, likely causing a confusing runtime error or invariant violation.

The same pattern applies to `fbtOperands` (line 374) and `uniqueIdentifiers` (line 604), though those have safe empty-set defaults. For `reactiveFunction`, there's no safe default. Consider checking `env.hasErrors()` and returning `Err(env.aggregateErrors())` immediately after this `tryRecord` block if `buildReactiveFunction` fails, since subsequent passes all depend on a valid `ReactiveFunction`.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +737 to +743
if (this.logger != null) {
this.logger.logEvent(this.filename, {
kind: 'CompileError',
detail: error,
fnLoc: null,
});
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Duplicate error logging with fnLoc: null

recordError logs each error with fnLoc: null. When the accumulated errors later flow back to Program.ts as an Err result, logError in Program.ts logs the same errors again — this time with the correct fnLoc. This is visible in the dynamic-gating-bailout-nopanic test fixture, which now shows a duplicate log entry.

Consider either removing the logging here (since Program.ts will log the errors) or passing fnLoc context into the Environment so it can log with the correct location. Since the design document says this is a transitional step and individual passes will later record errors directly, removing the logging here might be the simplest fix.

Prompt To Fix With AI
This is a comment left during a code review.
Path: compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts
Line: 737-743

Comment:
**Duplicate error logging with `fnLoc: null`**

`recordError` logs each error with `fnLoc: null`. When the accumulated errors later flow back to Program.ts as an `Err` result, `logError` in Program.ts logs the same errors again — this time with the correct `fnLoc`. This is visible in the `dynamic-gating-bailout-nopanic` test fixture, which now shows a duplicate log entry.

Consider either removing the logging here (since Program.ts will log the errors) or passing `fnLoc` context into the Environment so it can log with the correct location. Since the design document says this is a transitional step and individual passes will later record errors directly, removing the logging here might be the simplest fix.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +19 to 37
Found 1 error:

Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
Invariant: Unexpected empty block with `goto` terminal

error.invalid-hook-for.ts:4:9
2 | let i = 0;
3 | for (let x = 0; useHook(x) < 10; useHook(i), x++) {
> 4 | i += useHook(x);
| ^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
5 | }
6 | return i;
7 | }
Block bb5 is empty.

Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)

error.invalid-hook-for.ts:3:35
error.invalid-hook-for.ts:3:2
1 | function Component(props) {
2 | let i = 0;
> 3 | for (let x = 0; useHook(x) < 10; useHook(i), x++) {
| ^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
4 | i += useHook(x);
5 | }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 4 | i += useHook(x);
| ^^^^^^^^^^^^^^^^^^^^
> 5 | }
| ^^^^ Unexpected empty block with `goto` terminal
6 | return i;
7 | }
8 |
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Error regression: user-facing errors replaced by internal invariant

This fixture previously reported 2 actionable validation errors ("Hooks must always be called in a consistent order"), which clearly told the developer what was wrong. Now it reports a single Invariant: Unexpected empty block with 'goto' terminal, which is an internal compiler error from BuildReactiveFunction (line 925 of BuildReactiveFunction.ts).

This happens because validateHooksUsage now records its error via tryRecord instead of throwing, allowing the pipeline to continue with HIR that has hooks called inside a for-loop. Later passes were never designed to handle this invalid HIR, so buildReactiveFunction hits an assertion.

The user experience is worse: instead of a clear "don't call hooks conditionally" message, they see an opaque internal error. Consider either:

  1. Adding an early return (if (env.hasErrors()) return Err(...)) after critical validation passes like validateHooksUsage that detect fundamentally invalid code patterns, or
  2. Not wrapping validateHooksUsage in tryRecord since hook rule violations make the HIR structurally invalid for downstream passes.
Prompt To Fix With AI
This is a comment left during a code review.
Path: compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-for.expect.md
Line: 19-37

Comment:
**Error regression: user-facing errors replaced by internal invariant**

This fixture previously reported 2 actionable validation errors ("Hooks must always be called in a consistent order"), which clearly told the developer what was wrong. Now it reports a single `Invariant: Unexpected empty block with 'goto' terminal`, which is an internal compiler error from `BuildReactiveFunction` (line 925 of `BuildReactiveFunction.ts`).

This happens because `validateHooksUsage` now records its error via `tryRecord` instead of throwing, allowing the pipeline to continue with HIR that has hooks called inside a for-loop. Later passes were never designed to handle this invalid HIR, so `buildReactiveFunction` hits an assertion.

The user experience is worse: instead of a clear "don't call hooks conditionally" message, they see an opaque internal error. Consider either:
1. Adding an early return (`if (env.hasErrors()) return Err(...)`) after critical validation passes like `validateHooksUsage` that detect fundamentally invalid code patterns, or
2. Not wrapping `validateHooksUsage` in `tryRecord` since hook rule violations make the HIR structurally invalid for downstream passes.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 21 to 33
```
Found 1 error:

Todo: [hoisting] EnterSSA: Expected identifier to be defined before being used
Invariant: [InferMutationAliasingEffects] Expected value kind to be initialized

Identifier x$1 is undefined.
<unknown> x$1.

error.dont-hoist-inline-reference.ts:3:2
error.dont-hoist-inline-reference.ts:3:21
1 | import {identity} from 'shared-runtime';
2 | function useInvalid() {
> 3 | const x = identity(x);
| ^^^^^^^^^^^^^^^^^^^^^^ [hoisting] EnterSSA: Expected identifier to be defined before being used
| ^ this is uninitialized
4 | return x;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Error regression: Todo replaced by internal invariant

Similar to the error.invalid-hook-for regression, this fixture previously reported a user-friendly Todo: [hoisting] EnterSSA: Expected identifier to be defined before being used, but now reports Invariant: [InferMutationAliasingEffects] Expected value kind to be initialized.

The enterSSA pass now records its Todo error via tryRecord but continues, leaving the HIR in a state where identifiers are not properly defined. When inferMutationAliasingEffects runs later, it encounters the uninitialized value and triggers an invariant violation.

This is a pattern where certain passes (like enterSSA) produce structural changes to the HIR that downstream passes depend on. When these passes fail, continuing the pipeline leads to invariant failures that mask the original error.

Prompt To Fix With AI
This is a comment left during a code review.
Path: compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.dont-hoist-inline-reference.expect.md
Line: 21-33

Comment:
**Error regression: Todo replaced by internal invariant**

Similar to the `error.invalid-hook-for` regression, this fixture previously reported a user-friendly `Todo: [hoisting] EnterSSA: Expected identifier to be defined before being used`, but now reports `Invariant: [InferMutationAliasingEffects] Expected value kind to be initialized`.

The `enterSSA` pass now records its Todo error via `tryRecord` but continues, leaving the HIR in a state where identifiers are not properly defined. When `inferMutationAliasingEffects` runs later, it encounters the uninitialized value and triggers an invariant violation.

This is a pattern where certain passes (like `enterSSA`) produce structural changes to the HIR that downstream passes depend on. When these passes fail, continuing the pipeline leads to invariant failures that mask the original error.

How can I resolve this? If you propose a fix, please make it concise.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

34 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile


```
Found 3 errors:
Found 6 errors:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Duplicate errors reported to users

This fixture now reports 6 errors when there are only 3 impure function calls. The same "Cannot call impure function" error is reported twice for each call site — once from inferMutationAliasingEffects (which now records errors via env.recordErrors() instead of throwing) and once from validateNoImpureFunctionsInRender (which runs later in the pipeline).

Previously, the errors from inferMutationAliasingEffects caused the pipeline to bail out before validateNoImpureFunctionsInRender ran. Now that errors are accumulated, both passes detect and report the same violations.

Consider deduplicating errors in aggregateErrors() (e.g., by source location + error category), or skipping validateNoImpureFunctionsInRender when inferMutationAliasingEffects already reported impure-function errors. The same duplication pattern also affects the new-mutability/error.invalid-impure-functions-in-render fixture.

Prompt To Fix With AI
This is a comment left during a code review.
Path: compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-impure-functions-in-render.expect.md
Line: 20

Comment:
**Duplicate errors reported to users**

This fixture now reports 6 errors when there are only 3 impure function calls. The same "Cannot call impure function" error is reported twice for each call site — once from `inferMutationAliasingEffects` (which now records errors via `env.recordErrors()` instead of throwing) and once from `validateNoImpureFunctionsInRender` (which runs later in the pipeline).

Previously, the errors from `inferMutationAliasingEffects` caused the pipeline to bail out before `validateNoImpureFunctionsInRender` ran. Now that errors are accumulated, both passes detect and report the same violations.

Consider deduplicating errors in `aggregateErrors()` (e.g., by source location + error category), or skipping `validateNoImpureFunctionsInRender` when `inferMutationAliasingEffects` already reported impure-function errors. The same duplication pattern also affects the `new-mutability/error.invalid-impure-functions-in-render` fixture.

How can I resolve this? If you propose a fix, please make it concise.


```
Found 1 error:
Found 2 errors:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Identical error reported twice

This fixture now shows 2 errors that are exact duplicates — same message, same location, same category. The type configuration validation in Globals.ts throws a Config error (not an invariant), which tryRecord catches and records. When a subsequent pass re-resolves the same type, the validation fires again, producing an identical second error.

This is different from the impure-function duplication (where two different passes detect the same issue) — here it's the same code path being triggered twice. The same pattern affects error.invalid-type-provider-hook-name-not-typed-as-hook-namespace, error.invalid-type-provider-hooklike-module-default-not-hook, and error.invalid-type-provider-nonhook-name-typed-as-hook.

Consider caching the type-provider validation result on the Environment so it doesn't throw on subsequent lookups, or deduplicating in aggregateErrors().

Prompt To Fix With AI
This is a comment left during a code review.
Path: compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-type-provider-hook-name-not-typed-as-hook.expect.md
Line: 17

Comment:
**Identical error reported twice**

This fixture now shows 2 errors that are exact duplicates — same message, same location, same category. The type configuration validation in `Globals.ts` throws a `Config` error (not an invariant), which `tryRecord` catches and records. When a subsequent pass re-resolves the same type, the validation fires again, producing an identical second error.

This is different from the impure-function duplication (where two different passes detect the same issue) — here it's the same code path being triggered twice. The same pattern affects `error.invalid-type-provider-hook-name-not-typed-as-hook-namespace`, `error.invalid-type-provider-hooklike-module-default-not-hook`, and `error.invalid-type-provider-nonhook-name-typed-as-hook`.

Consider caching the type-provider validation result on the Environment so it doesn't throw on subsequent lookups, or deduplicating in `aggregateErrors()`.

How can I resolve this? If you propose a fix, please make it concise.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

32 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

27 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

josephsavona and others added 2 commits February 23, 2026 15:18
…ent (#35873)

Add error accumulation methods to the Environment class:
- #errors field to accumulate CompilerErrors across passes
- recordError() to record a single diagnostic (throws if Invariant)
- recordErrors() to record all diagnostics from a CompilerError
- hasErrors() to check if any errors have been recorded
- aggregateErrors() to retrieve the accumulated CompilerError
- tryRecord() to wrap callbacks and catch CompilerErrors

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35873).
* #35888
* #35884
* #35883
* #35882
* #35881
* #35880
* #35879
* #35878
* #35877
* #35876
* #35875
* #35874
* __->__ #35873
…erance

- Change runWithEnvironment/run/compileFn to return Result<CodegenFunction, CompilerError>
- Wrap all pipeline passes in env.tryRecord() to catch and record CompilerErrors
- Record inference pass errors via env.recordErrors() instead of throwing
- Handle codegen Result explicitly, returning Err on failure
- Add final error check: return Err(env.aggregateErrors()) if any errors accumulated
- Update tryCompileFunction and retryCompileFunction in Program.ts to handle Result
- Keep lint-only passes using env.logErrors() (non-blocking)
- Update 52 test fixture expectations that now report additional errors

This is the core integration that enables fault tolerance: errors are caught,
recorded, and the pipeline continues to discover more errors.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

27 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

## Code

```javascript
import { c as _c } from "react/compiler-runtime";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unused compiler-runtime import in output

With fault tolerance, it appears a function in this module (likely useControllableState or NoopComponent) now completes compilation where it previously didn't, triggering addImportsToProgram. However, the compiled output doesn't actually use _c anywhere — no memoization cache calls appear in the code below. This results in a dead import in the compiled output.

This is harmless at runtime (bundlers typically tree-shake unused imports), but it's a minor regression in output quality for the 'use no forget' opt-out case.

Prompt To Fix With AI
This is a comment left during a code review.
Path: compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-no-forget-multiple-with-eslint-suppression.expect.md
Line: 28

Comment:
**Unused compiler-runtime import in output**

With fault tolerance, it appears a function in this module (likely `useControllableState` or `NoopComponent`) now completes compilation where it previously didn't, triggering `addImportsToProgram`. However, the compiled output doesn't actually use `_c` anywhere — no memoization cache calls appear in the code below. This results in a dead import in the compiled output.

This is harmless at runtime (bundlers typically tree-shake unused imports), but it's a minor regression in output quality for the `'use no forget'` opt-out case.

How can I resolve this? If you propose a fix, please make it concise.

@everettbu

Copy link
Copy Markdown
Author

Upstream PR was closed or merged. Code is synced via branch mirror.

@everettbu everettbu closed this Feb 24, 2026
@everettbu
everettbu deleted the pr35874 branch February 24, 2026 00:36
@everettbu
everettbu restored the pr35874 branch February 24, 2026 01:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed React Core Team Opened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants