Commit Graph

15887 Commits

Author SHA1 Message Date
gaearon 9adade5cc6 Remove deprecated methods from react-is (#28224)
These aren't being used anywhere and don't even correspond to real APIs.

DiffTrain build for [35b2c28178](https://github.com/facebook/react/commit/35b2c28178bf4f79898d11dce0bc2a7ce675f670)
2024-02-11 00:30:17 +00:00
kassens e0e832eabb Add infinite update loop detection (#28279)
This is a partial redo of https://github.com/facebook/react/pull/26625.
Since that was unlanded due to some detected breakages. This now
includes a feature flag to be careful in rolling this out.

DiffTrain build for [d8c1fa6b0b](https://github.com/facebook/react/commit/d8c1fa6b0b8da0512cb5acab9cd4f242451392f3)
2024-02-09 16:19:24 +00:00
sebmarkbage b2392647b5 [Flight] Serialize deduped elements by direct reference even if they suspend (#28283)
In #28123 I switched these to be lazy references. However that creates a
lazy wrapper even if they're synchronously available. We try to as much
as possible preserve the original data structure in these cases.

E.g. here in the dev outlining I only use a lazy wrapper if it didn't
complete synchronously:
https://github.com/facebook/react/pull/28272/files#diff-d4c9c509922b3671d3ecce4e051df66dd5c3d38ff913c7a7fe94abc3ba2ed72eR638

Unfortunately we don't have a data structure that tracks the status of
each emitted row. We could store the task in the map but then they
couldn't be GC:ed as they complete. We could maybe store the status of
each element but seems so heavy.

For now I just went back to direct reference which might be an issue
since it can suspend something higher up when deduped.

DiffTrain build for [ba5e6a8329](https://github.com/facebook/react/commit/ba5e6a8329c7194a2c573c037a37f24ce45ee58f)
2024-02-08 23:50:18 +00:00
sebmarkbage 64de3b0154 Throw a better error when Lazy/Promise is used in React.Children (#28280)
We could in theory actually support this case by throwing a Promise when
it's used inside a render. Allowing it to be synchronously unwrapped.
However, it's a bit sketchy because we officially only support this in
the render's child position or in `use()`.

Another alternative could be to actually pass the Promise/Lazy to the
callback so that you can reason about it and just return it again or
even unwrapping with `use()` - at least for the forEach case maybe.

DiffTrain build for [e41ee9ea70](https://github.com/facebook/react/commit/e41ee9ea70f8998144fdd959ac11fd7a40e4ee20)
2024-02-08 22:14:59 +00:00
acdlite 3b33617b80 Delete more redundant JSX code (#28276)
Found another redundant implementation of JSX code. Not being used
anywhere so safe to delete.

DiffTrain build for [d3def47935](https://github.com/facebook/react/commit/d3def47935e8912c197f78c78c97c2476fa1a77a)
2024-02-08 16:08:53 +00:00
sebmarkbage c064e1665c [Flight] Emit debug info for a Server Component (#28272)
This adds a new DEV-only row type `D` for DebugInfo. If we see this in
prod, that's an error. It can contain extra debug information about the
Server Components (or Promises) that were compiled away during the
server render. It's DEV-only since this can contain sensitive
information (similar to errors) and since it'll be a lot of data, but
it's worth using the same stream for simplicity rather than a
side-channel.

In this first pass it's just the Server Component's name but I'll keep
adding more debug info to the stream, and it won't always just be a
Server Component's stack frame.

Each row can get more debug rows data streaming in as it resolves and
renders multiple server components in a row.

The data structure is just a side-channel and it would be perfectly fine
to ignore the D rows and it would behave the same as prod. With this
data structure though the data is associated with the row ID / chunk, so
you can't have inline meta data. This means that an inline Server
Component that doesn't get an ID otherwise will need to be outlined. The
way I outline Server Components is using a direct reference where it's
synchronous though so on the client side it behaves the same (i.e.
there's no lazy wrapper in this case).

In most cases the `_debugInfo` is on the Promises that we yield and we
also expose this on the `React.Lazy` wrappers. In the case where it's a
synchronous render it might attach this data to Elements or Arrays
(fragments) too.

In a future PR I'll wire this information up with Fiber to stash it in
the Fiber data structures so that DevTools can pick it up. This property
and the information in it is not limited to Server Components. The name
of the property that we look for probably shouldn't be `_debugInfo`
since it's semi-public. Should consider the name we use for that.

If it's a synchronous render that returns a string or number (text node)
then we don't have anywhere to attach them to. We could add a
`React.Lazy` wrapper for those but I chose to prioritize keeping the
data structure untouched. Can be useful if you use Server Components to
render data instead of React Nodes.

DiffTrain build for [b229f540e2](https://github.com/facebook/react/commit/b229f540e2da91370611945f9875e00a96196df6)
2024-02-08 16:06:43 +00:00
sebmarkbage 82dd48d0a1 Remove __self and __source location from elements (#28265)
Along with all the places using it like the `_debugSource` on Fiber.
This still lets them be passed into `createElement` (and JSX dev
runtime) since those can still be used in existing already compiled code
and we don't want that to start spreading to DOM attributes.

We used to have a DEV mode that compiles the source location of JSX into
the compiled output. This was nice because we could get the actual call
site of the JSX (instead of just somewhere in the component). It had a
bunch of issues though:

- It only works with JSX.
- The way this source location is compiled is different in all the
pipelines along the way. It relies on this transform being first and the
source location we want to extract but it doesn't get preserved along
source maps and don't have a way to be connected to the source hosted by
the source maps. Ideally it should just use the mechanism other source
maps use.
- Since it's expensive it only works in DEV so if it's used for
component stacks it would vary between dev and prod.
- It only captures the callsite of the JSX and not the stack between the
component and that callsite. In the happy case it's in the component but
not always.

Instead, we have another zero-cost trick to extract the call site of
each component lazily only if it's needed. This ensures that component
stacks are the same in DEV and PROD. At the cost of worse line number
information.

The better way to get the JSX call site would be to get it from `new
Error()` or `console.createTask()` inside the JSX runtime which can
capture the whole stack in a consistent way with other source mappings.
We might explore that in the future.

This removes source location info from React DevTools and React Native
Inspector. The "jump to source code" feature or inspection can be made
lazy instead by invoking the lazy component stack frame generation. That
way it can be made to work in prod too. The filtering based on file path
is a bit trickier.

When redesigned this UI should ideally also account for more than one
stack frame.

With this change the DEV only Babel transforms are effectively
deprecated since they're not necessary for anything.

DiffTrain build for [37d901e2b8](https://github.com/facebook/react/commit/37d901e2b81e12d40df7012c6f8681b8272d2555)
2024-02-07 21:42:46 +00:00
gnoff a6a77a2a05 Improve flagging of React.cache to remove indirection in bundled code (#28263)
Uses a better technique for conditionally disabling cache on the client

DiffTrain build for [a1ace9d3c2](https://github.com/facebook/react/commit/a1ace9d3c2a0fc53703f11e30f32d0a009c5a8c9)
2024-02-07 01:44:50 +00:00
acdlite 126187e9cd jsx(): Treat __self and __source as normal props (#28257)
These used to be reserved props because the classic React.createElement
runtime passed this data as props, whereas the jsxDEV() runtime passes
them as separate arguments.

This brings us incrementally closer to being able to pass the props
object directly through to React instead of cloning a subset into a new
object.

The React.createElement runtime is unaffected.

DiffTrain build for [91caa96e42](https://github.com/facebook/react/commit/91caa96e4261704d42333f5e02ba32d870379fc4)
2024-02-07 01:07:46 +00:00
sebmarkbage 7a0151305a [Flight] Unify plain Server Component and forwardRef under one function (#28261)
This used to be trivial but it's no longer trivial.

In Fizz and Fiber this is split into renderWithHooks and
finishFunctionComponent since they also support indeterminate
components.

Interestingly thanks to this unification we always call functions with
an arity of 2 which is a bit weird - with the second argument being
undefined in everything except forwardRef and legacy context consumers.

This makes Flight makes the same thing but we could also call it with an
arity of 1.

Since Flight errors early if you try to pass it a ref, and there's no
legacy context, the second arg is always undefined.

The practical change in this PR is that returning a Promise from a
forwardRef now turns it into a lazy. We previously didn't support async
forwardRef since it wasn't supported on the client. However, since
eventually this will be supported by child-as-a-promise it seems fine to
support it.

DiffTrain build for [f07ac1e268](https://github.com/facebook/react/commit/f07ac1e2680a26c5b3bf9c651d62c792de71d46d)
2024-02-07 00:46:08 +00:00
acdlite de5b760022 jsx(): Inline reserved prop checks (#28262)
The JSX runtime (both the new one and the classic createElement runtime)
check for reserved props like `key` and `ref` by doing a lookup in a
plain object map with `hasOwnProperty`.

There are only a few reserved props so this inlines the checks instead.

DiffTrain build for [1beb94133a](https://github.com/facebook/react/commit/1beb94133a93a433669a893aef02dd5afec07394)
2024-02-07 00:01:39 +00:00
sebmarkbage e46929f3ed [Flight] Move pendingChunks ref count increment into createTask (#28260)
Every time we create a task we need to wait for it so we increase a ref
count. We can do this in `createTask`. This is in line with what Fizz
does too.

They differ in that Flight counts when they're actually flushed where as
Fizz decrements them when they complete.

Flight should probably count them when they complete so it's possible to
wait for the end before flushing for buffering purposes.

DiffTrain build for [0d11563b4a](https://github.com/facebook/react/commit/0d11563b4a96e0f4f2361cdf7375b12375688163)
2024-02-06 21:22:53 +00:00
acdlite aa5199bf97 Delete duplicate jsx() implementation (#28258)
Not sure how this happened but there are two identical implementations
of the jsx and jsxDEV functions. One of them was unreachable. I deleted
that one.

DiffTrain build for [6692445759](https://github.com/facebook/react/commit/66924457594bc28eb2f3f39c7c61d54b931c188e)
2024-02-06 20:09:46 +00:00
eps1lon d1b0b96c04 [Fresh] Update the list of built-in hooks (#27864)
DiffTrain build for [7cbd026ff4](https://github.com/facebook/react/commit/7cbd026ff4ff833db2a2f2271f95cb2b91cb3895)
2024-02-06 19:02:28 +00:00
eps1lon a52f42714f Ensure useState and useReducer initializer functions are double invoked in StrictMode (#28248)
DiffTrain build for [97fd3e7064](https://github.com/facebook/react/commit/97fd3e7064b162f05b1bac3962ed10c6559c346c)
2024-02-06 16:57:47 +00:00
gsathya 47b1b75d09 Patch devtools before running useMemo function in strict mode (#28249)
This fixes a regression https://github.com/facebook/react/pull/25583
where we stopped patching before calling useMemo function.

Fixes https://github.com/facebook/react/issues/27989

DiffTrain build for [db120f69ec](https://github.com/facebook/react/commit/db120f69ec7a0b8c7f38ca7a1ddb1886de92e465)
2024-02-06 16:50:17 +00:00
gnoff b72ef1accd Add flag to disable caching behavior of React.cache on the client (#28250)
Adds a feature flag to control whether the client cache function is just
a passthrough. before we land breaking changes for the next major it
will be off and then we can flag it on when we want to break it.

flag is off for OSS for now and on elsewhere (though the parent flag
enableCache is off in some cases)

DiffTrain build for [2bc7d336ae](https://github.com/facebook/react/commit/2bc7d336ae7db689699baeb1fffc2c03d8753ffe)
2024-02-06 00:37:01 +00:00
gaearon c178d6f4b1 [Flight] Delete Server Context (#28225)
Server Context was never documented, and has been deprecated in
https://github.com/facebook/react/pull/27424.

This PR removes it completely, including the implementation code.

Notably, `useContext` is removed from the shared subset, so importing it
from a React Server environment would now should be a build error in
environments that are able to enforce that.

DiffTrain build for [472854820b](https://github.com/facebook/react/commit/472854820bfd0058dfc85524051171c7b7c998c1)
2024-02-05 22:44:00 +00:00
sebmarkbage b505fe3f92 [Flight] Support Keyed Server Components (#28123)
Conceptually a Server Component in the tree is the same as a Client
Component.

When we render a Server Component with a key, that key should be used as
part of the reconciliation process to ensure the children's state are
preserved when they move in a set. The key of a child should also be
used to clear the state of the children when that key changes.

Conversely, if a Server Component doesn't have a key it should get an
implicit key based on the slot number. It should not inherit the key of
its children since the children don't know if that would collide with
other keys in the set the Server Component is rendered in.

A Client Component also has an identity based on the function's
implementation type. That mainly has to do with the state (or future
state after a refactor) that Component might contain. To transfer state
between two implementations it needs to be of the same state type. This
is not a concern for a Server Components since they never have state so
identity doesn't matter.

A Component returns a set of children. If it returns a single child,
that's the same as returning a fragment of one child. So if you
conditionally return a single child or a fragment, they should
technically reconcile against each other.

The simple way to do this is to simply emit a Fragment for every Server
Component. That would be correct in all cases. Unfortunately that is
also unfortunate since it bloats the payload in the common cases. It
also means that Fiber creates an extra indirection in the runtime.

Ideally we want to fold Server Component aways into zero cost on the
client. At least where possible. The common cases are that you don't
specify a key on a single return child, and that you do specify a key on
a Server Component in a dynamic set.

The approach in this PR treats a Server Component that returns other
Server Components or Lazy Nodes as a sequence that can be folded away.
I.e. the parts that don't generate any output in the RSC payload.
Instead, it keeps track of their keys on an internal "context". Which
gets reset after each new reified JSON node gets rendered.

Then we transfer the accumulated keys from any parent Server Components
onto the child element. In the simple case, the child just inherits the
key of the parent.

If the Server Component itself is keyless but a child isn't, we have to
add a wrapper fragment to ensure that this fragment gets the implicit
key but we can still use the key to reset state. This is unusual though
because typically if you keyed something it's because it was already in
a fragment.

In the case a Server Component is keyed but forks its children using a
fragment, we need to key that fragment so that the whole set can move
around as one. In theory this could be flattened into a parent array but
that gets tricky if something suspends, because then we can't send the
siblings early.

The main downside of this approach is that switching between single
child and fragment in a Server Component isn't always going to reconcile
against each other. That's because if we saw a single child first, we'd
have to add the fragment preemptively in case it forks later. This
semantic of React isn't very well known anyway and it might be ok to
break it here for pragmatic reasons. The tests document this
discrepancy.

Another compromise of this approach is that when combining keys we don't
escape them fully. We instead just use a simple `,` separated concat.
This is probably good enough in practice. Additionally, since we don't
encode the implicit 0 index slot key, you can move things around between
parents which shouldn't really reconcile but does. This keeps the keys
shorter and more human readable.

DiffTrain build for [95ec128399](https://github.com/facebook/react/commit/95ec128399a8b34884cc6bd90a041e03ce5c1844)
2024-02-05 17:38:19 +00:00
gnoff 55b1962e67 add RSC entrypoint for jsx-runtime (#28217)
Adds a new entrypoint for the production jsx-runtime when using
react-server condition. Currently the entrypoints are the same but in
the future we will potentially change the implementation of the runtime
in ways that can only be optimized for react-server constraints and we
want to have the entrypoint already separated so environments using it
will be pulling in the right version

DiffTrain build for [00f9acb12c](https://github.com/facebook/react/commit/00f9acb12c036ef24a2b6d7957d75359c6280087)
2024-02-02 21:43:43 +00:00
eps1lon 65f2fcff29 fix(eslint-plugin-react-hooks): accepting as expression as a callback (#28202)
## Summary

Closes #20750

## How did you test this change?

Added a test case

DiffTrain build for [2efa38332a](https://github.com/facebook/react/commit/2efa38332adc1fc1500753d79fcba41a0197a7a6)
2024-02-01 20:12:01 +00:00
rickhanlonii 7bfb304cc6 Remove createRootStrictEffectsByDefault flag (#28102)
There's no need to separate strict mode from strict effects mode any
more.

I didn't clean up the `StrictEffectMode` fiber flag, because it's used
to prevent strict effects in legacy mode. I could replace those checks
with `LegacyMode` checks, but when we remove legacy mode, we can remove
that flag and condense them into one StrictMode flag away.

DiffTrain build for [3d1da1f9ab](https://github.com/facebook/react/commit/3d1da1f9ab7d54984c096e6a04c8729f3a50fd8a)
2024-02-01 19:59:11 +00:00
eps1lon 96284300ed fix(eslint-plugin-react-hooks): accepting as expressions as deps array (#28189)
## Summary

This PR closes #25844
The original issue talks about `as const`, but seems like it fails for
any `as X` expressions since it adds another nesting level to the AST.

EDIT: Also closes #20162

## How did you test this change?

Added unit tests

DiffTrain build for [a1433ca0ba](https://github.com/facebook/react/commit/a1433ca0bacff76f720ffec9a0020f56e8c9ffed)
2024-02-01 19:35:11 +00:00
acdlite a96ef807a2 Add stable React.act export (#28160)
Starting in version 19, users can import the `act` testing API from the
`react` package instead of using a renderer specific API, like
`react-dom/test-utils`.

DiffTrain build for [53b12e46a1](https://github.com/facebook/react/commit/53b12e46a17549ec7644e13c126440ed2f3629fd)
2024-02-01 18:34:16 +00:00
gnoff 72343e632a [Fizz] Support aborting with Postpone (#28183)
Semantically if you make your reason for aborting a Postpone instance
the render should not hit the error pathways but should instead follow
the postpone pathways. It's awkward today to actually get your hands on
a Postpone instance because you have to catch the throw from postpone
and then pass that into `abort()` or `AbortController.abort()`
(depending on the renderer API you are using)

This change makes it so that in most circumstances if you abort with a
postpone the `onPostpone` handler will be called and the Suspense
boundaries still pending will be put into client render mode with the
appropriate postpone digest to avoid trigger recoverable error pathways
on the client.

Similar to postponing in the shell during a resume or render however if
you abort before the shell is complete in a resume or render we will
fatally error. The fatal error is contextualized by React to avoid
passing the postpone object itself to the `onError` and related options.

DiffTrain build for [1219d57fc9](https://github.com/facebook/react/commit/1219d57fc9fcbf44c873c0b10e5acbd31f613c15)
2024-02-01 15:18:52 +00:00
eps1lon 5f663581bc Restore old behavior for empty href props on anchor tags (#28124)
Treat `<a href="" />` the same with and without
`enableFilterEmptyStringAttributesDOM`

in https://github.com/facebook/react/pull/18513 we started to warn and
ignore for empty `href` and `src` props since it usually hinted at a
mistake. However, for anchor tags there's a valid use case since `<a
href=""></a>` will by spec render a link to the current page. It could
be used to reload the page without having to rely on browser
affordances.

The implementation for Fizz is in the spirit of
https://github.com/facebook/react/pull/21153. I gated the fork behind
the flag so that the fork is DCE'd when the flag is off.

DiffTrain build for [f3ce87ab65](https://github.com/facebook/react/commit/f3ce87ab650f07774e1df9bc3f8033e023973d10)
2024-01-30 23:48:54 +00:00
rickhanlonii 3cc608a8e7 Update www flags (#28150)
Adds an experiment for `enableFormActions` and hardcodes
`enableCustomElementPropertySupport` on www since this is shipped.

DiffTrain build for [417188314d](https://github.com/facebook/react/commit/417188314dd1d6df54efc8cd6a0c5d4830615888)
2024-01-30 19:29:43 +00:00
acdlite ec00d40eaa Always warn if client component suspends with an uncached promise (#28159)
Previously we only warned during a synchronous update, because we
eventually want to support async client components in controlled
scenarios, like during navigations. However, we're going to warn in all
cases for now until we figure out how that should work.

DiffTrain build for [178f435194](https://github.com/facebook/react/commit/178f4351947a842ff0b56700e9115b25ae8f20d0)
2024-01-30 19:28:23 +00:00
gnoff fa09a710fb [Fizz] improve Hoistable handling for Elements and Resources inside Suspense Boundaries (#28069)
Updates Fizz to handle Hoistables (Resources and Elements) in a way that
better aligns with Suspense fallbacks

1. Hoistable Elements inside a fallback (regardless of how deep and how
many additional boundaries are intermediate) will be ignored. The
reasoning is fallbacks are transient and since there is not good way to
clean up hoistables because they escape their Suspense container its
better to not emit them in the first place. SSR fallbacks are already
not full fidelity because they never hydrate so this aligns with that
somewhat.
2. Hoistable stylesheets in fallbacks will only block the reveal of a
parent suspense boundary if the fallback is going to flush with that
completed parent suspense boundary. Previously if you rendered a
stylesheet Resource inside a fallback any parent suspense boundaries
that completed after the shell flushed would include that resource in
the set required to resolve before the boundary reveal happens on the
client. This is not a semantic change, just a performance optimization
3. preconnect and preload hoistable queues are gone, if you want to
optimize resource loading you shoudl use `ReactDOM.preconnect` and
`ReactDOM.preload`. `viewport` meta tags get their own queue because
they need to go before any preloads since they affect the media state.

In addition to those functional changes this PR also refactors the
boundary resource tracking by moving it to the task rather than using
function calls at the start of each render and flush. Tasks also now
track whether they are a fallback task

supercedes prior work here: https://github.com/facebook/react/pull/27534

DiffTrain build for [554fc49f41](https://github.com/facebook/react/commit/554fc49f41465d914b15dc8eb2ec094f37824f7e)
2024-01-30 18:20:40 +00:00
gnoff bc0fa9ecd7 [Fiber] Use a safer strategy to track the last precedence (#28110)
Uses a safer strategy to track the last precedence to avoid the need to
consistently remember to preprend `'p'` to the precedence value

DiffTrain build for [1c958aa4ab](https://github.com/facebook/react/commit/1c958aa4abf9e6b638489b1d73cdb1b6dc7c3ab6)
2024-01-30 18:15:00 +00:00
rickhanlonii 52a1078a24 Remove outdated enableSchedulerDebugging flag (#28101)
This flag was moved to the scheduler feature flags, so these flags don't
do anything.

DiffTrain build for [766eac46bb](https://github.com/facebook/react/commit/766eac46bb52bda28f87c11740214a4444ca881b)
2024-01-26 21:57:53 +00:00
acdlite c6f9c3abf5 Capture React.startTransition errors and pass to reportError (#28111)
To make React.startTransition more consistent with the hook form of
startTransition, we capture errors thrown by the scope function and pass
them to the global reportError function. (This is also what we do as a
default for onRecoverableError.)

This is a breaking change because it means that errors inside of
startTransition will no longer bubble up to the caller. You can still
catch the error by putting a try/catch block inside of the scope
function itself.

We do the same for async actions to prevent "unhandled promise
rejection" warnings.

The motivation is to avoid a refactor hazard when changing from a sync
to an async action, or from useTransition to startTransition.

DiffTrain build for [60f190a559](https://github.com/facebook/react/commit/60f190a55948a7512d4e2a336f03b45fd38d6a80)
2024-01-26 17:15:15 +00:00
gnoff c53cad6bbe fix incorrect insertion order of stylesheets (#28108)
## Summary

In the precendences Map every key is prefixed with `p`. This fixes one
case where this is missing.

## 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.
-->

DiffTrain build for [763612647c](https://github.com/facebook/react/commit/763612647ceb66d95f728af896ca5e18a8181db8)
2024-01-26 16:00:50 +00:00
acdlite bd16b96a44 Async action support for React.startTransition (#28097)
This adds support for async actions to the "isomorphic" version of
startTransition (i.e. the one exported by the "react" package).
Previously, async actions were only supported by the startTransition
that is returned from the useTransition hook.

The interesting part about the isomorphic startTransition is that it's
not associated with any particular root. It must work with updates to
arbitrary roots, or even arbitrary React renderers in the same app. (For
example, both React DOM and React Three Fiber.)

The idea is that React.startTransition should behave as if every root
had an implicit useTransition hook, and you composed together all the
startTransitions provided by those hooks. Multiple updates to the same
root will be batched together. However, updates to one root will not be
batched with updates to other roots.

Features like useOptimistic work the same as with the hook version.

There is one difference from from the hook version of startTransition:
an error triggered inside an async action cannot be captured by an error
boundary, because it's not associated with any particular part of the
tree. You should handle errors the same way you would in a regular
event, e.g. with a global error event handler, or with a local
`try/catch`.

DiffTrain build for [85b296e9b6](https://github.com/facebook/react/commit/85b296e9b6ded4accd9ec3389297f95091fb1ac0)
2024-01-26 02:59:47 +00:00
sebmarkbage b9b97d9ac8 [Flight/Fizz] Reset ThenableState Only in Branches Where It's Added (#28068)
Before, we used to reset the thenable state and extract the previous
state very early so that it's only the retried task that can possibly
consume it. This is nice because we can't accidentally consume that
state for any other node.

However, it does add a lot of branches of code that has to pass this
around. It also adds extra bytes on the stack per node. Even though it's
mostly just null.

This changes it so that where ever we can create a thenable state (e.g.
entering a component with hooks) we first extract this from the task.
The principle is that whatever could've created the thenable state in
the first place, must always be rerendered so it'll take the same code
paths to get there and so we'll always consume it.

DiffTrain build for [382190c595](https://github.com/facebook/react/commit/382190c595126837ee7e43b4fa953f4edd30e01c)
2024-01-26 00:58:02 +00:00
sebmarkbage 68cd468ecd [Flight] Refactor the Render Loop to Behave More Like Fizz (#28065)
This refactors the Flight render loop to behave more like Fizz with
similar naming conventions. So it's easier to apply similar techniques
across both. This is not necessarily better/faster - at least not yet.

This doesn't yet implement serialization by writing segments to chunks
but we probably should do that since the built-in parts that
`JSON.stringify` gets us isn't really much anymore (except serializing
strings). When we switch to that it probably makes sense for the whole
thing to be recursive.

Right now it's not technically fully recursive because each recursive
render returns the next JSON value to encode. So it's kind of like a
trampoline. This means we can't have many contextual things on the
stack. It needs to use the Server Context `__POP` trick. However, it
does work for things that are contextual only for one sequence of server
component abstractions in a row. Since those are now recursive.

An interesting observation here is that `renderModel` means that
anything can suspend while still serializing the outer siblings.
Typically only Lazy or Components would suspend but in principle a Proxy
can suspend/postpone too and now that is left serialized by reference to
a future value. It's only if the thing that we rendered was something
that can reduce to Lazy e.g. an Element that we can serialize it as a
lazy.

Similarly to how Suspense boundaries in Fizz can catch errors, anything
that can be reduced to Lazy can also catch an error rather than bubbling
it. It only errors when the Lazy resolves. Unlike Suspense boundaries
though, those things don't render anything so they're otherwise going to
use the destructive form. To ensure that throwing in an Element can
reuse the current task, this must be handled by `renderModel`, not for
example `renderElement`.

DiffTrain build for [b123b9c4f0](https://github.com/facebook/react/commit/b123b9c4f054a7def7ed84e350ccd46cc86672a6)
2024-01-25 17:14:06 +00:00
acdlite 69fea0b202 Batch async actions even if useTransition is unmounted (#28078)
If there are multiple updates inside an async action, they should all be
rendered in the same batch, even if they are separate by an async
operation (`await`). We currently implement this by suspending in the
`useTransition` hook to block the update from committing until all
possible updates have been scheduled by the action. The reason we did it
this way is so you can "cancel" an action by navigating away from the UI
that triggered it.

The problem with that approach, though, is that even if you navigate
away from the `useTransition` hook, the action may have updated shared
parts of the UI that are still in the tree. So we may need to continue
suspending even after the `useTransition` hook is deleted.

In other words, the lifetime of an async action scope is longer than the
lifetime of a particular `useTransition` hook.

The solution is to suspend whenever _any_ update that is part of the
async action scope is unwrapped during render. So, inside useState and
useReducer.

This fixes a related issue where an optimistic update is reverted before
the async action has finished, because we were relying on the
`useTransition` hook to prevent the optimistic update from finishing.

This also prepares us to support async actions being passed to the
non-hook form of `startTransition` (though this isn't implemented yet).

DiffTrain build for [11c9fd0c53](https://github.com/facebook/react/commit/11c9fd0c53133f24f5270d36591b65b8fc2ebd25)
2024-01-25 04:59:52 +00:00
rickhanlonii 605ae6d45e Convert ReactDOMTestSelectors-test.js to createRoot (#27993)
Straightforward adding createRoot and act

DiffTrain build for [4217d324ae](https://github.com/facebook/react/commit/4217d324ae5766b3201e682bb4d67b8855652694)
2024-01-24 04:06:34 +00:00
rickhanlonii d703a879f2 Update error decoder URL (#27240)
Updates the error decoder to the URL for the new docs site.

- Switches the domain from reactjs.org to react.dev
- Switches to put the error code in the URL for SSG
- All params are still in the query

Example without args:

- Before: `https://reactjs.org/docs/error-decoder.html?invariant=200`
- After: ` https://react.dev/errors/200`

Example with args:
- Before:
`https://reactjs.org/docs/error-decoder.html?invariant=124?args[]=foo&args[]=bar
`
- After: ` https://react.dev/errors/124?args[]=foo&args[]=bar`

Requires: https://github.com/reactjs/react.dev/pull/6214

---------

Co-authored-by: Jan Kassens <jkassens@meta.com>

DiffTrain build for [b300304710](https://github.com/facebook/react/commit/b3003047101b4c7a643788a8faf576f7e370fb45)
2024-01-18 02:45:49 +00:00
acdlite a2531fa8a8 Remove client caching from cache() API (#27977)
We haven't yet decided how we want `cache` to work on the client. The
lifetime of the cache is more complex than on the server, where it only
has to live as long as a single request.

Since it's more important to ship this on the server, we're removing the
existing behavior from the client for now. On the client (i.e. not a
Server Components environment) `cache` will have not have any caching
behavior. `cache(fn)` will return the function as-is.

We intend to implement client caching in a future major release. In the
meantime, it's only exposed as an API so that Shared Components can use
per-request caching on the server without breaking on the client.

DiffTrain build for [5c607369ce](https://github.com/facebook/react/commit/5c607369ceebe56d85175df84b7b6ad58dd25e1f)
2024-01-17 01:31:57 +00:00
acdlite 0cd227f5e2 Refactor React Server entrypoint to not depend on the client one (#27940)
This refactors the Server Components entrypoint for the `react` package
(ReactServer.js) so that it doesn't depend on the client entrypoint
(React.js). I also renamed React.js to ReactClient.js to make the
separation clearer.

This structure will make it easier to add client-only and server-only
features.

DiffTrain build for [f16344ea6d](https://github.com/facebook/react/commit/f16344ea6db5bcc108de80dbc39a41ec28e8210d)
2024-01-17 01:23:48 +00:00
acdlite 5832ad09fd Rename "shared subset" to "server" (#27939)
The internal file ReactSharedSubset is what the `react` module resolves
to when imported from a Server Component environment. We gave it this
name because, originally, the idea was that Server Components can access
a subset of the APIs available on the client.

However, since then, we've also added APIs that can _only_ by accessed
on the server and not the client. In other words, it's no longer a
subset, it's a slightly different overlapping set.

So this commit renames ReactSharedSubet to ReactServer and updates all
the references. This does not affect the public API, only our internal
implementation.

DiffTrain build for [5d1b15a4f0](https://github.com/facebook/react/commit/5d1b15a4f06fa93e76cd89f37ea5bfd62cc66183)
2024-01-17 01:02:57 +00:00
acdlite f10aaf1267 Fix: useOptimistic should return passthrough value when there are no updates pending (#27936)
This fixes a bug that happened when the canonical value passed to
useOptimistic without an accompanying call to setOptimistic. In this
scenario, useOptimistic should pass through the new canonical value.

I had written tests for the more complicated scenario, where a new value
is passed while there are still pending optimistic updates, but not this
simpler one.

DiffTrain build for [60a927d04a](https://github.com/facebook/react/commit/60a927d04ad3888facebcdf7da620aa1cfc9528f)
2024-01-14 02:42:16 +00:00
sebmarkbage 990d5cc255 Use getComponentNameFromType for debug info for the key warning (#27930)
If this is a client reference we shouldn't dot into it, which would
throw in the proxy.

Interestingly our client references don't really have a `name`
associated with them for debug information so a component type doesn't
show up in error logs even though it seems like it should.

DiffTrain build for [0ac3ea471f](https://github.com/facebook/react/commit/0ac3ea471fbcb7d79bc7d36179e960c72c779e76)
2024-01-11 22:29:18 +00:00
noahlemen 827e912776 re-add dynamic feature flags for isInputPending (#27919)
## Summary

these were removed in https://github.com/facebook/react/pull/26617. adds
them back so we can conduct another experiment.

## How did you test this change?
`yarn test-www`

DiffTrain build for [c81f4e02ba](https://github.com/facebook/react/commit/c81f4e02bab9d03e1583047d041fdb5e4eb19415)
2024-01-09 22:25:42 +00:00
sebmarkbage 3d4df0a7de [Fizz] Fix Client Render after Postpone (#27905)
If we end up client rendering a boundary due to an error after we have
already injected a postponed hole in that boundary we'll end up trying
to target a missing segment. Since we never insert segments for an
already errored boundary into the HTML. Normally an errored prerender
wouldn't be used but if it is, such as if it was an intentional client
error it triggers this case. Those should really be replaced with
postpones though.

This is a bit annoying since we eagerly build up the postponed path. I
took the easy route here and just cleared out the suspense boundary
itself from having any postponed slots. However, this still creates an
unnecessary replay path along the way to the boundary. We could probably
walk the path and remove any empty parent nodes.

What is worse is that if this is the only thing that postponed, we'd
still generate a postponed state even though there's actually nothing to
resume. Since this is a bit of an edge case already maybe it's fine.

In my test I added a check for the `error` event on `window` since this
error only surfaces by throwing an ignored error. We should really do
that globally for all tests. Our tests should fail by default if there's
an error logged to the window.

DiffTrain build for [f9dddcbbb1](https://github.com/facebook/react/commit/f9dddcbbb1c0b73f974e78b9488927b778630682)
2024-01-09 04:57:25 +00:00
acdlite f748f7366c Fix: useDeferredValue initialValue suspends forever without switching to final (#27888)
Fixes a bug in the experimental `initialValue` option for
`useDeferredValue` (added in #27500).

If rendering the `initialValue` causes the tree to suspend, React should
skip it and switch to rendering the final value instead. It should not
wait for `initialValue` to resolve.

This is not just an optimization, because in some cases the initial
value may _never_ resolve — intentionally. For example, if the
application does not provide an instant fallback state. This capability
is, in fact, the primary motivation for the `initialValue` API.

I mostly implemented this correctly in the original PR, but I missed
some cases where it wasn't working:

- If there's no Suspense boundary between the `useDeferredValue` hook
and the component that suspends, and we're not in the shell of the
transition (i.e. there's a parent Suspense boundary wrapping the
`useDeferredValue` hook), the deferred task would get incorrectly
dropped.
- Similarly, if there's no Suspense boundary between the
`useDeferredValue` hook and the component that suspends, and we're
rendering a synchronous update, the deferred task would get incorrectly
dropped.

What these cases have in common is that it causes the `useDeferredValue`
hook itself to be replaced by a Suspense fallback. The fix was the same
for both. (It already worked in cases where there's no Suspense fallback
at all, because those are handled differently, at the root.)

The way I discovered this was when investigating a particular bug in
Next.js that would happen during a 'popstate' transition (back/forward),
but not during a regular navigation. That's because we render popstate
transitions synchronously to preserve browser's scroll position — which
in this case triggered the second scenario above.

DiffTrain build for [f1039be4a4](https://github.com/facebook/react/commit/f1039be4a48384e7e4b0a87d4d92c48e900053b9)
2024-01-08 04:22:01 +00:00
sebmarkbage f2094eebbf [Fizz] Only compute component stacks in DEV and prerenders (#27850)
If you have a lot of intentional throws (or postpones) from client-only
rendering then computing the stack is too much.

DiffTrain build for [c5b9375767](https://github.com/facebook/react/commit/c5b9375767e2c4102d7e5559d383523736f1c902)
2023-12-19 23:08:55 +00:00
alunyov beb4a4d2d1 [RSC @ Meta] Simplify implementation of isClientReference, getClientReferenceKey, resolveClientReferenceMetadata (#27839)
For clientReferences we can just check the instance of the
`clientReference`.
The implementation of `isClientReference` is provided via configuration.
The class for ClientReference has to implement an interface that has
`getModuleId() method.

DiffTrain build for [cb2439624f](https://github.com/facebook/react/commit/cb2439624f43c510007f65aea5c50a8bb97917e4)
2023-12-19 14:22:53 +00:00
gnoff 7fb394d17d [Fizz] Add Component Stacks to onError and onPostpone when in dev mode or during prerenders in prod mode (#27761)
Historically React would produce component stacks for dev builds only.
There is a cost to tracking component stacks and given the prod builds
try to optimize runtime performance these stacks were left out. More
recently React added production component stacks to Fiber in because it
can be immensely helpful in tracking down hard to debug production
issues. Fizz was not updated to have a similar behavior.

With the advent of prerendering however stacks for production in Fizz
are more relevant because prerendering is not really a dev-time task. If
you want the ability to reason about errors or postpones that happen
during a prerender having component stacks to interrogate is helpful and
these component stacks need to be available in production otherwise you
are really never going to see them. (it is possible that you could do
dev-mode prerenders but we don't expect this to be a common dev mode
workflow)

To better support the prerender use case and to make error logging in
Fizz more useful the following changes have been made

1. `onPostpone` now accepts a second `postponeInfo` argument which will
contain a componentStack. Postpones always originate from a component
render so the stack should be consistently available. The type however
will indicate the stack is optional so we can remove them in the future
if we decide the overhead is the wrong tradeoff in certain cases
2. `onError` now accepts a second `errorInfo` argument which may contain
a componentStack. If an error originated from a component a stack will
be included in the following cases.

This change entails tracking the component hierarchy in prod builds now.
While this isn't cost free it is implemented in a relatively lean
manner. Deferring the most expensive work (reifying the stack) until we
are actually in an error pathway.

In the course of implementing this change a number of simplifications
were made to the code which should make the stack tracking more
resilient. We no longer use a module global to curry the stack up to
some handler. This was delicate because you needed to always reset it
properly. We now curry the stack on the task itself.

Another change made was to track the component stack on SuspenseBoundary
instances so that we can provide the stack when aborting suspense
boundaries to help you determine which ones were affected by an abort.

DiffTrain build for [63310df2b2](https://github.com/facebook/react/commit/63310df2b243b6c3b2f01e8b121e7d115e839cfb)
2023-12-16 02:10:31 +00:00