Commit Graph
19256 Commits
Author SHA1 Message Date
hylinzandGitHub d193f09f71 Punctuation & correcting spelling mistakes (#30592) 2024-08-09 14:53:53 -07:00
Joe Savona d0ad6bcb0e [compiler][be] Remove completed todo comment
We made block types explicit a long time ago, this comment is super stale

ghstack-source-id: 810a34bb4c14a3f4541003db23ffb7ad91aecc8c
Pull Request resolved: https://github.com/facebook/react/pull/30633
2024-08-09 14:11:01 -07:00
Joe Savona 3655fb7e5f [compiler][be] Cleanup class naming in PromoteUsedTemporaries
I forgot to clean this up before landing #30573.

ghstack-source-id: 2141471912e410aa12545dcf7989f45447007ba9
Pull Request resolved: https://github.com/facebook/react/pull/30632
2024-08-09 14:11:01 -07:00
Jan KassensandGitHub 023244724f [ci] fix path in compiler_typescript.yml (#30651)
The path was incorrect, so the job didn\t run on changes to it.
2024-08-09 13:21:24 -04:00
Mofei Zhang 0020c6810a [compiler][ez] Option to bail out on blocklisted imports
ghstack-source-id: 540d154b25e49a83683a05fc9326dbd0ad59a6bd
Pull Request resolved: https://github.com/facebook/react/pull/30643
2024-08-09 09:10:01 -07:00
Mofei Zhang 193b6b2db9 [compiler][be] Clean up compilation skipping logic in Program
ghstack-source-id: fe2c81de9d4f41a787c690b722cbcff55eb18ac3
Pull Request resolved: https://github.com/facebook/react/pull/30642
2024-08-09 09:10:01 -07:00
Mofei Zhang 11a6e1ca95 [compiler][ez] Add types for Math.min, recursive global
ghstack-source-id: 9940b8f96eec3fb2b411af8a7c92d93aae6da85e
Pull Request resolved: https://github.com/facebook/react/pull/30641
2024-08-09 09:10:01 -07:00
Sebastian MarkbågeandGitHub 122ae7b1cd [DevTools] Build up DevTools Instance Shadow Tree (#30625)
This is the beginning of a refactor of the DevTools Fiber backend. The
new approach is basically that we listen to each commit from Fiber and
traverse the tree - building up a filtered shadow tree. Then we send
diffs based on that tree and perform our own operations against that
instead of using Fibers as the source of truth.

Fiber diffs Elements -> Fibers. The backend diffs Fibers ->
DevToolsInstances as a side-effect it sends deltas to the front end.

This makes the algorithm resilient to a different Fiber implementation
that doesn't use pairs of Fibers (alternates) but instead stateless new
clones each time. In that world we can't treat Fibers as instances. They
can hold onto instances but they're not necessarily 1:1 themselves.

The same thing also applies to Server Components that don't have their
own instances.

The algorithm is more or less the same as React's reconciliation in
ReactChildFiber itself. However, we do a mutable update of the tree as
we go. We also cheat a bit here in the first version in that we still
have fiberToFiberInstance map and alternate which makes reorders easier.
Further down we could do the reorders by adding the previous set to a
temporary map like ChildFiber does but only if they're not already in
order.

This first bit is just about making sure that we produce correct trees.
We have fairly good test coverage already of that already.

In the next few follow ups I'll start simplifying the rest of the logic
by taking advantage of the new tree.
2024-08-08 12:44:35 -04:00
Jan KassensandGitHub 4ce558098d [compiler] remove duplicate root files (#30639)
These files are duplicates from the root from a time when React Compiler
was in a different repo.
2024-08-08 12:42:45 -04:00
Sathya Gunsasekaran 387faa4b08 [compiler] Add context callee import if required
Previously the compiler would add an import for the specified context
callee even if the context access was not lowered, leading to unused
imports.

This PR tracks if lowering has happened and adds the import only when
necessary.

ghstack-source-id: 6ad794da41116e1034783b6c4a58fbfe7790343e
Pull Request resolved: https://github.com/facebook/react/pull/30628
2024-08-08 15:53:13 +01:00
Sathya Gunsasekaran f783577f97 [compiler] Rewrite useContext callee
If a value is specified for the LowerContextAccess environment config,
we rewrite the callee from 'useContext' to the specificed value.

This will allow us run an experiment internally.

ghstack-source-id: 00e161b988c8f8a1cf96efff8095f050cb534cc1
Pull Request resolved: https://github.com/facebook/react/pull/30612
2024-08-08 15:53:13 +01:00
Sol LeeandGitHub 02817bbeff [compiler] Replace for...in with for...of for array of strings (#30631)
closes https://github.com/facebook/react/issues/30627

Thanks!
2024-08-07 22:07:04 -07:00
Mofei Zhang 71d3f27374 [compiler] Patch ValidatePreserveMemo to bailout correctly for refs
ghstack-source-id: b9c13bf5f8
Pull Request resolved: https://github.com/facebook/react/pull/30603
2024-08-07 18:57:57 -07:00
Mofei Zhang e73698d6b3 [compiler] Remove transitive memo check in validatePreserveMemo
ghstack-source-id: 45521370e4
Pull Request resolved: https://github.com/facebook/react/pull/30630
2024-08-07 18:57:56 -07:00
Mofei Zhang 1399ed5eed [compiler][repro] False positives for ValidatePreserveMemo
ghstack-source-id: 7fa94fea86
Pull Request resolved: https://github.com/facebook/react/pull/30629
2024-08-07 18:57:56 -07:00
Mofei Zhang 8671f79c1e [compiler][repro] ValidatePreserveMemo x useRef bug
ghstack-source-id: 6ac5d58e97
Pull Request resolved: https://github.com/facebook/react/pull/30602
2024-08-07 18:57:56 -07:00
Mofei Zhang c0591efabb [compiler][be] Less ambiguous error messages for validateMemo bailout
ghstack-source-id: 312093ec74
Pull Request resolved: https://github.com/facebook/react/pull/30601
2024-08-07 18:57:56 -07:00
Sathya Gunsasekaran c5ee786450 [compiler] Add lowerContextAccess pass
*This is only for internal profiling, not intended to ship.*

This pass is intended to be used with https://github.com/facebook/react/pull/30407.

This pass synthesizes selector functions by collecting immediately
destructured context acesses. We bailout for other types of context
access.

This pass lowers context access to use a selector function by passing
the synthesized selector function as the second argument.

ghstack-source-id: 92d0f6ff2f
Pull Request resolved: https://github.com/facebook/react/pull/30548
2024-08-07 16:30:11 +01:00
Mike Vitousek 0dca2c9b7d [compiler][ez] Default to using flow suppressions
ghstack-source-id: b6592650e0
Pull Request resolved: https://github.com/facebook/react/pull/30622
2024-08-06 23:47:09 -07:00
Lauren Tan ecd7e2ff4c [ci] Fix incorrect tags being pushed for compiler releases
ghstack-source-id: 812e49333c
Pull Request resolved: https://github.com/facebook/react/pull/30620
2024-08-06 17:27:27 -04:00
Lauren Tan 7db05844e3 [ci] Fix dist-tag command
ghstack-source-id: bdbcc12b28
Pull Request resolved: https://github.com/facebook/react/pull/30619
2024-08-06 15:35:38 -04:00
Lauren Tan 86c1380f59 [final] Actually publish packages to npm
ghstack-source-id: 78a358a81726f1e9898be7f46de23e80005b5bfd
Pull Request resolved: https://github.com/facebook/react/pull/30618
2024-08-06 15:12:03 -04:00
Joe Savona 4a8b5b4da1 [compiler] Stay in SSA form through entire pipeline
This PR updates to use SSA form through the entire compilation pipeline. This means that in both HIR form and ReactiveFunction form, `Identifier` instances map 1:1 to `IdentifierId` values. If two identifiers have the same IdentifierId, they are the same instance. What this means is that all our passes can use this more precise information to determine if two particular identifiers are not just the same variable, but the same SSA "version" of that variable.

However, some parts of our analysis really care about program variables as opposed to SSA versions, and were relying on LeaveSSA to reset identifiers such that all Identifier instances for a particular program variable would have the same IdentifierId (though not necessarily the same Identifier instance). With LeaveSSA removed, those analysis passes can now use DeclarationId instead to uniquely identify a program variable.

Note that this PR surfaces some opportunties to improve edge-cases around reassigned values being declared/reassigned/depended-upon across multiple scopes. Several passes could/should use IdentifierId to more precisely identify exactly which values are accessed - for example, a scope that reassigns `x` but doesn't use `x` prior to reassignment doesn't have to take a dependency on `x`. But today we take a dependnecy.

My approach for these cases was to add a "TODO LeaveSSA" comment with notes and the name of the fixture demonstrating the difference, but to intentionally preserve the existing behavior (generally, switching to use DeclarationId when IdentifierId would have been more precise).

Beyond updating passes to use DeclarationId instead of Identifier/IdentifierId, the other change here is to extract out the remaining necessary bits of LeaveSSA into a new pass that rewrites InstructionKind (const/let/reassign/etc) based on whether a value is actually const or has reassignments and should be let.

ghstack-source-id: 69afdaee5fadf3fdc98ce97549da805f288218b4
Pull Request resolved: https://github.com/facebook/react/pull/30573
2024-08-06 12:02:50 -07:00
Joe Savona 0b2ae19602 [compiler] Add Identifier.declarationId
Adds `Identifier.declarationId` and the new `DeclarationId` (simulated) opaque type. DeclarationId allows uniquely identifying a variable in the original source, ie regardless of reassignments. This allows us to stay in SSA form throughout compilation (see next diff) while still being able to distinguish SSA versions (via IdentifierId) and non-SSA versions (DeclarationId).

ghstack-source-id: f2547a58aa7b30cea29fcfe23d5cb45583858a4e
Pull Request resolved: https://github.com/facebook/react/pull/30569
2024-08-06 12:02:50 -07:00
Lauren Tan b4c38b0786 [ci] Make compiler publish script runnable
ghstack-source-id: 309bda2bc3
Pull Request resolved: https://github.com/facebook/react/pull/30617
2024-08-06 14:59:19 -04:00
Lauren Tan bab698e1c6 [ci] Add prerelease nightly and manual script for compiler
Publishes the compiler packages on the same schedule as the React ones.
For now the manual script can only build from `main` but in the future
we can add support for building specific commits

ghstack-source-id: 66676c578b795b90bf3c5715be8900438868b6ee
Pull Request resolved: https://github.com/facebook/react/pull/30615
2024-08-06 14:48:33 -04:00
Lauren Tan 413486aab7 [compiler] Refactor release script
Updates the release script to publish tags as well as take a `--ci`
option

Test plan:
```
$ yarn npm:publish --debug --frfr

yarn run v1.22.22
$ node scripts/release/publish --debug --frfr
ℹ Preparing to publish (for real) [debug=true]
ℹ Building packages
✔ Successfully built babel-plugin-react-compiler
✔ Successfully built eslint-plugin-react-compiler
✔ Successfully built react-compiler-healthcheck
NPM 2-factor auth code: ******
✔ Wrote package.json for [email protected]

========== babel-plugin-react-compiler ==========

⠧ Publishing [email protected] to npm
+ [email protected]

✔ Successfully published babel-plugin-react-compiler to npm
ℹ dry-run: npm dist-tag add [email protected] experimental --otp=******
✔ Successfully pushed dist-tag experimental for babel-plugin-react-compiler to npm
✔ Wrote package.json for [email protected]

========== eslint-plugin-react-compiler ==========

⠹ Publishing [email protected] to npm
+ [email protected]

✔ Successfully published eslint-plugin-react-compiler to npm
ℹ dry-run: npm dist-tag add [email protected] experimental --otp=******
✔ Successfully pushed dist-tag experimental for eslint-plugin-react-compiler to npm
✔ Wrote package.json for [email protected]

========== react-compiler-healthcheck ==========

⠙ Publishing [email protected] to npm
+ [email protected]

✔ Successfully published react-compiler-healthcheck to npm
ℹ dry-run: npm dist-tag add [email protected] experimental --otp=******
✔ Successfully pushed dist-tag experimental for react-compiler-healthcheck to npm

✅ All done
✨  Done in 50.64s.
```

ghstack-source-id: 405cc001c2ab2adaad2bfe4f11fdb7fd28d7e2d1
Pull Request resolved: https://github.com/facebook/react/pull/30614
2024-08-06 14:48:33 -04:00
Lauren Tan c8111967dc [compiler] Remove sleep in manual release script
I originally added this prior to the compiler being OSS'd as a "just in
case" feature to panic cancel if something went wrong. Now that the
compiler is already launched this is unnecessary.

ghstack-source-id: dd17dc8a331657ce23c0cbc012ba967cfc3b9542
Pull Request resolved: https://github.com/facebook/react/pull/30613
2024-08-06 14:48:33 -04:00
Lauren Tan 0e06b111b7 Fix rust lints
ghstack-source-id: baf433a98a70d9105c8088d82e04a3d96783e9e6
Pull Request resolved: https://github.com/facebook/react/pull/30616
2024-08-06 14:48:32 -04:00
ArthurandGitHub b0a071ab1d [CI] fix the shared_lint cached key (#30609)
<!--
  Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.

Before submitting a pull request, please make sure the following is
done:

1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
  2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn test --debug --watch TestName`,
open `chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
  9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
  10. If you haven't already, complete the CLA.

Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->

## Summary

<!--
Explain the **motivation** for making this change. What existing problem
does the pull request solve?
-->

In the shared_lint,

for the first Prettier job, use `${{ runner.arch }}-${{ runner.os
}}-modules-${{ hashFiles('yarn.lock') }}` as the cache key.

For the following jobs, use `${{ runner.arch }}-${{ runner.os
}}-modules-${{ hashFiles('**/yarn.lock') }}` as the cache key.

Some of the jobs do not hit the cache if the hash does not match.

## How did you test this change?

<!--
Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes the user
interface.
How exactly did you verify that your PR solves the issue you wanted to
solve?
  If you leave this empty, your PR will very likely be closed.
-->

I run [act](https://github.com/nektos/act) locally to test it.
2024-08-06 14:43:10 -04:00
Jan KassensandGitHub a5c7499e70 Replace NodeJS 21 with 22 in devEngines field (#30598)
21 is EOL and 22 is stable now.

Homebrew installs 22 by default as well which is the practical reason
for me to update this.
2024-08-06 11:06:14 -04:00
Sathya Gunsasekaran c26b9ee0ec [compiler] Refactor createTemporaryPlace
Update createTemporaryPlace to use makeTemporary and also rename
makeTemporary to makeTemporaryIdentifier to make it less ambiguous.

ghstack-source-id: b5955d3d667064f2ccf7e633ab63df2269dc56fa
Pull Request resolved: https://github.com/facebook/react/pull/30585
2024-08-06 15:30:01 +01:00
Jan KassensandGitHub bca2058a3d Remove flag enableUseDeferredValueInitialArg (#30595)
This is enabled everywhere for a while and I don't think we'd be backing
this out of 19. Seems like it's good to clean up to me.
2024-08-05 11:25:05 -04:00
Greg BrimbleandGitHub 3a9c681b34 Fix typos in Turbopack configuration and in Node.js loader error messages (#30593)
<!--
  Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.

Before submitting a pull request, please make sure the following is
done:

1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
  2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn test --debug --watch TestName`,
open `chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
  9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
  10. If you haven't already, complete the CLA.

Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->

## Summary

Just fixing some copy-paste typos.

## How did you test this change?

Untested.
2024-08-05 10:11:39 -04:00
Ruslan LesiutinandGitHub 66f59428a5 chore[packages/react-devtools]: remove unused index.js (#30579)
This is unused. See
https://github.com/facebook/react/pull/30533#discussion_r1700455529.

Ran a fresh build of `react-devtools` via `yarn start` in
`packages/react-devtools` to validate that it is still works with React
Native.
2024-08-05 07:53:08 +01:00
Sebastian MarkbågeandGitHub 9e73ddfb2d [Flight] Warn for keyless fragments in an array (#30588)
Conceptually this is the same as rendering this as if it was a built-in
Server Component.
2024-08-02 20:08:08 -04:00
Sebastian MarkbågeandGitHub a67e6039a6 [DevTools] Track DOM nodes to Fiber map for HostHoistable Resources (#30590)
Follow up from #30584.

You can already select a singleton or hoistable (that's not a resource)
in the browser elements panel and it'll select the corresponding node in
the RDT Components panel. That works because it uses the same mechanism
as event dispatching and those need to be able to receive events.
However, you can't select a resource. Because that's conceptually one to
many.

This keeps track of which fiber is acquiring which resource so we can
find all the corresponding instances.

E.g. now you can select the `<link rel="stylesheet">` in the Flight
fixture in the Element panel and then the component that rendered it in
the Components panel will be selected.

If we had a concept multi-selection we could potentially select all of
them. This similar to how a Server Component can be rendered in more
than one place and if we want to select all matching ones. It's kind of
weird though and both cases are edge cases.

Notably imperative preloads do have elements that don't have any
corresponding component but that's ok. So they'll just select `<head>`.
Maybe in dev we could track the owners of those.
2024-08-02 19:22:39 -04:00
Mike Vitousek 5bc09556c4 [compiler] Fix issue with macro arguments being outlined
Summary:
Fixes issue documented by #30435. We change the pipeline order so that outlining comes after tracking macro operands, and any function that is referenced in a macro will now not be outlined.

ghstack-source-id: f731ad65c8b84db3fc5f3a2ff3a6986112765963
Pull Request resolved: https://github.com/facebook/react/pull/30587
2024-08-02 14:55:55 -07:00
Sebastian MarkbågeandGitHub 436d50c1c7 [DevTools] Rename mountFiberRecursively/updateFiberRecursively (#30586)
This is just for clarity at first.

Before: 
- mountFiberRecursively accepts a set of children and flag that says
whether to just do one
- updateFiberRecursively accepts a fiber and loops over its children
- unmountFiberChildrenRecursively accepts a fiber and loops over its
children

After:
- mountFiberRecursively accepts a Fiber and calls
mountChildrenRecursively
- updateFiberRecursively accepts a Fiber and calls
updateChildrenRecursively
- unmountFiberRecursively accepts a Fiber and calls
unmountChildrenRecursively
- mountChildrenRecursively accepts a set of children and loops over each
one
- updateChildrenRecursively accepts a set of children and loops over
each one
- unmountChildrenRecursively accepts a set of children and loops over
each one

So now there's one place where things happens for the single item and
one place where we do the loop.
2024-08-02 17:53:17 -04:00
4dd0cc7832 [DevTools] Allow Highlighting/Inspect HostSingletons/Hoistables and Resources (#30584)
Basically the new Float types needs to be supported. Resources are a bit
special because they're a DOM specific type but we can expect any other
implementation using resources to provide and instance on this field if
needed.

There's a slightly related case for the reverse lookup. You can already
select a singleton or hoistable (that's not a resource) in the browser
elements panel and it'll select the corresponding node in the RDT
Components panel. That works because it uses the same mechanism as event
dispatching and those need to be able to receive events.

However, you can't select a resource. Because that's conceptually one to
many. We could in principle just search the tree for the first one or
keep a map of currently mounted resources and just pick the first fiber
that created it. So that you can select a resource and see what created
it. Particularly useful when there's only one Fiber which is most of the
time.

---------

Co-authored-by: Ruslan Lesiutin <[email protected]>
2024-08-02 17:04:27 -04:00
Mike Vitousek aed27a334d [compiler] Allow global mutation effects in arguments passed to hooks and in return values
ghstack-source-id: f9ea675ead6eb61b3afc2a3deace0da270612d9d
Pull Request resolved: https://github.com/facebook/react/pull/30576
2024-08-02 12:24:41 -07:00
Sathya Gunsasekaran 0028e7c9d6 [compiler] Add flag for lowering context access
*This is only for internal profiling, not intended to ship.*

ghstack-source-id: e48998b7be4272199c8a6ff9cc2ec0975add5030
Pull Request resolved: https://github.com/facebook/react/pull/30547
2024-08-02 18:13:51 +01:00
Sathya Gunsasekaran 7f5840d2bf [compiler] Add typing for useContext hook
In the future, we can use this to identify useContext calls.

ghstack-source-id: 01d7b0941ccd09f65346eb5431aa53fe361ce5ed
Pull Request resolved: https://github.com/facebook/react/pull/30546
2024-08-02 18:13:51 +01:00
Sathya Gunsasekaran 1876e457f5 [compiler] Refactor makeTemporary outside HIRBuilder
This is a useful utility function similar to the existing
`makeInstructionId` and `makeIdentifierId` functions.

This PR moves it outside the HIRBuilder so we can use this in passes
that don't have access to the builder instance.

ghstack-source-id: 1ac0839e6cb417aedcdf8cdd159af7069af7172a
Pull Request resolved: https://github.com/facebook/react/pull/30545
2024-08-02 18:13:51 +01:00
Sathya Gunsasekaran 346ab483d0 [compiler] Simplify FunctionExpression node
Rather than storing the entire babel node, store only the required
information which is the node type.

This will be useful for when we synthesize new functions that don't have
a corresponding babel node.

ghstack-source-id: 9098cbdbc4b1e9a6e7dafa2e7645f6f4854e1eac
Pull Request resolved: https://github.com/facebook/react/pull/30544
2024-08-02 18:13:51 +01:00
Joe Savona 1535ced04a [compiler] Validate against setState in useMemo (resubmit of #30552)
ghstack failed to land #30552 properly, resubmitting

Developers sometimes use `useMemo()` as a way to conditionally execute code, including conditionally calling setState. However, the compiler may remove existing useMemo calls if they are not necessary, which _should_ always be a safe optimization. If the useMemo has side effects (eg sets state), then this isn't safe.

This PR improves ValidateNoSetStateInRender to disallow any setState in useMemo (even if it's conditional), expanding on the previous check for unconditional setState in render. Note that the approach uses the StartMemoize/FinishMemoize instructions added in DropManualMemo to know whether a particular setState call is within a useMemo or not. This means enabling the validation in DropManualMemo when the setState validation is enabled, but that's fine since that validation is on everywhere by default (_except_ for in fixtures, which we have a todo for)

ghstack-source-id: 65bb3289c3
Pull Request resolved: https://github.com/facebook/react/pull/30583
2024-08-02 10:06:08 -07:00
Ruslan LesiutinandGitHub d4c92ecc61 chore[react-devtools]: add global for native and use it to fork backend implementation (#30533)
Adding `__IS_NATIVE__` global, which will be used for forking backend
implementation. Will only be set to `true` for `react-devtools-core`
package, which is used by `react-native`.

Ideally, we should name it `react-devtools-native`, and keep
`react-devtools-core` as host-agnostic.

With this change, the next release of `react-devtools-core` should
append component stack as Error object, not as string, and should add
`(<anonymous>)` suffix to component stack frames.
2024-08-02 10:51:15 +01:00
Jan KassensandGitHub 33647c269d Cloned flag to avoid extra clones in persistent renderer (#27647)
Persistent renderers used the `Update` effect flag to check if a subtree
needs to be cloned. In some cases, that causes extra renders, such as
when a layout effect is triggered which only has an effect on the JS
side, but doesn't update the host components.

It's been a bit tricky to find the right places where this needs to be
set and I'm not 100% sure I got all the cases even though the tests
passed.
2024-08-01 15:11:19 -04:00
Sebastian MarkbågeandGitHub 4dc67a6991 [DevTools] Enable pointEvents while scrolling (#30560)
[`react-window` disables `pointerEvents` while scrolling meaning you
can't click anything while
scrolling.](https://github.com/bvaughn/react-window/issues/128).

This means that the first click when you stop the scroll with inertial
scrolling doesn't get registered. This is suuuper annoying. This might
make sense when you click to stop on a more intentional UI but it
doesn't makes sense in a list like this because we eagerly click things
even on mousedown.

This PR just override that to re-enable pointer events.

Supposedly this is done for performance but that might be outdated
knowledge. I haven't observed any difference so far.

If we discover that it's a perf problem, there's another technique we
can use where we call `ownerDocument.elementFromPoint(e.pageX, e.pageY)`
and then dispatch the event against that element. But let's try the
simplest approach first?
2024-08-01 11:34:38 -04:00
Sebastian MarkbågeandGitHub 63d89d2674 [DevTools] Make Element Inspection Feel Snappy (#30555)
There's two problems. The biggest one is that it turns out that Chrome
is throttling looping timers that we're using both while polling and for
batching bridge traffic. This means that bridge traffic a lot of the
time just slows down to 1 second at a time. No wonder it feels sluggish.
The only solution is to not use timers for this.

Even when it doesn't like in Firefox the batching into 100ms still feels
too sluggish.

The fix I use is to batch using a microtask instead so we can still
batch multiple commands sent in a single event but we never artificially
slow down an interaction.

I don't think we've reevaluated this for a long time since this was in
the initial commit of DevTools to this repo. If it causes other issues
we can follow up on those.

We really shouldn't use timers for debouncing and such. In fact, React
itself recommends against it because we have a better technique with
scheduling in Concurrent Mode. The correct way to implement this in the
bridge is using a form of back-pressure where we don't keep sending
messages until we get a message back and only send the last one that
matters. E.g. when moving the cursor over a the elements tab we
shouldn't let the backend one-by-one move the DOM node to each one we
have ever passed. We should just move to the last one we're currently
hovering over. But this can't be done at the bridge layer since it
doesn't know if it's a last-one-wins or imperative operation where each
one needs to be sent. It needs to be done higher. I'm not currently
seeing any perf problems with this new approach but I'm curious on React
Native or some thing. RN might need the back-pressure approach. That can
be a follow up if we ever find a test case.

Finally, the other problem is that we use a Suspense boundary around the
Element Inspection. Suspense boundaries are for things that are expected
to take a long time to load. This shows a loading state immediately. To
avoid flashing when it ends up being fast, React throttles the reveal to
200ms. This means that we take a minimum of 200ms to show the props. The
way to show fast async data in React is using a Transition (either using
startTransition or useDeferredValue). This lets the old value remaining
in place while we're loading the next one.

We already implement this using `inspectedElementID` which is the async
one. It would be more idiomatic to implement this with useDeferredValue
rather than the reducer we have now but same principle. We were just
using the wrong ID in a few places so when it synchronously updated they
suspended. So I just made them use the inspectedElementID instead.

Then I can simply remove the Suspense boundary. Now the selection
updates in the tree view synchronously and the sidebar lags a frame or
two but it feels instant. It doesn't flash to white between which is
key.
2024-08-01 11:04:56 -04:00