Commit Graph
21773 Commits
Author SHA1 Message Date
Joseph Savona cc21616c8c Merge 67c687ccda into sapling-pr-archive-josephsavona 2025-10-03 08:36:29 -07:00
Joe Savona 67c687ccda Update readme for eprh 2025-10-03 08:36:21 -07:00
Eugene Choi 0eebd37041 [playground] Config panel quality fixes (#34611)
Fixed two small issues with the config panel in the compiler playground:
1. Object descriptions were being confined in the config box and most of
it would not be visible upon hover
2. Changed it so that "Applied Configs" would only display a valid set
of configs, rather than switching between "Invalid Configs" and the set
of options. This would be less visually jarring for users as the Output
panel already displays errors. Additionally, if users want to see the
list of config options but have a currently broken config, they would
previously not know how to fix it.

Object hover before: 
<img width="702" height="481" alt="Screenshot 2025-09-26 at 10 41 03 AM"
src="https://github.com/user-attachments/assets/b2ddec2f-16ba-41a1-be1f-96211f46764c"
/>
Hover after:
<img width="702" height="481" alt="Screenshot 2025-09-26 at 10 40 37 AM"
src="https://github.com/user-attachments/assets/dc713a22-4710-46a8-a5d7-485060cc9074"
/>

Applied Configs always displays the last valid set of configs:


https://github.com/user-attachments/assets/2fb9232f-7388-4488-9b7a-bb48bf09e4ca
2025-10-03 10:52:36 -04:00
Jack Pope 74dee8ef64 Add getClientRects to fabric fragment instance (#34545)
Stacked on #34544 

We only have getBoundingClientRect available from RN currently. This
should work as a substitute for this case because the equivalent of
multi-rect elements in RN is a nested Text component. We only include
the rects of top-level host components here so we can assume that
calling getBoundingClientRect on each child is the same result.

Tested in react-native with Fantom.
2025-10-03 09:54:33 -04:00
Jack Pope e866b1d1e9 Add getRootNode to fabric fragment instance (#34544)
Stacked on #34533 for root fragment handling

This is the same approach as DOM, where we call getRootNode on the
parent.
    
Tests are in react-native using Fantom.
2025-10-03 09:48:37 -04:00
lauren 19f65ff179 [eprh] Remove NoUnusedOptOutDirectives (#34703)
This rule was a leftover from a while ago and doesn't actually lint
anything useful. Specifically, you get a lint error if you try to opt
out a component that isn't already bailing out. If there's a bailout the
compiler already safely skips over it, so adding `'use no memo'` there
is unnecessary.

Fixes #31407

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34703).
* __->__ #34703
* #34700
2025-10-02 19:19:01 -04:00
lauren 26b177bc5e [eprh] Fix recommended config for flat config compatibility (#34700)
Previously, the `recommended` config used the legacy ESLint format
(plugins as an array of strings). This causes errors when used with
ESLint v9's `defineConfig()` helper. This was following [eslint's own
docs](https://eslint.org/docs/latest/extend/plugins#backwards-compatibility-for-legacy-configs):

> With this approach, both configuration systems recognize
"recommended". The old config system uses the recommended key while the
current config system uses the flat/recommended key. The defineConfig()
helper first looks at the recommended key, and if that is not in the
correct format, it looks for the flat/recommended key. This allows you
an upgrade path if you’d later like to rename flat/recommended to
recommended when you no longer need to support the old config system.

However,
[`isLegacyConfig()`](https://github.com/eslint/rewrite/blob/main/packages/config-helpers/src/define-config.js#L73-L81)
(also see
[`eslintrcKeys`](https://github.com/eslint/rewrite/blob/main/packages/config-helpers/src/define-config.js#L24-L35))
function doesn't check for the `plugins` key, so our config was
incorrectly treated as flat config despite being in legacy format.

This PR fixes the issue, along with a few other fixes combined:

1. Convert `recommended` to flat config format
2. Separate basic rules (exhaustive-deps, rules-of-hooks) from compiler
rules
3. Add `recommended-latest-legacy` config for non-flat config users who
want all recommended rules (including compiler rules)
4. Adding more types for the exported config

Our shipped presets in 6.x.x will essentially be:
- `recommended-legacy`: legacy (non-flat), with basic rules only
- `recommended-latest-legacy`: legacy (non-flat), all rules (basic +
compiler)
- `flat/recommended`: flat, basic rules only (now the same as
recommended, but to avoid making a breaking change we'll just keep it
around in 6.x.x)
- `recommended-latest`: flat, all rules (basic + compiler)
- `recommended`: flat, basic rules only

In the next breaking release 7.x.x, we will collapse down the presets
into three:

- `recommended-legacy`: all recommended rules
- `recommended`: all recommended rules
- `recommended-experimental`: all recommended rules + new bleeding edge
experimental rules

Closes #34679

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34700).
* #34703
* __->__ #34700
2025-10-02 18:52:52 -04:00
lauren 056a586928 [fixtures] Update eslint fixture lockfiles (#34699)
Updates the eslint fixture lockfiles.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34699).
* #34703
* #34700
* __->__ #34699
* #34675
2025-10-02 18:42:43 -04:00
lauren 5cc3d49f72 [eprh] Add compiler rules to recommended preset (#34675)
Adds back the compiler rules to the recommended preset, intended for the
next release.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34675).
* #34703
* #34700
* #34699
* __->__ #34675
2025-10-02 18:42:30 -04:00
Eugene Choi 289f070d64 [playground] Improve DiffEditor scrollbar + view (#34691)
The previous DiffEditor view of the playground looked broken and not
cohesive. There would be parts of the scrollbar appearing on the left
side for some reason, along with two scrollbars on the right side. This
PR makes the DiffEditor look more cohesive.

Previous:


https://github.com/user-attachments/assets/1aa1c775-5940-43b2-a75a-9b46452fb78b

After:


https://github.com/user-attachments/assets/b5c04998-6a6c-4b52-b3c5-b2fef21729e0
2025-10-02 17:41:29 -04:00
Sebastian "Sebbie" Silbermann 6a8a8ef326 [Flight] Add <Activity> (#34697) 2025-10-02 23:14:52 +02:00
Sebastian Markbåge f89ed71ddf [DevTools] Track whether to auto select when new timeline entries come on (#34698)
This auto updates to select the last entry in the timeline until we make
the first selection. That way when new content loads in, we show the
last timeline of what is visible.
2025-10-02 17:06:52 -04:00
Josh Story 7d9f876cbc [Fizz] Detatch boundary after flushing segment with boundary (#34694)
When we flush a Suspense boundary we might not flush the fallback
segment, it might only flush a placeholder instead. In this case the
segment can flush again but we do not want to flush the boundary itself
a second time. We now detach the boundary after flushing it.

better solution to: https://github.com/facebook/react/pull/34668
2025-10-02 13:21:57 -07:00
Sebastian "Sebbie" Silbermann df3562dc7f Fix DevTools regression tests (#34696) 2025-10-02 21:52:50 +02:00
Sebastian Markbåge b56907db51 [DevTools] Show Props as Read-only for Suspense/Activity but below (#34695)
Somehow my last commit didn't make it in #34630.
2025-10-02 15:29:38 -04:00
Sebastian Markbåge c825f03067 [DevTools] Hide State and Props in the Sidebar for Suspense (#34630)
We're showing too much noise in the side-panel when selecting a Suspense
boundary. The interesting thing to see directly is the "Suspended by".

The "props" are mostly useless because the `"name"` prop is already in
the tree. I'm now also showing it in the title bar of the selected
element panel. The "children" and "fallback" props are just the thing
that you can see in the tree view anyway.

The "state" is this weird section with just one field in it, which we
already have duplicated in the top toolbar as well. We can just delete
this. I make sure to show the icon and a "suspended..." section while
the boundary is still loading but now yet resuspended by force
suspending.

While still loading:

<img width="600" height="193" alt="Screenshot 2025-09-27 at 11 54 37 PM"
src="https://github.com/user-attachments/assets/1c3f3a96-46e0-4b11-806f-032569c7d5b5"
/>

After loading:

<img width="602" height="266" alt="Screenshot 2025-09-27 at 11 54 53 PM"
src="https://github.com/user-attachments/assets/c43cc4cb-036f-4ced-9b0d-226c6320cd76"
/>

Resuspended after loading:

<img width="602" height="300" alt="Screenshot 2025-09-27 at 11 55 07 PM"
src="https://github.com/user-attachments/assets/0be01735-48a7-47dc-b5cf-e72ec71e0148"
/>
2025-10-02 15:18:41 -04:00
Sebastian Markbåge 2e68dc76a4 [DevTools] Give a distinct color to the root (#34690)
Stacked on #34654.

The root is special since it represents "Initial Paint" (or a
"Transition" when an Activity is selected). This gives it a different
color in the timeline as well as gives it an outline that's clickable.
Hovering the timeline now shows "Initial Paint" or "Suspense".

Also made the cursor a pointer to invite you to try to click things and
some rounded corners.

<img width="1219" height="420" alt="Screenshot 2025-10-02 at 1 26 38 PM"
src="https://github.com/user-attachments/assets/12451f93-8917-4f3b-8f01-930129e5fc13"
/>

<img width="1217" height="419" alt="Screenshot 2025-10-02 at 1 26 54 PM"
src="https://github.com/user-attachments/assets/02b5e94c-3fbe-488d-b0f2-225b73578608"
/>

<img width="1215" height="419" alt="Screenshot 2025-10-02 at 1 27 24 PM"
src="https://github.com/user-attachments/assets/c24e8861-e74a-4ccc-8643-ee9d04bef43c"
/>

<img width="1216" height="419" alt="Screenshot 2025-10-02 at 1 27 10 PM"
src="https://github.com/user-attachments/assets/d5cc2b62-fa64-41bf-b485-116b1cd67467"
/>
2025-10-02 14:37:03 -04:00
Sebastian Markbåge ced705d756 [DevTools] Always include the root in the timeline and select it by default (#34654)
Rebased on #34454.

Always include the root in the timeline even if it has no unique
suspenders, since even if it won't suspend, we have to be able to see
that and step to one step before the next boundary to see the first
boundary that does suspend in its fallback state.

Also, if there's no current selection on initial mount, select the last
entry in the timeline. We usually do this with `selectedSuspenseID` but
that doesn't happen on initial load. So this does it on initial load if
nothing else is selected by then. That way when you reload you get the
initial root selected.

There's a problem here because we should really use one source of truth
and `selectedSuspenseID` doesn't really do anything now. Either it
should be its separate source of truth and you can't show components in
the side-panel or it should be derived from the other state.

If it's derived, once there's a selection, e.g. in the root, then even
if new timelines load it will never change but that's probably a good
thing.
2025-10-02 14:20:02 -04:00
Joseph Savona 70b52beca6 [compiler] @enablePreserveExistingMemoizationGuarantees on by default (#34689)
This enables `@enablePreserveExistingMemoizationGuarantees` by default.
As of the previous PR (#34503), this mode now enables the following
behaviors:

- Treating variables referenced within a `useMemo()` or `useCallback()`
as "frozen" (immutable) as of the start of the call. Ie, the compiler
will assume that the values you reference are not mutated by the body of
the useMemo, not are they mutated later. Directly modifying them (eg
`var.property = true`) will be an error.
- Similarly, the results of the useMemo/useCallback are treated as
frozen (immutable) after the call.

These two rules match the behavior for other hooks: this means that
developers will see similar behavior to swapping out `useMemo()` for a
custom `useMyMemo()` wrapper/alias.

Additionally, as of #34503 the compiler uses information from the manual
dependencies to know which variables are non-nullable. Even if a useMemo
block conditionally accesses a nested property — `if (cond) { log(x.y.z)
}` — where the compiler would not usually know that `x` is non-nullable,
if the user specifies `x.y.z` as a manual dependency then the compiler
knows that `x` and `x.y` are non-nullable and can infer a more precise
dependency.

Finally, this mode also ensures that we always memoize function calls
that return primitives. See #34343 for more details.

For now, I've explicitly opted out of this feature in all test fixtures
where the behavior changed.
2025-10-02 10:25:00 -07:00
Sebastian "Sebbie" Silbermann 4a28227960 [DevTools] Inspect the Initial Paint when inspecting a Root (#34454) 2025-10-02 19:18:15 +02:00
Sebastian "Sebbie" Silbermann e4a27db283 [DevTools] Defer Suspense tab to 19.3.0-canary (#34688) 2025-10-02 19:13:52 +02:00
Joseph Savona 1a61287d0e Merge ae3444675f into sapling-pr-archive-josephsavona 2025-10-02 09:54:07 -07:00
Joe Savona ae3444675f [compiler] @enablePreserveExistingMemoizationGuarantees on by default
This enables `@enablePreserveExistingMemoizationGuarantees` by default. As of the previous PR (#34503), this mode now enables the following behaviors:

- Treating variables referenced within a `useMemo()` or `useCallback()` as "frozen" (immutable) as of the start of the call. Ie, the compiler will assume that the values you reference are not mutated by the body of the useMemo, not are they mutated later. Directly modifying them (eg `var.property = true`) will be an error.
- Similarly, the results of the useMemo/useCallback are treated as frozen (immutable) after the call.

These two rules match the behavior for other hooks: this means that developers will see similar behavior to swapping out `useMemo()` for a custom `useMyMemo()` wrapper/alias.

Additionally, as of #34503 the compiler uses information from the manual dependencies to know which variables are non-nullable. Even if a useMemo block conditionally accesses a nested property — `if (cond) { log(x.y.z) }` — where the compiler would not usually know that `x` is non-nullable, if the user specifies `x.y.z` as a manual dependency then the compiler knows that `x` and `x.y` are non-nullable and can infer a more precise dependency.

Finally, this mode also ensures that we always memoize function calls that return primitives. See #34343 for more details.

For now, I've explicitly opted out of this feature in all test fixtures where the behavior changed.
2025-10-02 09:53:51 -07:00
Joseph Savona 57d5a59748 [compiler] enablePreserveMemo treats manual deps as non-nullable (#34503)
The `@enablePreserveExistingMemoizationGuarantees` mode can still fail
to preserve manual memoization due to mismtached dependencies.
Specifically, where the user's dependencies are more precise than the
compiler infers bc the compiler is being conservative about what might
be nullable. In this mode though we're intentionally using information
from the manual memoization and can also rely on the deps as a signal
for what's non-nullable.

The idea of the PR is that we treat manual memo deps just like other
inferred-as-non-nullable objects during PropagateScopeDeps. We're
careful to not treat the full path as non-nullable, only up to the last
property index. So `x.y.z` as a manual dep treats `x` and `x.y` as
non-nullable, allowing us to preserve a conditional dependency on
`x.y.z`.

Optionals within manual dependencies are a bit trickier and aren't
handled yet, but hopefully that's less common and something we can
improve in a follow-up. Not handling them just means that developers may
hit false positives on validating existing memoization if they use
optional chains in manual dependencies.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34503).
* #34689
* __->__ #34503
2025-10-02 09:48:52 -07:00
Joseph Savona abdaf09644 Merge 26111cadff into sapling-pr-archive-josephsavona 2025-10-02 09:47:35 -07:00
Joe Savona 26111cadff [compiler] @enablePreserveExistingMemoizationGuarantees on by default
This enables `@enablePreserveExistingMemoizationGuarantees` by default. As of the previous PR (#34503), this mode now enables the following behaviors:

- Treating variables referenced within a `useMemo()` or `useCallback()` as "frozen" (immutable) as of the start of the call. Ie, the compiler will assume that the values you reference are not mutated by the body of the useMemo, not are they mutated later. Directly modifying them (eg `var.property = true`) will be an error.
- Similarly, the results of the useMemo/useCallback are treated as frozen (immutable) after the call.

These two rules match the behavior for other hooks: this means that developers will see similar behavior to swapping out `useMemo()` for a custom `useMyMemo()` wrapper/alias.

Additionally, as of #34503 the compiler uses information from the manual dependencies to know which variables are non-nullable. Even if a useMemo block conditionally accesses a nested property — `if (cond) { log(x.y.z) }` — where the compiler would not usually know that `x` is non-nullable, if the user specifies `x.y.z` as a manual dependency then the compiler knows that `x` and `x.y` are non-nullable and can infer a more precise dependency.

Finally, this mode also ensures that we always memoize function calls that return primitives. See #34343 for more details.

For now, I've explicitly opted out of this feature in all test fixtures where the behavior changed.
2025-10-02 09:47:24 -07:00
Sebastian "Sebbie" Silbermann bc828bf6e3 [DevTools] Recommend React Performance tracks if supported when Timeline profiler is not supported (#34684) 2025-10-02 18:33:50 +02:00
Joseph Savona 1e383b1929 Merge 8cca076ad9 into sapling-pr-archive-josephsavona 2025-10-02 09:19:36 -07:00
Joe Savona 8cca076ad9 [compiler] ValidateExhaustiveDeps disallows unnecessary non-reactive deps
Just to be consistent, we disallow unnecessary deps even if they're known to be non-reactive.
2025-10-02 09:19:24 -07:00
Joe Savona 3c0ea0c7a6 [compiler] Auto-fix for non-exhaustive deps
Records more information in DropManualMemoization so that we know the full span of the manual dependencies array (if present). This allows ValidateExhaustiveDeps to include a suggestion with the correct deps.
2025-10-02 09:19:22 -07:00
Joe Savona 5809d69de3 [compiler] Implement exhaustive dependency checking for manual memoization
The compiler currently drops manual memoization and rewrites it using its own inference. If the existing manual memo dependencies has missing or extra dependencies, compilation can change behavior by running the computation more often (if deps were missing) or less often (if there were extra deps). We currently address this by relying on the developer to use the ESLint plugin and have `eslint-disable-next-line react-hooks/exhaustive-deps` suppressions in their code. If a suppression exists, we skip compilation.

But not everyone is using the linter! Relying on the linter is also imprecise since it forces us to bail out on exhaustive-deps checks that only effect (ahem) effects — and while it isn't good to have incorrect deps on effects, it isn't a problem for compilation.

So this PR is a rough sketch of validating manual memoization dependencies in the compiler. Long-term we could use this to also check effect deps and replace the ExhaustiveDeps lint rule, but for now I'm focused specifically on manual memoization use-cases. If this works, we can stop bailing out on ESLint suppressions, since the compiler will implement all the appropriate checks (we already check rules of hooks).
2025-10-02 09:19:21 -07:00
Joe Savona 2d357eb9be [compiler] enablePreserveMemo treats manual deps as non-nullable
The `@enablePreserveExistingMemoizationGuarantees` mode can still fail to preserve manual memoization due to mismtached dependencies. Specifically, where the user's dependencies are more precise than the compiler infers bc the compiler is being conservative about what might be nullable. In this mode though we're intentionally using information from the manual memoization and can also rely on the deps as a signal for what's non-nullable.

The idea of the PR is that we treat manual memo deps just like other inferred-as-non-nullable objects during PropagateScopeDeps. We're careful to not treat the full path as non-nullable, only up to the last property index. So `x.y.z` as a manual dep treats `x` and `x.y` as non-nullable, allowing us to preserve a conditional dependency on `x.y.z`.

Optionals within manual dependencies are a bit trickier and aren't handled yet, but hopefully that's less common and something we can improve in a follow-up. Not handling them just means that developers may hit false positives on validating existing memoization if they use optional chains in manual dependencies.
2025-10-02 09:19:19 -07:00
Joe Savona a56d634dce merge commit for archive created by Sapling 2025-10-02 09:14:35 -07:00
Joe Savona b4b3863b8f [compiler] ValidateExhaustiveDeps disallows unnecessary non-reactive deps
Just to be consistent, we disallow unnecessary deps even if they're known to be non-reactive.
2025-10-02 09:14:09 -07:00
Joe Savona 767ae4970a [compiler] Auto-fix for non-exhaustive deps
Records more information in DropManualMemoization so that we know the full span of the manual dependencies array (if present). This allows ValidateExhaustiveDeps to include a suggestion with the correct deps.
2025-10-02 09:14:09 -07:00
Joe Savona 93696d8d6c [compiler] Implement exhaustive dependency checking for manual memoization
The compiler currently drops manual memoization and rewrites it using its own inference. If the existing manual memo dependencies has missing or extra dependencies, compilation can change behavior by running the computation more often (if deps were missing) or less often (if there were extra deps). We currently address this by relying on the developer to use the ESLint plugin and have `eslint-disable-next-line react-hooks/exhaustive-deps` suppressions in their code. If a suppression exists, we skip compilation.

But not everyone is using the linter! Relying on the linter is also imprecise since it forces us to bail out on exhaustive-deps checks that only effect (ahem) effects — and while it isn't good to have incorrect deps on effects, it isn't a problem for compilation.

So this PR is a rough sketch of validating manual memoization dependencies in the compiler. Long-term we could use this to also check effect deps and replace the ExhaustiveDeps lint rule, but for now I'm focused specifically on manual memoization use-cases. If this works, we can stop bailing out on ESLint suppressions, since the compiler will implement all the appropriate checks (we already check rules of hooks).
2025-10-02 09:14:09 -07:00
Joe Savona 9dac3689dc [compiler][rfc] enablePreserveMemo treats manual deps as non-nullable
The `@enablePreserveExistingMemoizationGuarantees` mode can still fail to preserve manual memoization due to mismtached dependencies. Specifically, where the user's dependencies are more precise than the compiler infers bc the compiler is being conservative about what might be nullable. In this mode though we're intentionally using information from the manual memoization and can also rely on the deps as a signal for what's non-nullable.

The idea of the PR — which I need to test with optional chains still — is that we treat manual memo deps just like other inferred-as-non-nullable objects during PropagateScopeDeps. We're careful to not treat the full path as non-nullable, only up to the last property index. So `x.y.z` as a manual dep treats `x.y` as non-nullable, allowing us to preserve a conditional dependency on `x.y.z`.

I still need to handle optionals and think about what should happen for manual deps like `x?.y?.z`.
2025-10-02 09:14:09 -07:00
Sebastian "Sebbie" Silbermann a757cb7667 Fix DevTools fixture crash due to usage of renamed APIs (#34682) 2025-10-02 14:43:02 +02:00
Sebastian Markbåge d74f061b69 [Fiber] Clean up ViewTransition when it fails to start (#34676)
The View Transition docs were unclear about this but apparently the
`finished` promise never settles if the animation never started. So if
there's an error that rejects the `ready` promise, we'll never run the
clean up which can cause it to stall.

Fixes #34662.

However, ultimately that is caused by Chrome stalling our default
`onDefaultTransitionIndicator` but it should be unblocked after 10
seconds, not a minute.
2025-10-01 21:58:13 -04:00
Eugene Choi f7254efc5c [playground] Persist open tabs on compiler error (#34673)
This change allows it so that tabs that were open before a compiler
error are automatically opened again when the error is resolved. Quality
of life change for those especially working with the advanced view of
the playground.


https://github.com/user-attachments/assets/cd2dc117-e6fc-4f57-a08f-259757c4f5e8
2025-10-01 21:26:16 -04:00
Sebastian "Sebbie" Silbermann 79ca5ae855 Bump next prerelease version numbers (#34674) 2025-10-02 00:31:55 +02:00
lauren ae74234eae [eprh] Allow compiler rules to be opted-in but not in the preset (#34672)
Follow up to #34649. This adds the compiler rules back so they can be
opted-in 6.1.0, but aren't included in the presets as that would be a
breaking change.
v19.2.0
2025-10-01 17:05:42 -04:00
Sebastian "Sebbie" Silbermann 861811347b Bump scheduler version (#34671)
The canaries have been published depending on 0.27-canary. Bumping
scheduler just in case to be sure.
2025-10-01 22:45:31 +02:00
Ricky 7f9d99749c Land enableHiddenSubtreeInsertionEffectCleanup (#34372)
Fixes a bug where insertion effects were not cleaned up if a hidden
Activity is unmounted.
2025-10-01 16:31:30 -04:00
aef8b1b562 19.2 changelog (#34655)
Co-authored-by: Jack Pope <jackpope1@gmail.com>
Co-authored-by: Rick Hanlon <rickhanlonii@meta.com>
2025-10-01 22:11:02 +02:00
Jack Pope 67e24bc527 Improve lint error messages for useEffectEvent (#34669)
Called Before:

> `logEvent` is a function created with React Hook "useEffectEvent", and
can only be called from the same component.

Called After:

> `logEvent` is a function created with React Hook "useEffectEvent", and
can only be called from Effects and Effect Events in the same component.

Referenced Before:

> `logEvent` is a function created with React Hook "useEffectEvent", and
can only be called from the same component. They cannot be assigned to
variables or passed down.

Referenced After:

> `logEvent` is a function created with React Hook "useEffectEvent", and
can only be called from Effects and Effect Events in the same component.
It cannot be assigned to a variable or passed down.
2025-10-01 15:17:08 -04:00
Sebastian Markbåge bbc2d596fa Traverse down an updated tree even if it has no passive effects in profiling mode (#34667)
We need this to be able to log the renders that happened inside.

This is the same thing we do here but for the offscreen special cases:


https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberCommitWork.js#L3452-L3457
2025-10-01 13:45:37 -04:00
Sebastian "Sebbie" Silbermann 1bd1f01f2a Ship partial-prerendering APIs to Canary (#34633) 2025-10-01 18:22:30 +02:00
Sebastian "Sebbie" SilbermannandRuslan Lesiutin 548235db10 Enable React performance tracks in Canary (#34665)
Co-authored-by: Ruslan Lesiutin <28902667+hoxyq@users.noreply.github.com>
2025-10-01 18:13:15 +02:00
Sebastian "Sebbie" Silbermann 1f460f31ee [DevTools] Fix host instance highlighting (#34661) 2025-10-01 17:32:34 +02:00