Commit Graph

21333 Commits

Author SHA1 Message Date
Joseph Savona
90c6d1b218 [compiler][snap] More minimization improvements (#35689)
* A few new minimization strategies, removing function params and
array/object pattern elements
* Ensure that we preserve the same set of errors based on not just
category+reason but also description.
2026-02-04 10:09:28 -05:00
Sebastian "Sebbie" Silbermann
f84ce5a45c [flags] Turn on enableViewTransition in OSS react-test-renderer (#35684) 2026-02-04 11:42:49 +01:00
Sebastian "Sebbie" Silbermann
c9ff56ec74 [DevTools] Disable Activity slices by default (#35685) 2026-02-04 10:56:33 +01:00
Joseph Savona
3ce1316b05 [compiler][snap] Fixes to relative path resolution; compile subcommand (#35688)
More snap improvements for use with agents:
* `yarn snap compile [--debug] <path>` for compiling any file,
optionally with debug logs
* `yarn snap minimize <path>` now accepts path as a positional param for
consistency w 'compile' command
* Both compile/minimize commands properly handle paths relative to the
compiler/ directory. When using `yarn snap` the current working
directory is compiler/packages/snap, but you're generally running it
from the compiler directory so this matches expectations of callers
better.
2026-02-03 22:12:21 -05:00
Joseph Savona
cd0c4879a2 [compiler] Fix for loops in try/catch (#35686)
This is a combination of a) a subagent for investigating compiler errors
and b) testing that agent by fixing bugs with for loops within
try/catch. My recent diffs to support maybe-throw within value blocks
was incomplete and handled many cases, like optionals/logicals/etc
within try/catch. However, the handling for for loops was making more
assumptions and needed additional fixes.

Key changes:
* `maybe-throw` terminal `handler` is now nullable. PruneMaybeThrows
nulls the handler for blocks that cannot throw, rather than changing to
a `goto`. This preserves more information, and makes it easier for
BuildReactiveFunction's visitValueBlock() to reconstruct the value
blocks
* Updates BuildReactiveFunction's handling of `for` init/test/update
(and similar for `for..of` and `for..in`) to correctly extract value
blocks. The previous logic made assumptions about the shape of the
SequenceExpression which were incorrect in some cases within try/catch.
The new helper extracts a flattened SequenceExpression.

Supporting changes:
* The agent itself (tested via this diff)
* Updated the script for invoking snap to keep `compiler/` as the
working directory, allowing relative paths to work more easily
* Add an `--update` (`-u`) flag to `yarn snap minimize`, which updates
the fixture in place w the minimized version
2026-02-03 18:04:34 -05:00
Sebastian "Sebbie" Silbermann
6853d7ab2f [Perf Tracks] Prevent crash when accessing $$typeof (#35679) 2026-02-03 17:53:45 +01:00
Sebastian "Sebbie" Silbermann
e32c126121 [flags] Turn on enableAsyncDebugInfo everywhere (#35683) 2026-02-03 17:52:57 +01:00
Ricky
3e00319b35 [Flight] allow context providers from client modules (#35675)
Allows Server Components to import Context from a `"use client'` module
and render its Provider.

Only tricky part was that I needed to add `REACT_CONTEXT_TYPE` handling
in mountLazyComponent so lazy-resolved Context types can be rendered.
Previously only functions, REACT_FORWARD_REF_TYPE, and REACT_MEMO_TYPE
were handled.

Tested in the Flight fixture.

ty bb claude

Closes https://github.com/facebook/react/issues/35340

---------

Co-authored-by: Sophie Alpert <git@sophiebits.com>
2026-02-03 10:22:57 -05:00
Sebastian "Sebbie" Silbermann
3419420e8b [flags] Cleanup enableActivity (#35681) 2026-02-03 16:08:18 +01:00
Janka Uryga
b1533b034e [Flight] Allow overriding request.timeOrigin via options.startTime (#35598)
Currently, IO that finished before the request started is not considered
IO:

6a0ab4d2dd/packages/react-server/src/ReactFlightServer.js (L5338-L5343)
This leads to loss of debug info when a flight stream is deserialized
and serialized again.
We can solve this by allowing "when the the request started" to be set
to a point in the past, when the original stream started by doing

```js
const startTime = performance.now() + performance.timeOrigin
// ... stuff happens and time passes...
ReactServer.renderToReadableStream(..., { startTime })
```
2026-02-03 15:29:51 +01:00
Ruslan Lesiutin
5dad2b47b8 [DevTools] Fix commit index reset when switching profiler roots (#35672)
Fixes https://github.com/facebook/react/issues/31463,
https://github.com/facebook/react/issues/30114.

When switching between roots in the profiler flamegraph, the commit
index was preserved from the previous root. This caused an error
"Invalid commit X. There are only Y commits." when the new root had
fewer commits than the selected index.

This fix resets the commit index to 0 (or null if no commits) when the
commitData changes, which happens when switching roots.
2026-02-03 12:44:04 +00:00
Sebastian "Sebbie" Silbermann
748ee74e22 Use modern JSX runtime in Flight fixture (#35677) 2026-02-03 12:05:24 +01:00
Joseph Savona
d4a325df4d [compiler] Add snap subcommand to minimize a test input (#35663)
Snap now supports subcommands 'test' (default) and 'minimize`. The
minimize subcommand attempts to minimize a single failing input fixture
by incrementally simplifying the ast so long as the same error occurs. I
spot-checked it and it seemed to work pretty well. This is intended for
use in a new subagent designed for investigating bugs — fixture
simplification is an important part of the process and we can automate
this rather than light tokens on fire.

Example Input:

```js
function Component(props) {
  const x = [];
  let result;
  for (let i = 0; i < 10; i++) {
    if (cond) {
      try {
        result = {key: bar([props.cond && props.foo])};
      } catch (e) {
        console.log(e);
      }
    }
  }
  x.push(result);
  return <Stringify x={x} />;
}
```

Command output:

```
$ yarn snap minimize --path .../input.js
Minimizing: .../input.js

Minimizing................

--- Minimized Code ---
function Component(props) {
  try {
    props && props;
  } catch (e) {}
}

Reduced from 16 lines to 5 lines
```

This demonstrates things like:
* Removing one statement at at time
* Replacing if/else with the test, consequent, or alternate. Similar for
other control-flow statements including try/catch
* Removing individual array/object expression properties
* Replacing single-value array/object with the value
* Replacing control-flow expression (logical, consequent) w the test or
left/right values
* Removing call arguments
* Replacing calls with a single argument with the argument
* Replacing calls with multiple arguments with an array of the arguments
* Replacing optional member/call with non-optional versions
* Replacing member expression with the object. If computed, also try
replacing w the key
* And a bunch more strategies, see the code
2026-02-02 22:03:47 -05:00
Sebastian "Sebbie" Silbermann
7b023d7073 [react-dom] Include submitter in submit events (#35590) 2026-02-02 21:17:31 +01:00
Sebastian "Sebbie" Silbermann
dcab44d757 [react-dom] Fire onReset when automatically resetting forms (#35176) 2026-02-02 21:17:14 +01:00
Joseph Savona
b8a6bfa22c [compiler] Support optional/logical/etc within try/catch (#35606)
Adds support for value terminals (optional/logical/ternary/sequence)
within try/catch clauses.

Try/catch expressions insert maybe-throw terminals after each
instruction, but BuildReactiveFunction's value block extraction was not
expecting these terminals. The fix is to roughly treat maybe-throw
similarly to goto, falling through to the continuation block, but there
are a few edge cases to handle.

I've also added extensive tests, including testing that errors correctly
flow to the catch handler.
2026-02-02 09:27:05 -08:00
Sebastian "Sebbie" Silbermann
ed4bd540ca [Flight] Warn once if eval is disabled in dev environment (#35661) 2026-02-02 12:56:14 +01:00
Nathan
64b4605cb8 [compiler] fix source location for return statements (#35660)
Fixes missing source locations for ReturnStatement nodes in generated
ast. Simple change using existing pattern, only required changes to the
codegen step, no other pipeline changes.

**Most file changes are new lines in generated code.** [First
commit](d15e90ebe0)
has the relevant changes, second commit has the noisy snap updates.

I added an exception to the validator to not report an error when a
return statement will be optimized to an implicit return by codegen, as
there's no separate return statement to instrument anyways in the final
ast. An edge case when it comes to preserving source locations for
instrumentation that is likely not as common for most babel transforms
since they are not doing optimizations.
2026-01-30 08:37:19 -08:00
Sebastian "Sebbie" Silbermann
da64117876 [Perf Tracks] Handle function names that aren't strings (#35659) 2026-01-29 18:32:18 +01:00
Ricky
230772f99d [tests] Fix ReactDOMAttribute-test (#35654)
In https://github.com/facebook/react/pull/35646 I thought there was a
bug in trusted types, but the bug is in jsdom.

For trusted types we still want to check the coersion and throw for a
good dev warning, but prod will also throw becuase the browser will
implicitly coerce to a string. This ensures there's no behavior
difference between dev and prod.

So the right fix is to add in the JSDOM hack that's used in
`ReactDOMSelect-test.js`.
2026-01-28 16:00:40 -05:00
Jack Pope
90b2dd442c Add additional fixtures for FragmentInstance text node support (#35631)
Stacked on https://github.com/facebook/react/pull/35630

- Adds test case for compareDocumentPosition, missing before and also
extending to text nodes
- Adds event handling fixture case for text
- Adds getRootNode fixture case for text
2026-01-28 14:55:07 -05:00
Jack Pope
875b06489f Add text node support to FragmentInstance operations (#35630)
This PR adds text node support to FragmentInstance operations, allowing
fragment refs to properly handle fragments that contain text nodes
(either mixed with elements or text-only).

Not currently adding/removing new text nodes as we don't need to track
them for events or observers in DOM. Will follow up on this and with
Fabric support.

## Support through parent element
- `dispatchEvent`
- `compareDocumentPosition`
- `getRootNode`

## Support through Range API
- `getClientRects`: Uses Range to calculate bounding rects for text
nodes
- `scrollIntoView`: Uses Range to scroll to text node positions directly

## No support
- `focus`/`focusLast`/`blur`: Noop for text-only fragments
- `observeUsing`:  Warns for text-only fragments in DEV
- `addEventListener`/`removeEventListener`: Ignores text nodes, but
still works on Fragment level through `dispatchEvent`
2026-01-28 14:45:17 -05:00
Jan Olaf Martin
d4d099f05b [flags] make enableTrustedTypesIntegration dynamic (#35646)
Co-authored-by: Rick Hanlon <rickhanlonii@meta.com>
2026-01-28 13:15:33 -05:00
Sebastian "Sebbie" Silbermann
c0c37063e2 [Flight] Restore original function name in dev, server callstacks served with unsafe-eval (#35650) 2026-01-28 18:41:08 +01:00
Sebastian "Sebbie" Silbermann
87ae75b33f [Perf Tracks] Use minus (-) instead of en dash for removed props (#35649) 2026-01-28 12:14:59 +01:00
Sebastian "Sebbie" Silbermann
ff191f24b5 [Perf Tracks] Handle arrays with bigints in deep objects (#35648) 2026-01-28 11:54:50 +01:00
Ricky
e66ef6480e [tests] remove withoutStack from assertConsole helpers (#35498)
Stacked on https://github.com/facebook/react/pull/35497

-----

Now that the assert helpers require a component stack, we don't need the
`{withoutStack: true}` option.
2026-01-27 22:34:03 -05:00
Sebastian "Sebbie" Silbermann
8c34556ca8 [Flight] Fix react-markup types for server references (#35634) 2026-01-26 21:13:16 +01:00
Hendrik Liebau
10680271fa [Flight] Add more DoS mitigations to Flight Reply, and harden Flight (#35632)
This fixes security vulnerabilities in Server Functions.

---------

Co-authored-by: Sebastian Markbåge <sebastian@calyptus.eu>
Co-authored-by: Josh Story <josh.c.story@gmail.com>
Co-authored-by: Janka Uryga <lolzatu2@gmail.com>
Co-authored-by: Sebastian Sebbie Silbermann <sebastian.silbermann@vercel.com>
2026-01-26 20:24:58 +01:00
Ruslan Lesiutin
699abc89ce [flags] make enableComponentPerformanceTrack static everywhere (#35629)
Follow-up to https://github.com/facebook/react/pull/34665.

Already gated on `enableProfilerTimer` everywhere, which is only enabled
for `__PROFILE__`, except for Flight should be unified in a future.
2026-01-26 18:38:56 +00:00
Sebastian "Sebbie" Silbermann
3e319a943c [DevTools] Apply component filters on initial load (#35587) 2026-01-26 11:06:04 +01:00
Sebastian "Sebbie" Silbermann
2c30ebc4e3 [DevTools] Update inspected element on component filter changes (#35599) 2026-01-26 11:04:06 +01:00
Ricky
a0566250b2 [repo] init claude config (#35617)
## Overview

Adds a claude setup that works with the nested /compiler setup.

The constraints are:
- when working in the root repo, don't use the compiler configs (easy)
- when working in the compiler/ don't use the parent contigs (hard)

The first one is easy: there's a claude.md and .claude directory in
/compiler that is only loaded when you start a session from /compuler.
The second one is hard, because if you start a session from /compiler,
the parent claude files and skills are loaded.

I was able to deny the permissions to the parent skills in
settings.json, but the descriptions are still loaded into context and I
don't think that's avoidable.

To keep the parent claude file out of context, I created a hook hack: I
moved all the non-compiler claude file context to instructions.md and
added a SessionStart hook to cat the file into context if the cwd isn't
the /compiler. Works well, but won't show it as part of the `/context`
slash command.


## Skills

I also added a number of skills specific to the React repo:

| Skill | Description |
|-------|-------------|
| `/extract-errors` |  `yarn extract-errors` |
| `/feature-flags` | how feature flags work and `@gate`  |
| `/fix` | linc and prettier |
| `/flags` | `yarn flags` |
| `/flow` | `yarn flow <variant>` |
| `/test` | `yarn test-*` |
| `/verify` | `run all the lints/tests/flow to verify` |

### Example: Flow

| before | after |
|-----|-----|
| <img width="1076" height="442" alt="flow-before"
src="https://github.com/user-attachments/assets/73eec143-d0af-4771-b501-c9dc29cc09ac"
/> | <img width="1076" height="273" alt="flow-after"
src="https://github.com/user-attachments/assets/292d33af-1d98-4252-9c08-744b33e88b86"
/> |

### Example: Tests

| before | after |
|-----|-----|
| <img width="1048" height="607" alt="test-before"
src="https://github.com/user-attachments/assets/aa558ccf-2cee-4d22-b1f1-e4221c5a59dd"
/> | <img width="1075" height="359" alt="test-after"
src="https://github.com/user-attachments/assets/eb795392-6f46-403f-b9bb-8851ed790165"
/> |
2026-01-23 20:16:06 -05:00
Joseph Savona
870cccd656 [compiler] Summaries of the compiler passes to assist agents in development (#35595)
Autogenerated summaries of each of the compiler passes which allow
agents to get the key ideas of a compiler pass, including key
input/output invariants, without having to reprocess the file each time.
In the subsequent diff this seemed to help.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35595).
* #35607
* #35298
* #35596
* #35573
* __->__ #35595
* #35539
2026-01-23 11:26:47 -08:00
Joseph Savona
c3b95b0979 [compiler] Improve snap workflow for debugging errors (#35539)
Much nicer workflow for working through errors in the compiler:
* Run `yarn snap -w`, oops there are are errors
* Hit 'p' to select a fixture => the suggestions populate with recent
failures, sorted alphabetically. No need to copy/paste the name of the
fixture you want to focus on!
* tab/shift-tab to pick one, hit enter to select that one
* ...Focus on fixing that test...
* 'p' to re-enter the picker. Snap tracks the last state of each fixture
and continues to show all tests that failed on their last run, so you
can easily move on to the next one. The currently selected test is
highlighted, making it easy to move to the next one.
* 'a' at any time to run all tests
* 'd' at any time to toggle debug output on/off (while focusing on a
single test)

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35539).
* #35607
* #35298
* #35596
* #35573
* #35595
* __->__ #35539
2026-01-23 11:26:33 -08:00
Joseph Savona
006ae37972 [compiler] Collapse CompilerError.{invariant,simpleInvariant} (#35614)
`invariant()` was a pain to use - we always record a single location,
but the API required passing a compiler detail. This PR replaces
`invariant()` (keeping the name) with `simpleInvariant()`s signature,
and updates call sites accordingly. I've noticed that agents
consistently get invariant() wrong, which aligns with it being tedious
to call when you're writing code by hand. The simplified API should help
a bit.
2026-01-23 11:07:11 -08:00
Joseph Savona
a688a3d18c worktree script improvements (#35603)
A few small improvements:
* Use `<root>/.worktrees` as the directory for worktrees so its hidden
by default in finder/ls
* Generate names with a timestamp, and allow auto-generating a name so
that you can just call eg `./scripts/worktree.sh --compiler --claude`
and get a random name
2026-01-23 10:41:17 -08:00
Joseph Savona
2c8725fdfd [compiler] snap fails if nothing compiled, unless @expectNothingCompiled (#35615)
A few times an agent has constructed fixtures that are silently skipped
because the component has no jsx or hook calls. This PR updates snap to
ensure that for each fixture either:

1) There are at least one compile success/failure *and* the
`@expectNothingCompiled` pragma is missing
2) OR there are zero success/failures *and* the `@expectNothingCompiled`
pragma is present

This ensures we are intentional about fixtures that are expected not to
have compilation, and know if that expectation breaks.
2026-01-23 10:38:40 -08:00
Joseph Savona
03613cd68c [compiler] Improve snap usability (#35537)
A whole bunch of changes to snap aimed at making it more usable for
humans and agents. Here's the new CLI interface:

```
node dist/main.js --help
Options:
      --version         Show version number                            [boolean]
      --sync            Run compiler in main thread (instead of using worker
                        threads or subprocesses). Defaults to false.
                                                      [boolean] [default: false]
      --worker-threads  Run compiler in worker threads (instead of
                        subprocesses). Defaults to true.
                                                       [boolean] [default: true]
      --help            Show help                                      [boolean]
  -w, --watch           Run compiler in watch mode, re-running after changes
                                                                       [boolean]
  -u, --update          Update fixtures                                [boolean]
  -p, --pattern         Optional glob pattern to filter fixtures (e.g.,
                        "error.*", "use-memo")                          [string]
  -d, --debug           Enable debug logging to print HIR for each pass[boolean]
```

Key changes:
* Added abbreviations for common arguments
* No more testfilter.txt! Filtering/debugging works more like Jest, see
below.
* The `--debug` flag (`-d`) controls whether to emit debug information.
In watch mode, this flag sets the initial debug value, and it can be
toggled by pressing the 'd' key while watching.
* The `--pattern` flag (`-p`) sets a filter pattern. In watch mode, this
flag sets the initial filter. It can be changed by pressing 'p' and
typing a new pattern, or pressing 'a' to switch to running all tests.
* As before, we only actually enable debugging if debug mode is enabled
_and_ there is only one test selected.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35537).
* #35607
* #35298
* #35596
* #35573
* #35595
* #35539
* __->__ #35537
* #35523
2026-01-23 10:36:55 -08:00
Joseph Savona
2af6822c21 [compiler] Claude file/settings (#35523)
Initializes CLAUDE.md and a settings file for the compiler/ directory to
help use claude with the compiler. Note that some of the commands here
depend on changes to snap from the next PR.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35523).
* #35607
* #35298
* #35596
* #35573
* #35595
* #35539
* #35537
* __->__ #35523
2026-01-23 10:36:43 -08:00
Sebastian "Sebbie" Silbermann
24d8716e36 Gitignore local Claude files (#35610) 2026-01-23 16:30:08 +01:00
Ruslan Lesiutin
94913cbffe [flags] cleanup renameElementSymbol (#35600)
Removed the feature flag completely, enabled by default. Will land once
I have everything ready on xplat side.
2026-01-23 10:46:30 +00:00
Ricky
2d8e7f1ce3 [flags] Remove enableHydrationLaneScheduling (#35549)
This is just a killswitch and has been on for over a year
https://github.com/facebook/react/pull/31751
2026-01-22 13:51:48 -05:00
Joseph Savona
6a0ab4d2dd Add worktree script (#35593)
Intended to be used directly and/or from skills in an agent.

Usage is `./scripts/worktree.sh [--compiler] [--claude] <name>`. The
script:
* Checks that ./worktrees is in gitignore
* Checks the named worktree does not exist yet
* Creates the named worktree in ./worktrees/
* Installs deps
* cds into the worktree (optionally the compiler dir if `--compiler`)
* optionally runs claude in the worktree if `--claude`
2026-01-21 22:38:37 -08:00
Joseph Savona
03ee29da2f [eslint-plugin-react-hooks] Skip compilation for non-React files (#35589)
Add a fast heuristic to detect whether a file may contain React
components or hooks before running the full compiler. This avoids the
overhead of Babel AST parsing and compilation for utility files, config
files, and other non-React code.

The heuristic uses ESLint's already-parsed AST to check for functions
with React-like names at module scope:
- Capitalized functions: MyComponent, Button, App
- Hook pattern functions: useEffect, useState, useMyCustomHook

Files without matching function names are skipped and return an empty
result, which is cached to avoid re-checking for subsequent rules.

Also adds test coverage for the heuristic edge cases.
2026-01-21 12:49:15 -08:00
Sebastian "Sebbie" Silbermann
cdbd55f440 Type react-devtools-hook-installer and react-devtools-hook-settings-injector messages (#35586) 2026-01-21 19:13:24 +01:00
Sebastian Markbåge
b546603bcb [Fiber] getNearestMountedFiber should consider fibers with alternates as mounted (#35578) 2026-01-21 08:33:35 -05:00
Sebastian "Sebbie" Silbermann
7fccd6b5a3 [DevTools] Fix console links not being openable (#35229) 2026-01-21 10:34:26 +01:00
Sebastian Markbåge
d29087523a Cancel animation when a custom Timeline is used (#35567)
Follow up to #35559.

The clean up function of the custom timeline doesn't necessarily clean
up the animation. Just the timeline's internal state.

This affects Firefox which doesn't support ScrollTimeline so uses the
polyfill's custom timeline.
2026-01-19 20:53:05 -05:00
Sebastian Markbåge
d343c39cce Remove Gesture warning when cloning the root (#35566)
Currently we always clone the root when a gesture transition happens.
The was to add an optimization where if a Transition could be isolated
to an absolutely positioned subtree then we could just clone that
subtree or just do a plain insertion if it was simple an Enter. That way
when switching between two absolutely positioned pages the shell
wouldn't need to be cloned. In that case `detectMutationOrInsertClones`
would return false. However, currently it always return true because we
don't yet have that optimization.

The idea was to warn when the root required cloning to ensure that you
optimize it intentionally since it's easy to accidentally update more
than necessary. However, since this is not yet actionable I'm removing
this warning for now.

Instead, I add a warning for particularly bad cases where you really
shouldn't clone like iframe and video. They may not be very actionable
without the optimization since you can't scope it down to a subtree
without the optimization. So if they're above the gesture then they're
always cloned atm. However, it might also be that it's unnecessary to
keep them mounted if they could be removed or hidden with Activity.
2026-01-19 19:28:12 -05:00