Commit Graph
1284 Commits
Author SHA1 Message Date
josephsavona c4e079782f [compiler] Add definitions for Object entries/keys/values (#34047)
Fixes remaining issue in #32261, where passing a previously useMemo()-d
value to `Object.entries()` makes the compiler think the value is
mutated and fail validatePreserveExistingMemo. While I was there I added
Object.keys() and Object.values() too.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34047).
* #34049
* __->__ #34047
* #34044

DiffTrain build for [0860b9cc1f](https://github.com/facebook/react/commit/0860b9cc1f4a7188b41204bddc57a127a8bbf6e9)
2025-08-01 13:06:06 -07:00
poteto 12966d2c5f [compiler] Emit more specific error when making identifiers with reserved words (#34080)
This currently throws an invariant which may be misleading. I checked
the ecma262 spec and used the same list of reserved words in our check.
To err on the side of being conservative, we also error when strict mode
reserved words are used.

DiffTrain build for [52612a7cbd](https://github.com/facebook/react/commit/52612a7cbdd8e1fee9599478247f78725869ebad)
2025-08-01 12:18:08 -07:00
gnoff 0e7e542347 [Fizz] Count Boundary bytes that may contribute to the preamble in the request byteSize (#34059)
Stacked on #34058

When tracking how large the shell is we currently only track the bytes
of everything above Suspense boundaries. However since Boundaries that
contribute to the preamble will always be inlined when the shell flushes
they should also be considered as part of the request byteSize since
they always flush alongside the shell. This change adds this tracking

DiffTrain build for [8de7aed892](https://github.com/facebook/react/commit/8de7aed8927d87a9e7e838f5d8ae28d5c30805d3)
2025-07-30 18:25:24 -07:00
gnoff 470e0bb4f5 [Fizz] Don't outline Boundaries that may contribute to the preamble (#34058)
Suspense boundaries that may have contributed to the preamble should not
be outlined due to size because these boundaries are only meant to be in
fallback state if the boundary actually errors. This change excludes any
boundary which has the potential to contribute to the preamble. We could
alternatively track which boundaries actually contributed to the
preamble but in practice there will be very few and I think this is
sufficient.

One problem with this approach is it makes Suspense above body opt out
of the mode where we omit rel="expect" for large shells. In essence
Suspense above body has the semantics of a Shell (it blocks flushing
until resolved) but it doesn't get tracked as request bytes and thus we
will not opt users into the skipped blocking shell for very large
boundaries.

This will be fixed in a followup

DiffTrain build for [98773466ce](https://github.com/facebook/react/commit/98773466ce6736a5ffb7e54c1f4b44645ac18a80)
2025-07-30 18:13:01 -07:00
josephsavona e918a9db2a Enable ref validation in linter (#34044)
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34044).
* #34027
* __->__ #34044

DiffTrain build for [88b40f6e41](https://github.com/facebook/react/commit/88b40f6e41004773f19d37827980c66a8cf1865b)
2025-07-29 12:36:49 -07:00
josephsavona 880a03f99e [compiler] Allow assigning ref-accessing functions to objects if not mutated (#34026)
Allows assigning a ref-accessing function to an object so long as that
object is not subsequently transitively mutated. We should likely
rewrite the ref validation to use the new mutation/aliasing effects,
which would provide a more consistent behavior across instruction types
and require fewer special cases like this.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34026).
* #34027
* __->__ #34026

DiffTrain build for [04a7a61918](https://github.com/facebook/react/commit/04a7a61918522734a083bff37843865d7815d466)
2025-07-29 11:04:45 -07:00
josephsavona e0a3dc5c61 [compiler] disallow ref access in state initializer, reducer/initializer (#34025)
Per title, disallow ref access in `useState()` initializer function,
`useReducer()` reducer, and `useReducer()` init function.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34025).
* #34027
* #34026
* __->__ #34025

DiffTrain build for [c2326b1336](https://github.com/facebook/react/commit/c2326b1336e38a52899fad6c2ddbb71ea7ddd3ee)
2025-07-29 11:03:02 -07:00
josephsavona 7f88cd0cf5 [compiler] treat ref-like identifiers as refs by default (#34005)
`@enableTreatRefLikeIdentifiersAsRefs` is now on by default. I made one
small fix to the render helper logic as part of this, uncovered by
including more tests.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34005).
* #34027
* #34026
* #34025
* #34024
* __->__ #34005

DiffTrain build for [6891dcb87d](https://github.com/facebook/react/commit/6891dcb87db831db17ab109730dea63706875dd7)
2025-07-29 10:58:35 -07:00
josephsavona 5cf31b63ee [compiler] Allow mergeRefs pattern (and detect refs passed as ref prop) (#34004)
Two related changes:
* ValidateNoRefAccessInRender now allows the mergeRefs pattern, ie a
function that aggregates multiple refs into a new ref. This is the main
case where we have seen false positive no-ref-in-render errors.
* Behind `@enableTreatRefLikeIdentifiersAsRefs`, we infer values passed
as the `ref` prop to some JSX as refs.

The second change is potentially helpful for situations such as

```js
function Component({ref: parentRef}) {
  const childRef = useRef(null);
  const mergedRef = mergeRefs(parentRef, childRef);
  useEffect(() => {
    // generally accesses childRef, not mergedRef
  }, []);
  return <Foo ref={mergedRef} />;
}
```

Ie where you create a merged ref but don't access its `.current`
property. Without inferring `ref` props as refs, we'd fail to allow this
merge refs case.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34004).
* #34027
* #34026
* #34025
* #34024
* #34005
* #34006
* __->__ #34004

DiffTrain build for [1d7e942da7](https://github.com/facebook/react/commit/1d7e942da76c794c3cbf52a8c214d90a69814a8f)
2025-07-29 10:12:05 -07:00
josephsavona 266f429f27 [compiler] Improve ref validation error message (#34003)
Improves the error message for ValidateNoRefAccessInRender, using the
new diagnostic type as well as providing a longer but succinct summary
of what refs are for and why they're unsafe to access in render.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34003).
* #34027
* #34026
* #34025
* #34024
* #34005
* #34006
* #34004
* __->__ #34003

DiffTrain build for [79dc706498](https://github.com/facebook/react/commit/79dc706498c4f8ef077167898492693197e1b975)
2025-07-29 10:10:52 -07:00
josephsavona c681973384 [compiler] Fixes to enableTreatRefLikeIdentifiersAsRefs (#34000)
We added the `@enableTreatRefLikeIdentifiersAsRefs` feature a while back
but never enabled it. Since then we've continued to see examples that
motivate this mode, so here we're fixing it up to prepare to enable by
default. It now works as follows:

* If we find a property load or property store where both a) the
object's name is ref-like (`ref` or `-Ref`) and b) the property is
`current`, we infer the object itself as a ref and the value of the
property as a ref value. Originally the feature only detected property
loads, not stores.
* Inferred refs are not considered stable (this is a change from the
original implementation). The only way to get a stable ref is by calling
`useRef()`. We've seen issues with assuming refs are stable.

With this change, cases like the following now correctly error:

```js
function Foo(props) {
  const fooRef = props.fooRef;
  fooRef.current = true;
  ^^^^^^^^^^^^^^ cannot modify ref in render
}
```

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34000).
* #34027
* #34026
* #34025
* #34024
* #34005
* #34006
* #34004
* #34003
* __->__ #34000

DiffTrain build for [85bbe39ef8](https://github.com/facebook/react/commit/85bbe39ef8e24a192b5e9f2987b1babf8ce772e1)
2025-07-29 10:05:12 -07:00
poteto 16f8eb9153 [eslint] Disallow use within try/catch blocks (#34040)
Follow up to #34032. The linter now ensures that `use` cannot be used
within try/catch.

DiffTrain build for [820af20971](https://github.com/facebook/react/commit/820af2097103309fdc5675d2bde744103a439eff)
2025-07-29 09:39:49 -07:00
sebmarkbage 0c4e650f61 [Fiber] Treat unwrapping React.lazy more like a use() (#34031)
While we want to get rid of React.lazy's special wrapper type and just
use a Promise for the type, we still have the wrapper.

However, this is still conceptually the same as a Usable in that it
should be have the same if you `use(promise)` or render a Promise as a
child or type position.

This PR makes it behave like a `use()` when we unwrap them. We could
move to a model where it actually reaches the internal of the Lazy's
Promise when it unwraps but for now I leave the lazy API signature
intact by just catching the Promise and then "use()" that.

This lets us align on the semantics with `use()` such as the suspense
yield optimization. It also lets us warn or fork based on legacy
throw-a-Promise behavior where as `React.lazy` is not deprecated.

DiffTrain build for [9be531cd37](https://github.com/facebook/react/commit/9be531cd37f5558c72f7de360eb921b0074e8544)
2025-07-29 08:56:28 -07:00
poteto 88ca7c7ed6 [compiler] Enable validateNoVoidUseMemo in eslint & playground (#34022)
Enables `validateNoVoidUseMemo` by default only in eslint (it defaults
to false otherwise) as well as the playground.

DiffTrain build for [7ee7571212](https://github.com/facebook/react/commit/7ee7571212bc02354b852752a98b23bc90546fdf)
2025-07-28 10:48:35 -07:00
poteto 1abacc2693 [compiler] Aggregate all errors reported from DropManualMemoization (#34002)
Noticed this from my previous PR that this pass was throwing on the
first error. This PR is a small refactor to aggregate every violation
and report them all at once.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34002).
* #34022
* __->__ #34002

DiffTrain build for [6b22f31f1a](https://github.com/facebook/react/commit/6b22f31f1ac88cce1b38c67a5c97c7ab0e832823)
2025-07-28 10:41:53 -07:00
poteto cf7bb43316 [compiler] Add new ValidateNoVoidUseMemo pass (#33990)
Adds a new validation pass to validate against `useMemo`s that don't
return anything. This usually indicates some kind of "useEffect"-like
code that has side effects that need to be memoized to prevent
overfiring, and is an anti-pattern.

A follow up validation could also look at the return value of `useMemo`s
to see if they are being used.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33990).
* #34022
* #34002
* #34001
* __->__ #33990
* #33989

DiffTrain build for [c60eebffea](https://github.com/facebook/react/commit/c60eebffea94a67f35c6ebbf7019e5b2145d4284)
2025-07-28 10:00:02 -07:00
poteto b723ffdb55 [compiler] Disambiguate between void, implicit, and explicit returns (#33989)
Adds a new property to ReturnTerminals to disambiguate whether it was
explicit, implicit (arrow function expressions), or void (where it was
omitted). I will use this property in the next PR adding a new
validation pass.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33989).
* #34022
* #34002
* #34001
* #33990
* __->__ #33989

DiffTrain build for [5dd622eabe](https://github.com/facebook/react/commit/5dd622eabe38e01781b3699d0d81c4a16e302f09)
2025-07-28 09:53:06 -07:00
eps1lon 15e2bbf2c7 fix: React.use inside React.lazy-ed component on SSR (#33941)
DiffTrain build for [cc015840ef](https://github.com/facebook/react/commit/cc015840ef72d48de86778785894c7ca44f4f856)
2025-07-28 01:41:54 -07:00
eps1lon bacebfd0a5 [Runtime] Fix CI (#33999)
DiffTrain build for [19baee813c](https://github.com/facebook/react/commit/19baee813cb08fc5971a3b301814faa6cd530ec8)
2025-07-25 12:11:08 -07:00
josephsavona e671c74a23 [compiler] Enable additional lints by default (#33752)
Enable more validations to help catch bad patterns, but only in the
linter. These rules are already enabled by default in the compiler _if_
violations could produce unsafe output.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33752).
* #33981
* #33777
* #33767
* #33765
* #33760
* #33759
* #33758
* #33751
* __->__ #33752
* #33753

DiffTrain build for [0d39496eab](https://github.com/facebook/react/commit/0d39496eab710b5a3efc07d34c0db3f2475c04f8)
2025-07-24 16:02:56 -07:00
josephsavona 97b9414b9a [compiler] Fix for false positive mutation of destructured spread object (#33786)
When destructuring, spread creates a new mutable object that _captures_
part of the original rvalue. This new value is safe to modify.

When making this change I realized that we weren't inferring array
pattern spread as creating an array (in type inference) so I also added
that here.

DiffTrain build for [448f781a52](https://github.com/facebook/react/commit/448f781a52d62042341d2411d1352d705ce2cbfe)
2025-07-24 15:40:55 -07:00
sebmarkbage 49e4c080e4 [Fiber] Don't throw away the Error object retaining the owner stack (#33976)
We currently throw away the Error once we've used to the owner stack of
a Fiber once. This maybe helps a bit with memory and redoing it but we
really don't expect most Fibers to hit this at all. It's not very hot.

If we throw away the Error, then we can't use native debugger protocols
to inspect the native stack. Instead, we'd have to maintain a url to
resource map indefinitely like what Chrome DevTools does to map a url to
a resource. Technically it's not even technically correct since the file
path might not be reversible and could in theory conflict.

DiffTrain build for [4f34cc4a2e](https://github.com/facebook/react/commit/4f34cc4a2e1198493375867d1876509ae9771aee)
2025-07-24 10:44:23 -07:00
eps1lon e5b30133c7 [Flight] Remove superfluous whitespace when console method is called with non-strings (#33953)
DiffTrain build for [f6fb1a07a5](https://github.com/facebook/react/commit/f6fb1a07a5fda2aa436f6ddf9a31025945cd67b3)
2025-07-23 01:13:06 -07:00
jbrown215 a25e9a67c2 Change autodeps configuration (#33800)
DiffTrain build for [074e92777c](https://github.com/facebook/react/commit/074e92777c22a56269647d614fdae80bf6406485)
2025-07-21 13:09:36 -07:00
jbrown215 fef10fd68d InferEffectDeps takes a React.AUTODEPS sigil (#33799)
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33799).
* #33800
* __->__ #33799

DiffTrain build for [dffacc7b80](https://github.com/facebook/react/commit/dffacc7b8094576c19790fe8341996f743ba4a89)
2025-07-17 05:38:15 -07:00
hoxyq a83fc58cfb fix: log renders from passive effects for only newly finished work (#33797)
This fixes displaying incorrect component render entries on a timeline,
when we are reconnecting passive effects.

### Before
<img width="2318" height="1127" alt="1"
src="https://github.com/user-attachments/assets/9b6b2824-d2de-43a3-8615-2c45d67c3668"
/>

The cloned nodes will persist original `actualStartTime`, when these
were first mounted. When we "replay", the end time will be "now" or
whatever the actual start time of the sibling. Depending on when this is
being recorded, the diff between end and start could be tens of seconds
and doesn't represent what React was doing.

We shouldn't log these entries at all.

### After
We are only logging newly finished renders, but could potentially loose
renders that never commit.

DiffTrain build for [9fec565a9b](https://github.com/facebook/react/commit/9fec565a9b9f78558323adff1013291cf46f7de7)
2025-07-16 10:16:47 -07:00
josephsavona 93f1925740 [compiler] Check TSAsExpression and TSNonNullExpression reorderability (#33788)
## Summary

The `TSAsExpression` and `TSNonNullExpression` nodes are supported by
`lowerExpression()` but `isReorderableExpression()` does not check if
they can be reordered. This PR updates `isReorderableExpression()` to
handle these two node types by adding cases that fall through to the
existing `TypeCastExpression` case.

We ran `react-compiler-healthcheck` at scale on several of our repos and
found dozens of `` (BuildHIR::node.lowerReorderableExpression)
Expression type `TSAsExpression` cannot be safely reordered`` errors and
a handful for `TSNonNullExpression`.

## How did you test this change?

In this case I added two fixture tests

DiffTrain build for [fe813143e2](https://github.com/facebook/react/commit/fe813143e23675963f92d25fa1fb35b39db40272)
2025-07-15 11:57:18 -07:00
jbrown215 af29a26f3d [eslint] Do not allow useEffectEvent fns to be called in arbitrary closures (#33544)
Summary:

useEffectEvent is meant to be used specifically in combination with
useEffect, and using
the feature in arbitrary closures can lead to surprising reactivity
semantics. In order to
minimize risk in the experimental rollout, we are going to restrict its
usage to being
called directly inside an effect or another useEffectEvent, effectively
enforcing the function
coloring statically. Without an effect system this is the best we can
do.

DiffTrain build for [97cdd5d3c3](https://github.com/facebook/react/commit/97cdd5d3c33eda77be4f96a43f72d6916d3badbb)
2025-07-10 13:56:44 -07:00
josephsavona 4ab994be7f [compiler] Add CompilerError.UnsupportedJS variant (#33750)
We use this variant for syntax we intentionally don't support: with
statements, eval, and inline class declarations.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33750).
* #33753
* #33752
* #33751
* __->__ #33750
* #33748

DiffTrain build for [96c61b7f1f](https://github.com/facebook/react/commit/96c61b7f1f145b9fe5103051b636959cdeb20cc8)
2025-07-09 22:30:34 -07:00
josephsavona 0116228a39 [compiler] Errors for eval(), with statments, class declarations (#33746)
* Error for `eval()`
* More specific error message for `with (expr) { ... }` syntax
* More specific error message for class declarations

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33746).
* #33752
* #33751
* #33750
* #33748
* #33747
* __->__ #33746

DiffTrain build for [4a3ff8eed6](https://github.com/facebook/react/commit/4a3ff8eed65f96cda7617150f92de3544d5ddf6a)
2025-07-09 22:24:39 -07:00
josephsavona 80e4d87f06 [compiler] Improve IIFE inlining (#33726)
We currently inline IIFEs by creating a temporary and a labeled block w
the original code. The original return statements turn into an
assignment to the temporary and break out of the label. However, many
cases of IIFEs are due to inlining of manual `useMemo()`, and these
cases often have only a single return statement. Here, the output is
cleaner if we avoid the temporary and label - so that's what we do in
this PR.

Note that the most complex part of the change is actually around
ValidatePreserveExistingMemo - we have some logic to track the IIFE
temporary reassignmetns which needs to be updated to handle the simpler
version of inlining.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33726).
* __->__ #33726
* #33725

DiffTrain build for [956d770adf](https://github.com/facebook/react/commit/956d770adf59e1f8a00a7b7c52b5727ef9e353e7)
2025-07-08 16:43:32 -07:00
gnoff c2297075f5 [Fizz] Render preamble eagerly (#33730)
We unnecessarily render the preamble in a task. This updates the
implementation to perform this render inline.

Testing this is tricky because one of the only ways you could assert
this was even happening is based on how things error if you abort while
rendering the root.

While adding a test for this I discovered that not all abortable tasks
report errors when aborted during a normal render. I've asserted the
current behavior and will address the other issue at another time and
updated the assertion later as necessary

DiffTrain build for [befc1246b0](https://github.com/facebook/react/commit/befc1246b07a04b401bc6e914b7f336a442dca1a)
2025-07-08 08:30:51 -07:00
sebmarkbage 0efbfeb94e [Fiber] Name content inside "Suspense fallback" (#33724)
Same as #33723 but for Fiber.

DiffTrain build for [b44a99bf58](https://github.com/facebook/react/commit/b44a99bf58d69d52b5288d9eadcc6d226d705e11)
2025-07-07 21:07:54 -07:00
rickhanlonii a357246f8c Finally remove favorSafetyOverHydrationPerf (#33619)
This is rolled out to 100%.

Let me merge it though.

DiffTrain build for [e43986f1f3](https://github.com/facebook/react/commit/e43986f1f3e6e94f7eef86fb21c830959e0ade6c)
2025-07-07 11:04:35 -07:00
rickhanlonii 0aa0c27c92 [tests] Assert on component stack for Maximum Update error (#33686)
Good to assert these include the component stack

DiffTrain build for [e4314a0a0f](https://github.com/facebook/react/commit/e4314a0a0f6ea1ab8f739c9119583d148c1be657)
2025-07-07 11:03:50 -07:00
sebmarkbage 56b1e5f29b [Fizz] Name content inside "Suspense fallback" (#33723)
Content in Suspense fallbacks are really not considered part of the
Suspense but since it does have some behavior it should be marked
somehow separately from the Suspense content.

A follow up would be to do the same in Fiber.

DiffTrain build for [c932e45780](https://github.com/facebook/react/commit/c932e457800f077352b1b322f14a796e589299fb)
2025-07-07 10:57:47 -07:00
sebmarkbage 216c636262 [Fiber] Highlight a Component with Deeply Equal Props in the Performance Track (#33660)
Stacked on #33658 and #33659.

If we detect that a component is receiving only deeply equal objects,
then we highlight it as potentially problematic and worth looking into.

<img width="1055" alt="Screenshot 2025-06-27 at 4 15 28 PM"
src="https://github.com/user-attachments/assets/e96c6a05-7fff-4fd7-b59a-36ed79f8e609"
/>

It's fairly conservative and can bail out for a number of reasons:

- We only log it on the first parent that triggered this case since
other children could be indirect causes.
- If children has changed then we bail out since this component will
rerender anyway. This means that it won't warn for a lot of cases that
receive plain DOM children since the DOM children won't themselves get
logged.
- If the component's total render time including children is 100ms or
less then we skip warning because rerendering might not be a big deal.
- We don't warn if you have shallow equality but could memoize the JSX
element itself since we don't typically recommend that and React
Compiler doesn't do that. It only warns if you have nested objects too.
- If the depth of the objects is deeper than like the 3 levels that we
print diffs for then we wouldn't warn since we don't know if they were
equal (although we might still warn on a child).
- If the component had any updates scheduled on itself (e.g. setState)
then we don't warn since it would rerender anyway. This should really
consider Context updates too but we don't do that atm. Technically you
should still memoize the incoming props even if you also had unrelated
updates since it could apply to deeper bailouts.

DiffTrain build for [0b78161d7d](https://github.com/facebook/react/commit/0b78161d7d76b7fb9786f25dd222010b9e417191)
2025-07-02 14:39:23 -07:00
sebmarkbage e05a926ec6 Clear width/height from Keyframes to Optimize View Transitions (#33576)
View Transitions has this annoying quirk where it adds `width` and
`height` to keyframes automatically when generating keyframes even when
it's not needed. This causes them to deopt from running on the
compositor thread in both Chrome and Safari. @bramus has a [good article
on
it](https://www.bram.us/2025/02/07/view-transitions-applied-more-performant-view-transition-group-animations/).

In React we can automatically rewrite the keyframes when we're starting
a View Transition to drop the `width` and `height` from the keyframes
when they have the same value and the same value as the pseudo element.

To compare it against the pseudo element we first apply the new
keyframes without the width/height and then read it back to see if it
has changed. For gestures, we have already cancelled the previous
animation so we can just read out from that.

DiffTrain build for [c0d151ce7e](https://github.com/facebook/react/commit/c0d151ce7ed9ebdcbcb7ea69c31d68b03b852d37)
2025-07-02 13:17:23 -07:00
kassens cd476cf847 Remove now dead argument from resolveClassComponentProps (#33682)
No longer used after https://github.com/facebook/react/pull/33648

DiffTrain build for [73aa744b70](https://github.com/facebook/react/commit/73aa744b7029556430f409ec3887a714940698ba)
2025-07-02 07:53:50 -07:00
kassens 6784e4efd6 Cleanup disableDefaultPropsExceptForClasses flag (#33648)
DiffTrain build for [602917c8cb](https://github.com/facebook/react/commit/602917c8cb521e6f9b8eae7070985e2a698fc0d0)
2025-07-01 12:59:32 -07:00
hoxyq a41d5941e6 fix: rename bottom stack frame (#33680)
`react-stack-bottom-frame` -> `react_stack_bottom_frame`.

This survives `@babel/plugin-transform-function-name`, but now frames
will be displayed as `at Object.react_stack_bottom_frame (...)` in V8.
Checks that were relying on exact function name match were updated to
use either `.indexOf()` or `.includes()`

For backwards compatibility, both React DevTools and Flight Client will
look for both options. I am not so sure about the latter and if React
version is locked.

DiffTrain build for [91d097b2c5](https://github.com/facebook/react/commit/91d097b2c588a0977a7a10ed12512dc8a34e3a5b)
2025-07-01 10:13:11 -07:00
sebmarkbage 7c4226a83a Special case printing Promises in Performance Track Properties (#33670)
Before:
<img width="266" alt="Screenshot 2025-06-30 at 8 32 23 AM"
src="https://github.com/user-attachments/assets/98aae5e1-4b2c-49bd-9b71-040b788c36ba"
/>

After:
<img width="342" alt="Screenshot 2025-06-30 at 8 39 17 AM"
src="https://github.com/user-attachments/assets/cd91c4a6-f6ae-4bec-9cd9-f42f4af468fe"
/>

DiffTrain build for [e9cab42ece](https://github.com/facebook/react/commit/e9cab42ece435ac3478ec85847e352177e596ae0)
2025-06-30 06:28:07 -07:00
sebmarkbage fd62043fd8 Include Component Props in Performance Track (#33655)
Similar to how we can include a Promise resolved value we can include
Component Props.

For now I left out props for Client Components for perf unless they
error. I'll try it for Client Components in general in a separate PR.

<img width="730" alt="Screenshot 2025-06-26 at 5 54 29 PM"
src="https://github.com/user-attachments/assets/f0c86911-2899-4b5f-b45f-5326bdbc630f"
/>
<img width="762" alt="Screenshot 2025-06-26 at 5 54 12 PM"
src="https://github.com/user-attachments/assets/97540d19-5950-4346-99e6-066af086040e"
/>

DiffTrain build for [d2a288febf](https://github.com/facebook/react/commit/d2a288febf61a1755b78ce98b3cb17dd412b81e3)
2025-06-27 05:51:37 -07:00
sebmarkbage 562aaeb636 [Flight] Log aborted await and component renders (#33641)
<img width="926" alt="Screenshot 2025-06-25 at 1 02 14 PM"
src="https://github.com/user-attachments/assets/1877d13d-5259-4cc4-8f48-12981e3073fe"
/>

The I/O entry doesn't show as aborted in the Server Request track
because technically it wasn't. The end time is just made up. It's still
going. It's not aborted until the abort signal propagates and if we do
get that signal wired up before it emits, it instead would show up as
rejected.

---------

Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>

DiffTrain build for [bb6c9d521e](https://github.com/facebook/react/commit/bb6c9d521e7f44eb9a9754a14cde62c8e6439e5e)
2025-06-25 13:39:33 -07:00
josephsavona 1796cb9a66 [compiler] Fix bug with reassigning function param in destructuring (#33624)
Closes #33577, a bug with ExtractScopeDeclarationsFromDestructuring and
codegen when a function param is reassigned.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33624).
* #33643
* #33642
* #33640
* #33625
* __->__ #33624

DiffTrain build for [9894c488e0](https://github.com/facebook/react/commit/9894c488e0d9a4d9759d80ba8666d4d094b894e9)
2025-06-25 11:24:29 -07:00
josephsavona 59b07a2562 [compiler] Consolidate HIRFunction return information (#33640)
We now have `HIRFunction.returns: Place` as well as `returnType: Type`.
I want to add additional return information, so as a first step i'm
consolidating everything under an object at `HIRFunction.returns:
{place: Place}`. We use the type of this place as the return type. Next
step is to add more properties to this object to represent things like
the return kind.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33640).
* #33643
* #33642
* __->__ #33640
* #33625
* #33624

DiffTrain build for [123ff13b19](https://github.com/facebook/react/commit/123ff13b193cd361a61b99056dd08f2decd7f55d)
2025-06-25 11:18:30 -07:00
josephsavona ab9cbb66a5 [compiler] Avoid empty switch cases (#33625)
Small cosmetic win, found this when i was looking at some code
internally with lots of cases that all share the same logic. Previously,
all the but last one would have an empty block.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33625).
* #33643
* #33642
* #33640
* __->__ #33625
* #33624

DiffTrain build for [e130c08b06](https://github.com/facebook/react/commit/e130c08b06470b5fc4ec8095310d19e782924427)
2025-06-25 11:16:30 -07:00
sebmarkbage 608544bc6f [Fizz] Push a stalled await from debug info to the ownerStack/debugTask (#33634)
If an aborted task is not rendering, then this is an async abort.
Conceptually it's as if the abort happened inside the async gap. The
abort reason's stack frame won't have that on the stack so instead we
use the owner stack and debug task of any halted async debug info.

One thing that's a bit awkward is that if you do have a sync abort and
you use that error as the "reason" then that thing still has a sync
stack in a different component. In another approach I was exploring
having different error objects for each component but I don't think
that's worth it.

DiffTrain build for [cee7939b00](https://github.com/facebook/react/commit/cee7939b0017ff58230e19663c22393bfd9025ef)
2025-06-25 08:20:39 -07:00
sebmarkbage 3d92b7b028 [Flight] Emit Partial Debug Info if we have any at the point of aborting a render (#33632)
When we abort a render we don't really have much information about the
task that was aborted. Because before a Promise resolves there's no
indication about would have resolved it. In particular we don't know
which I/O would've ultimately called resolve().

However, we can at least emit any information we do have at the point
where we emit it. At the least the stack of the top most Promise.

Currently we synchronously flush at the end of an `abort()` but we
should ideally schedule the flush in a macrotask and emit this debug
information right before that. That way we would give an opportunity for
any `cacheSignal()` abort to trigger rejections all the way up and those
rejections informs the awaited stack.

---------

Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>

DiffTrain build for [e67b4fe22e](https://github.com/facebook/react/commit/e67b4fe22e0c3c267303ee6737aec1db48055022)
2025-06-24 13:43:22 -07:00
josephsavona 57e4b48f33 [compiler] New inference repros/fixes (#33584)
Substantially improves the last major known issue with the new inference
model's implementation: inferring effects of function expressions. I
knowingly used a really simple (dumb) approach in
InferFunctionExpressionAliasingEffects but it worked surprisingly well
on a ton of code. However, investigating during the sync I saw that we
the algorithm was literally running out of memory, or crashing from
arrays that exceeded the maximum capacity. We were accumluating data
flow in a way that could lead to lists of data flow captures compounding
on themselves and growing very large very quickly. Plus, we were
incorrectly recording some data flow, leading to cases where we reported
false positive "can't mutate frozen value" for example.

So I went back to the drawing board. InferMutationAliasingRanges already
builds up a data flow graph which it uses to figure out what values
would be affected by mutations of other values, and update mutable
ranges. Well, the key question that we really want to answer for
inferring a function expression's aliasing effects is which values
alias/capture where. Per the docs I wrote up, we only have to record
such aliasing _if they are observable via mutations_. So, lightbulb:
simulate mutations of the params, free variables, and return of the
function expression and see which params/free-vars would be affected!
That's what we do now, giving us precise information about which such
values alias/capture where. When the "into" is a param/context-var we
use Capture, iwhen the destination is the return we use Alias to be
conservative.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33584).
* #33626
* #33625
* #33624
* __->__ #33584

DiffTrain build for [94cf60bede](https://github.com/facebook/react/commit/94cf60bede7cd6685e07a4374d1e3aa90445130b)
2025-06-24 10:08:41 -07:00