Commit Graph

138 Commits

Author SHA1 Message Date
Sebastian Markbåge
f0e808e5bc [Debug Tools] Always use includeHooksSource option (#28309)
This option was added defensively but it's not needed. There's no cost
to including it always.

I suspect this optional was added mainly to avoid needing to update
tests. That's not a reason to have an unnecessary public API though.

We have a praxis for dealing with source location in tests to avoid them
failing tests. I also ported them to inline snapshots so that additions
to the protocol isn't such a pain.
2024-02-14 11:07:35 -05:00
Andrew Clark
015ff2ed66 Revert "[Tests] Reset modules by default" (#28318)
This was causing a slowdown in one of the tests
ESLintRuleExhaustiveDeps-test.js. Reverting until we figure out why.
2024-02-13 11:39:45 -05:00
dan
14fd9630ee Switch <Context> to mean <Context.Provider> (#28226)
Previously, `<Context>` was equivalent to `<Context.Consumer>`. However,
since the introduction of Hooks, the `<Context.Consumer>` API is rarely
used. The goal here is to make the common case cleaner:

```js
const ThemeContext = createContext('light')

function App() {
  return (
    <ThemeContext value="dark">
      ...
    </ThemeContext>
  )
}

function Button() {
  const theme = use(ThemeContext)
  // ...
}
```

This is technically a breaking change, but we've been warning about
rendering `<Context>` directly for several years by now, so it's
unlikely much code in the wild depends on the old behavior. [Proof that
it warns today (check
console).](https://codesandbox.io/p/sandbox/peaceful-nobel-pdxtfl)

---

**The relevant commit is 5696782b428a5ace96e66c1857e13249b6c07958.** It
switches `createContext` implementation so that `Context.Provider ===
Context`.

The main assumption that changed is that a Provider's fiber type is now
the context itself (rather than an intermediate object). Whereas a
Consumer's fiber type is now always an intermediate object (rather than
it being sometimes the context itself and sometimes an intermediate
object).

My methodology was to start with the relevant symbols, work tags, and
types, and work my way backwards to all usages.

This might break tooling that depends on inspecting React's internal
fields. I've added DevTools support in the second commit. This didn't
need explicit versioning—the structure tells us enough.
2024-02-13 10:04:49 -05:00
Sebastian Markbåge
7a32d718b9 [Debug Tools] Introspect Promises in use() (#28297)
Alternative to #28295.

Instead of stashing all of the Usables eagerly, we can extract them by
replaying the render when we need them like we do with any other hook.
We already had an implementation of `use()` but it wasn't quite
complete.

These can also include further DebugInfo on them such as what Server
Component rendered the Promise or async debug info. This is nice just to
see which use() calls were made in the side-panel but it can also be
used to gather everything that might have suspended.

Together with https://github.com/facebook/react/pull/28286 we cover the
case when a Promise was used a child and if it was unwrapped with use().
Notably we don't cover a Promise that was thrown (although we do support
that in a Server Component which maybe we shouldn't). Throwing a Promise
isn't officially supported though and that use case should move to the
use() Hook.

The pattern of conditionally suspending based on cache also isn't really
supported with the use() pattern. You should always call use() if you
previously called use() with the same input. This also ensures that we
can track what might have suspended rather than what actually did.

One limitation of this strategy is that it's hard to find all the places
something might suspend in a tree without rerendering all the fibers
again. So we might need to still add something to the tree to indicate
which Fibers may have further debug info / thenables.
2024-02-12 17:54:28 -05:00
Sebastian Silbermann
04b59928d8 DevTools: Add support for use(Context) (#28233) 2024-02-08 18:47:40 +01:00
Ricky
30e2938e04 [Tests] Reset modules by default (#28254)
## Overview

Sets `resetModules: true` in the base Jest config, and deletes all the
`jest.resetModule()` calls we don't need.
2024-02-06 12:43:27 -05:00
Sebastian Silbermann
56cd10beb4 DevTools: Add support for useFormState (#28232)
## Summary

Add support for `useFormState` Hook fixing "Unsupported hook in the
react-debug-tools package: Missing method in Dispatcher: useFormState"
when inspecting components using `useFormState`

## How did you test this change?

- Added test to ReactHooksInspectionIntegration
- Added dedicated section for form actions to devtools-shell
![Screenshot 2024-02-04 at 12 02
05](https://github.com/facebook/react/assets/12292047/bb274789-64b8-4594-963e-87c4b6962144)
2024-02-05 15:39:45 +01:00
Sebastian Silbermann
85cc01743b DevTools: Add support for useOptimistic Hook (#27982)
## Summary

Add support for `useOptimistic` Hook fixing "Unsupported hook in the
react-debug-tools package: Missing method in Dispatcher: useOptimistic"
when inspecting components using `useOptimistic`

## How did you test this change?

- Added test following the same pattern as for `useDeferredValue`
2024-02-02 23:18:16 +01:00
Jack Pope
b36ae8d7aa Add stable concurrent option to react-test-renderer (#27804)
## Summary

Concurrent rendering has been the default since React 18 release.
ReactTestRenderer requires passing `{unstable_isConcurrent: true}` to
match this behavior, which means by default tests written with RTR use a
different rendering method than the code they test.

Eventually, RTR should only use ConcurrentRoot. As a first step, let's
add a version of the concurrent option that isn't marked unstable. Next
we will follow up with removing the unstable option when it is safe to
merge.

## How did you test this change?

`yarn test
packages/react-test-renderer/src/__tests__/ReactTestRendererAsync-test.js`
2023-12-07 10:26:33 -05:00
Jan Kassens
f498aa2992 Flow: make more objects exact (#27790)
This makes a couple objects more exact. Nothing critical, just noticed
this old branch I had created when doing some Flow upgrades in the past.
2023-12-04 16:10:36 -05:00
Ruslan Lesiutin
aec521a96d fix[devtools/useMemoCache]: implement a working copy of useMemoCache (#27659)
In https://github.com/facebook/react/pull/27472 I've removed broken
`useMemoCache` implementation and replaced it with a stub. It actually
produces errors when trying to inspect components, which are compiled
with Forget.

The main difference from the implementation in
https://github.com/facebook/react/pull/26696 is that we are using
corresponding `Fiber` here, which has patched `updateQueue` with
`memoCache`. Previously we would check it on a hook object, which
doesn't have `updateQueue`.

Tested on pages, which are using Forget and by inspecting elements,
which are transpiled with Forget.
2023-11-14 18:23:39 +00:00
Ruslan Lesiutin
a419575077 fix[devtools/useMemoCache]: add stub for useMemoCache in ReactDebugHook (#27472)
Currently, we have this error in our logs of the internal version of
React DevTools:
```
TypeError: Cannot read properties of undefined (reading 'memoCache')
    at Proxy.useMemoCache (chrome-extension://dnjnjgbfilfphmojnmhliehogmojhclc/build/react_devtools_backend_compact.js:151:71)
```

Looking at the build files of the extension, it fails here:
dddfe68820/packages/react-debug-tools/src/ReactDebugHooks.js (L333-L337)

Looks like `updateQueue` can be `undefined`, as it is not defined in
hook object here:
dddfe68820/packages/react-reconciler/src/ReactFiberHooks.js (L180-L186)

~~Also, it looks like `useMemoCache` implementation doesn't expect this,
so it should also result into TypeError here, line 1114:~~

dddfe68820/packages/react-reconciler/src/ReactFiberHooks.js (L1108-L1115)

~~Should this also be updated?~~
2023-10-17 18:39:10 +01:00
Andrew Clark
be67db46b6 Add optional initialValue argument to useDeferredValue (#27500)
Adds a second argument to useDeferredValue called initialValue:

```js
const value = useDeferredValue(finalValue, initialValue);
```

During the initial render of a component, useDeferredValue will return
initialValue. Once that render finishes, it will spawn an additional
render to switch to finalValue.

This same sequence should occur whenever the hook is hidden and revealed
again, i.e. by a Suspense or Activity, though this part is not yet
implemented.

When initialValue is not provided, useDeferredValue has no effect during
initial render, but during an update, it will remain on the previous
value, then spawn an additional render to switch to the new value. (This
is the same behavior that exists today.)

During SSR, initialValue is always used, if provided.

This feature is currently behind an experimental flag. We plan to ship
it in a non-breaking release.
2023-10-10 16:39:02 -04:00
Noah Lemen
80d9a40114 Remove useMutableSource (#27011)
## Summary

This PR cleans up `useMutableSource`. This has been blocked by a
remaining dependency internally at Meta, but that has now been deleted.

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

## How did you test this change?

```
yarn flow
yarn lint
yarn test --prod
```

<!--
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.
-->
2023-06-27 12:45:46 -04:00
lauren
25b99efe0c [DevTools] Add support for useMemoCache (#26696)
useMemoCache wasn't previously supported in the DevTools, so any attempt
to inspect a component using the hook would result in a
`dispatcher.useMemoCache is not a function (it is undefined)` error.
2023-04-25 09:19:25 -07:00
Andrew Clark
7ce765ec32 Clean up enableUseHook flag (#26707)
This has been statically enabled everywhere for months.
2023-04-23 14:50:17 -04:00
Sophie Alpert
767f52237c Use .slice() for all substring-ing (#26677)
- substr is Annex B
- substring silently flips its arguments if they're in the "wrong order", which is confusing
- slice is better than sliced bread (no pun intended) and also it works the same way on Arrays so there's less to remember

---

> I'd be down to just lint and enforce a single form just for the potential compression savings by using a repeated string.

_Originally posted by @sebmarkbage in https://github.com/facebook/react/pull/26663#discussion_r1170455401_
2023-04-19 14:26:01 -07:00
Jan Kassens
afea1d0c53 [flow] make Flow suppressions explicit on the error (#26487)
Added an explicit type to all $FlowFixMe suppressions to reduce
over-suppressions of new errors that might be caused on the same lines.

Also removes suppressions that aren't used (e.g. in a `@noflow` file as
they're purely misleading)

Test Plan:
yarn flow-ci
2023-03-27 13:43:04 +02:00
Andrew Clark
a8875eab7f Update more tests to not rely on sync queuing (#26358)
This fixes a handful of tests that were accidentally relying on React
synchronously queuing work in the Scheduler after a setState.

Usually this is because they use a lower level SchedulerMock method
instead of either `act` or one of the `waitFor` helpers. In some cases,
the solution is to switch to those APIs. In other cases, if we're
intentionally testing some lower level behavior, we might have to be a
bit more clever.

Co-authored-by: Tianyu Yao <skyyao@fb.com>
2023-03-10 11:06:28 -05:00
Andrew Clark
62cd5af08e Codemod redundant async act scopes (#26350)
Prior to #26347, our internal `act` API (not the public API) behaved
differently depending on whether the scope function returned a promise
(i.e. was an async function), for historical reasons that no longer
apply. Now that this is fixed, I've codemodded all async act scopes that
don't contain an await to be sync.

No pressing motivation other than it looks nicer and the codemod was
easy. Might help avoid confusion for new contributors who see async act
scopes with nothing async inside and infer it must be like that for a
reason.
2023-03-08 16:40:23 -05:00
Andrew Clark
44d3807945 Move internalAct to internal-test-utils package (#26344)
This is not a public API. We only use it for our internal tests, the
ones in this repo. Let's move it to this private package. Practically
speaking this will also let us use async/await in the implementation.
2023-03-08 12:58:31 -05:00
Andrew Clark
702fc984e6 Codemod act -> await act (4/?) (#26338)
Similar to the rationale for `waitFor` (see #26285), we should always
await the result of an `act` call so that microtasks have a chance to
fire.

This only affects the internal `act` that we use in our repo, for now.
In the public `act` API, we don't yet require this; however, we
effectively will for any update that triggers suspense once `use` lands.
So we likely will start warning in an upcoming minor.
2023-03-08 11:36:05 -05:00
Andrew Clark
703c67560d Codemod act -> await act (1/?) (#26334)
Similar to the rationale for `waitFor` (see
https://github.com/facebook/react/pull/26285), we should always await
the result of an `act` call so that microtasks have a chance to fire.

This only affects the internal `act` that we use in our repo, for now.
In the public `act` API, we don't yet require this; however, we
effectively will for any update that triggers suspense once `use` lands.
So we likely will start warning in an upcoming minor.
2023-03-07 10:15:34 -05:00
Andrew Clark
ce8a72fd4e Codemod tests to waitFor pattern (2/?) (#26296)
This converts some of our test suite to use the `waitFor` test pattern,
instead of the `expect(Scheduler).toFlushAndYield` pattern. Most of
these changes are automated with jscodeshift, with some slight manual
cleanup in certain cases.

See #26285 for full context.
2023-03-03 17:01:57 -05:00
Jan Kassens
6ddcbd4f96 [flow] enable LTI inference mode (#26104)
This is the next generation inference mode for Flow.
2023-02-09 17:07:39 -05:00
Jan Kassens
6b30832666 Upgrade prettier (#26081)
The old version of prettier we were using didn't support the Flow syntax
to access properties in a type using `SomeType['prop']`. This updates
`prettier` and `rollup-plugin-prettier` to the latest versions.

I added the prettier config `arrowParens: "avoid"` to reduce the diff
size as the default has changed in Prettier 2.0. The largest amount of
changes comes from function expressions now having a space. This doesn't
have an option to preserve the old behavior, so we have to update this.
2023-01-31 08:25:05 -05:00
Jan Kassens
e2424f33b3 [flow] enable exact_empty_objects (#25973)
This enables the "exact_empty_objects" setting for Flow which makes
empty objects exact instead of building up the type as properties are
added in code below. This is in preparation to Flow 191 which makes this
the default and removes the config.

More about the change in the Flow blog
[here](https://medium.com/flow-type/improved-handling-of-the-empty-object-in-flow-ead91887e40c).
2023-01-09 17:00:36 -05:00
Jan Kassens
0b4f443020 [flow] enable enforce_local_inference_annotations (#25921)
This setting is an incremental path to the next Flow version enforcing
type annotations on most functions (except some inline callbacks).

Used
```
node_modules/.bin/flow codemod annotate-functions-and-classes --write .
```
to add a majority of the types with some hand cleanup when for large
inferred objects that should just be `Fiber` or weird constructs
including `any`.

Suppressed the remaining issues.

Builds on #25918
2023-01-09 15:46:48 -05:00
Sebastian Markbåge
7b17f7bbf3 Enable warning for defaultProps on function components for everyone (#25699)
This also fixes a gap where were weren't warning on memo components.
2022-11-17 12:22:23 -05:00
Andrew Clark
9cdf8a99ed [Codemod] Update copyright header to Meta (#25315)
* Facebook -> Meta in copyright

rg --files | xargs sed -i 's#Copyright (c) Facebook, Inc. and its affiliates.#Copyright (c) Meta Platforms, Inc. and affiliates.#g'

* Manual tweaks
2022-10-18 11:19:24 -04:00
Sebastian Markbåge
a8c16a0040 Split Cache into its own Dispatcher (#25474)
* Missing Hooks

* Remove www forks. These can use __SECRET... instead.

* Move cache to separate dispatcher

These will be available in more contexts than just render.
2022-10-12 23:13:39 -04:00
Jan Kassens
3b6826ed9e Flow: inference_mode=constrain_writes
This mode is going to be the new default in Flow going forward.
There was an unfortuante large number of suppressions in this update.

More on the changes can be found in this [Flow blog post](https://medium.com/flow-type/new-flow-language-rule-constrained-writes-4c70e375d190).

Added some of the required annotations using the provided codemod:

```sh
node_modules/.bin/flow codemod annotate-declarations --write .
```

ghstack-source-id: 0b168e1b23
Pull Request resolved: https://github.com/facebook/react/pull/25422
2022-10-04 15:49:48 -04:00
Tianyu Yao
6e3bc8a2e8 [DevTools] Check if Proxy exists before creating DispatcherProxy (#25278) 2022-09-16 11:24:03 -07:00
Jan Kassens
346c7d4c43 straightford explicit types (#25253) 2022-09-13 17:57:38 -04:00
Jan Kassens
8003ab9cf5 Flow: remove explicit object syntax (#25223) 2022-09-09 16:03:48 -04:00
Jan Kassens
8a9e7b6cef Flow: implicit-inexact-object=error (#25210)
* implicit-inexact-object=error
* default everything ambiguous to exact object
* inexact where exact causes errors
2022-09-09 10:13:58 -04:00
Jan Kassens
a473d08fce Update to Flow from 0.97 to 0.122 (#25204)
* flow 0.122
* update ReactModel type
2022-09-08 11:46:07 -04:00
Sebastian Silbermann
9bd0dd4c18 test(react-debug-tools): Improve coverage of currentDispatcher.current setter (#24945) 2022-07-21 15:46:43 -04:00
Mengdi Chen
72ebc703ac [DevTools] fix useDeferredValue to match reconciler change (#24742)
* [DevTools] fix useDeferredValue to match reconciler change

* fixup

* update test to catch original issue

* fix lint

* add safer tests for other composite hooks
2022-06-17 14:43:10 -04:00
Mengdi "Monday" Chen
c89a15c716 [ReactDebugTools] wrap uncaught error from rendering user's component (#24216)
* [ReactDebugTools] wrap uncaught error from rendering user's component

* fix lint

* make error names more package specific

* update per review comments

* fix tests

* fix lint

* fix tests

* fix lint

* fix error name & nits

* try catch instead of mocking error

* fix test for older node.js version

* avoid false positive from try-catch in tests
2022-04-01 14:38:11 -04:00
Mengdi "Monday" Chen
0415b18a10 [ReactDebugTools] add custom error type for future new hooks (#24168)
* [ReactDebugTools] add custom error type for future new hooks

* update per review comments

* remove unused argument
2022-03-30 11:07:12 -04:00
Andrew Clark
efe4121ee2 Add : to beginning and end of every useId (#23360)
The ids generated by useId are unique per React root. You can create
additional ids by concatenating them with locally unique strings.

To support this pattern, no id will ever be a subset of another id. We
achieve this by adding a special character to the beginning and end.

We use a colon (":") because it's uncommon — even if you don't prefix
the ids using the `identifierPrefix` option, collisions are unlikely.

One downside of a colon is that it's not a valid character in DOM
selectors, like `querySelectorAll`. We think this is probably
fine because it's not a common use case in React, and there are
workarounds or alternative solutions. But we're open to reconsidering
this in the future if there's a compelling argument.
2022-02-24 20:07:41 -05:00
Luna Ruan
42f15b324f [DevTools][Transition Tracing] onTransitionComplete and onTransitionStart implmentation (#23313)
* add transition name to startTransition

Add a transitionName to start transition, store the transition start time and name in the batch config, and pass it to the root on render

* Transition Tracing Types and Consts

* Root begin work

The root operates as a tracing marker that has all transitions on it. This PR only tested the root with one transition so far

- Store transitions in memoizedState. Do this in updateHostRoot AND attemptEarlyBailoutIfNoScheduledUpdate. We need to do this in the latter part because even if the root itself doesn't have an update, it could still have new transitions in its transitionLanes map that we need to process.

* Transition Tracing commit phase

- adds a module scoped pending transition callbacks object that contains all transition callbacks that have not yet been processed. This  contains all callbacks before the next paint occurs.
- Add code in the mutation phase to:
        * For the root, if there are transitions that were initialized during this commit in the root transition lanes map, add a transition start call to the pending transition callbacks object. Then, remove the transitions from the root transition lanes map.
        * For roots, in the commit phase, add a transition complete call

We add this code in the mutation phase because we can't add it to the passive phase because then the paint might have occurred before we even know which callbacks to call

* Process Callbacks after paint

At the end of the commit phase, call scheduleTransitionCallbacks to schedule all pending transition callbacks to be called after paint. Then clear the callbacks
2022-02-24 14:28:18 -08:00
Sebastian Markbåge
1ad8d81292 Remove object-assign polyfill (#23351)
* Remove object-assign polyfill

We really rely on a more modern environment where this is typically
polyfilled anyway and we don't officially support IE with more extensive
polyfilling anyway. So all environments should have the native version
by now.

* Use shared/assign instead of Object.assign in code

This is so that we have one cached local instance in the bundle.

Ideally we should have a compile do this for us but we already follow
this pattern with hasOwnProperty, isArray, Object.is etc.

* Transform Object.assign to now use shared/assign

We need this to use the shared instance when Object.spread is used.
2022-02-23 19:34:24 -05:00
Sebastian Markbåge
0dedfcc681 Update the exports field (#23257)
* Add .browser and .node explicit entry points

This can be useful when the automatic selection doesn't work properly.

* Remove react/index

I'm not sure why I added this in the first place. Perhaps due to how our
builds work somehow.

* Remove build-info.json from files field
2022-02-08 21:07:26 -05:00
Andrew Clark
5cccacd131 Upgrade useId to alpha channel (#22674) 2021-11-01 15:26:42 -07:00
Andrew Clark
75f3ddebfa Remove experimental useOpaqueIdentifier API (#22672)
useId is the updated version of this API.
2021-11-01 15:02:39 -07:00
Andrew Clark
ebf9ae8579 useId (#22644)
* Add useId to dispatcher

* Initial useId implementation

Ids are base 32 strings whose binary representation corresponds to the
position of a node in a tree.

Every time the tree forks into multiple children, we add additional bits
to the left of the sequence that represent the position of the child
within the current level of children.

    00101       00010001011010101
    ╰─┬─╯       ╰───────┬───────╯
  Fork 5 of 20       Parent id

The leading 0s are important. In the above example, you only need 3 bits
to represent slot 5. However, you need 5 bits to represent all the forks
at the current level, so we must account for the empty bits at the end.

For this same reason, slots are 1-indexed instead of 0-indexed.
Otherwise, the zeroth id at a level would be indistinguishable from
its parent.

If a node has only one child, and does not materialize an id (i.e. does
not contain a useId hook), then we don't need to allocate any space in
the sequence. It's treated as a transparent indirection. For example,
these two trees produce the same ids:

<>                          <>
  <Indirection>               <A />
    <A />                     <B />
  </Indirection>            </>
  <B />
</>

However, we cannot skip any materializes an id. Otherwise, a parent id
that does not fork would be indistinguishable from its child id. For
example, this tree does not fork, but the parent and child must have
different ids.

<Parent>
  <Child />
</Parent>

To handle this scenario, every time we materialize an id, we allocate a
new level with a single slot. You can think of this as a fork with only
one prong, or an array of children with length 1.

It's possible for the the size of the sequence to exceed 32 bits, the
max size for bitwise operations. When this happens, we make more room by
converting the right part of the id to a string and storing it in an
overflow variable. We use a base 32 string representation, because 32 is
the largest power of 2 that is supported by toString(). We want the base
to be large so that the resulting ids are compact, and we want the base
to be a power of 2 because every log2(base) bits corresponds to a single
character, i.e. every log2(32) = 5 bits. That means we can lop bits off
the end 5 at a time without affecting the final result.

* Incremental hydration

Stores the tree context on the dehydrated Suspense boundary's state
object so it resume where it left off.

* Add useId to react-debug-tools

* Add selective hydration test

Demonstrates that selective hydration works and ids are preserved even
after subsequent client updates.
2021-11-01 13:30:44 -07:00
Andrew Clark
a0d991fe65 Re-land #22292 (remove uMS from open source build) (#22664)
I had to revert #22292 because there are some internal callers of
useMutableSource that we haven't migrated yet. This removes
useMutableSource from the open source build but keeps it in the
internal one.
2021-10-31 21:39:51 -07:00
Andrew Clark
6bce0355c3 Upgrade useSyncExternalStore to alpha channel (#22662)
* Move useSyncExternalStore shim to a nested entrypoint

Also renames `useSyncExternalStoreExtra` to
`useSyncExternalStoreWithSelector`.

- 'use-sync-external-store/shim' -> A shim for `useSyncExternalStore`
  that works in React 16 and 17 (any release that supports hooks). The
  module will first check if the built-in React API exists, before
  falling back to the shim.
- 'use-sync-external-store/with-selector' -> An extended version of
  `useSyncExternalStore` that also supports `selector` and `isEqual`
  options. It does _not_ shim `use-sync-external-store`; it composes the
  built-in React API. **Use this if you only support 18+.**
- 'use-sync-external-store/shim/with-selector' -> Same API, but it
  composes `use-sync-external-store/shim` instead. **Use this for
  compatibility with 16 and 17.**
- 'use-sync-external-store' -> Re-exports React's built-in API. Not
  meant to be used. It will warn and direct users to either the shim or
  the built-in API.

* Upgrade useSyncExternalStore to alpha channel
2021-10-31 15:38:03 -07:00