Commit Graph
15734 Commits
Author SHA1 Message Date
hoxyq c4d091a1dc fix: devtools source field disappears after component remount (#27297)
## Summary

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

On actions that cause a component to change its signature, and therefore
to remount, the `_debugSource` property of the fiber updates in delay
and causes the `devtools` source field to vanish.

This issue happens in
https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberBeginWork.js

```js
function beginWork(
  current: Fiber | null,
  workInProgress: Fiber,
  renderLanes: Lanes,
): Fiber | null {
  if (__DEV__) {
    if (workInProgress._debugNeedsRemount && current !== null) {
      // This will restart the begin phase with a new fiber.
      return remountFiber(
        current,
        workInProgress,
        createFiberFromTypeAndProps(
          workInProgress.type,
          workInProgress.key,
          workInProgress.pendingProps,
          workInProgress._debugOwner || null,
          workInProgress.mode,
          workInProgress.lanes,
        ),
      );
    }
  }

  // ...
```

`remountFiber` uses the 3rd parameter as the new fiber
(`createFiberFromTypeAndProps(...)`), but this parameter doesn’t contain
a `_debugSource`.

## How did you test this change?

Tested by monkey patching
`./node_modules/react-dom/cjs/react-dom.development.js`:
<img width="1749" alt="image"
src="https://github.com/facebook/react/assets/75563024/ccaf7fab-4cc9-4c05-a48b-64db6f55dc23">

https://github.com/facebook/react/assets/75563024/0650ae5c-b277-44d1-acbb-a08d98bd38e0

DiffTrain build for [eaa696876e](https://github.com/facebook/react/commit/eaa696876ee40bb048727aefe995be1bbb7384a8)
2023-08-29 15:47:57 +00:00
noahlemen 5a211bb7c8 set priority on TaskController instead of on postTask/yield (#27295)
## Summary

passing both a signal and a priority to `postTask`/`yield` in chrome
causes memory to spike and potentially causes OOMs. a fix for this has
landed in chrome 118, but we can avoid the issue in earlier versions by
setting priority on just the TaskController instead.

https://bugs.chromium.org/p/chromium/issues/detail?id=1469367

## How did you test this change?
```
yarn test SchedulerPostTask
```

DiffTrain build for [4129ea8c92](https://github.com/facebook/react/commit/4129ea8c922b950be3964f98d2bb74ff4a1c5431)
2023-08-29 13:11:41 +00:00
acdlite eeb35792f2 Client implementation of useFormState (#27278)
This implements useFormState in Fiber. (It does not include any
progressive enhancement features; those will be added later.)

useFormState is a hook for tracking state produced by async actions. It
has a signature similar to useReducer, but instead of a reducer, it
accepts an async action function.

```js
async function action(prevState, payload) {
  // ..
}
const [state, dispatch] = useFormState(action, initialState)
```

Calling dispatch runs the async action and updates the state to the
returned value.

Async actions run before React's render cycle, so unlike reducers, they
can contain arbitrary side effects.

DiffTrain build for [456d153bb5](https://github.com/facebook/react/commit/456d153bb582798effa76c09bec2405ab2e392cf)
2023-08-28 15:10:46 +00:00
acdlite a7a6a73c44 Fix mount-or-update check in rerenderOptimistic (#27277)
I noticed this was wrong because it should call updateWorkInProgressHook
before it checks if currentHook is null.

DiffTrain build for [9a01c8b54e](https://github.com/facebook/react/commit/9a01c8b54e91c588391070c65701342e4e361ea7)
2023-08-28 15:09:55 +00:00
acdlite b1f8e0d638 Selective Hydration: Don't suspend if showing fallback (#27230)
A transition that flows into a dehydrated boundary should not suspend if
the boundary is showing a fallback.

This is related to another issue where Fizz streams in the initial HTML
after a client navigation has already happened. That issue is not fixed
by this commit, but it does make it less likely. Need to think more
about the larger issue.

DiffTrain build for [ab31a9ed28](https://github.com/facebook/react/commit/ab31a9ed28d340172440e4b12e27d2af689249b3)
2023-08-25 00:09:28 +00:00
gnoff 3129e28505 [Float][Fizz][Static] add importMap option to Fizz and Static server renderers (#27260)
Import maps need to be emitted before any scripts or preloads so the
browser can properly locate these resources.

Unlike most scripts, importmaps are singletons meaning you can only have
one per document and they must appear before any modules are loaded or
preloaded. In the future there may be a way to dynamically add more
mappings however the proposed API for this seems likely to be a
javascript API and not an html tag.

Given the unique constraints here this PR implements React's support of
importMaps as the following

1. an `importMap` option accepting a plain object mapping module
specifier to path is accepted in any API that renders a preamble (head
content). Notably this precludes resume rendering because in resume
cases the preamble should have already been produced as part of the
prerender step.
2. the importMap is stringified and emitted as a `<script
type="importmap">...</script>` in the preamble.
3. the importMap is escaped identically to how bootstrapScriptContent is
escaped, notably, isntances of `</script>` are escaped to avoid breaking
out of the script context

Users can still render importmap tags however with Float enabled this is
rather pointless as most modules will be hoisted above the importmap
that is rendered. In practice this means the only functional way to use
import maps with React is to use this config API.

DiffTrain build for [9d4582dffd](https://github.com/facebook/react/commit/9d4582dffdea5b4dcb6a6093ea848d15423c7701)
2023-08-24 20:53:38 +00:00
acdlite 2bd9065dd7 Scaffolding for useFormState (#27270)
This exposes, but does not yet implement, a new experimental API called
useFormState. It's gated behind the enableAsyncActions flag.

useFormState has a similar signature to useReducer, except instead of a
reducer it accepts an (async) action function. React will wait until the
promise resolves before updating the state:

```js
async function action(prevState, payload) {
  // ..
}
const [state, dispatch] = useFormState(action, initialState)
```

When used in combination with Server Actions, it will also support
progressive enhancement — a form that is submitted before it has
hydrated will have its state transferred to the next page. However, like
the other action-related hooks, it works with fully client-driven
actions, too.

DiffTrain build for [b4cdd3e892](https://github.com/facebook/react/commit/b4cdd3e8922713f8c9817b004a0dc51be47bc5df)
2023-08-23 15:05:09 +00:00
sebmarkbage ff6e098a4b [Fizz] Split ResponseState/Resources into RenderState/ResumableState (#27268)
This exposes a `resume()` API to go with the `prerender()` (only in
experimental). It doesn't work yet since we don't yet emit the postponed
state so not yet tested.

The main thing this does is rename ResponseState->RenderState and
Resources->ResumableState. We separated out resources into a separate
concept preemptively since it seemed like separate enough but probably
doesn't warrant being a separate concept. The result is that we have a
per RenderState in the Config which is really just temporary state and
things that must be flushed completely in the prerender. Most things
should be ResumableState.

Most options are specified in the `prerender()` and transferred into the
`resume()` but certain options that are unique per request can't be.
Notably `nonce` is special. This means that bootstrap scripts and
external runtime can't use `nonce` in this mode. They need to have a CSP
configured to deal with external scripts, but not inline.

We need to be able to restore state of things that we've already emitted
in the prerender. We could have separate snapshot/restore methods that
does this work when it happens but that means we have to explicitly do
that work. This design is trying to keep to the principle that we just
work with resumable data structures instead so that we're designing for
it with every feature. It also makes restoring faster since it's just
straight into the data structure.

This is not yet a serializable format. That can be done in a follow up.

We also need to vet that each step makes sense. Notably stylesToHoist is
a bit unclear how it'll work.

DiffTrain build for [31034b6de7](https://github.com/facebook/react/commit/31034b6de73c7cd9093e92a34e384d84c082aa4e)
2023-08-22 19:26:27 +00:00
gnoff f51a814e8a [Float][Fizz][Legacy] hoisted elements no longer emit before <html> in legacy apis such as renderToString() (#27269)
renderToString is a legacy server API which used a trick to avoid having
the DOCTYPE included when rendering full documents by setting the root
formatcontext to HTML_MODE rather than ROOT_HTML_MODE. Previously this
was of little consequence but with Float the Root mode started to be
used for things like determining if we could flush hoistable elements
yet. In issue #27177 we see that hoisted elements can appear before the
<html> tag when using a legacy API `renderToString`.

This change exports a DOCTYPE from FizzConfigDOM and FizzConfigDOMLegacy
respectively, using an empty chunk in the legacy case. The only runtime
perf cost here is that for legacy APIs there is an extra empty chunk to
write when rendering a top level <html> tag which is trivial enough

Fixes #27177

DiffTrain build for [86198b9231](https://github.com/facebook/react/commit/86198b923199224b60533952b636348bb0484a6d)
2023-08-22 17:59:31 +00:00
acdlite c1e19bbad3 Fix: Stylesheet in error UI suspends indefinitely (#27265)
This fixes the regression test added in the previous commit. The
"Suspensey commit" implementation relies on the
`shouldRemainOnPreviousScreen` function to determine whether to 1)
suspend the commit 2) activate a parent fallback and schedule a retry.
The issue was that we were sometimes attempting option 2 even when there
was no parent fallback.

Part of the reason this bug landed is due to how `throwException` is
structured. In the case of Suspensey commits, we pass a special "noop"
thenable to `throwException` as a way to trigger the Suspense path. This
special thenable must never have a listener attached to it. This is not
a great way to structure the logic, it's just a consequence of how the
code evolved over time. We should refactor it into multiple functions so
we can trigger a fallback directly without having to check the type. In
the meantime, I added an internal warning to help detect similar
mistakes in the future.

DiffTrain build for [dd480ef923](https://github.com/facebook/react/commit/dd480ef923930c8906a02664b01bcdea50707b5d)
2023-08-22 15:27:25 +00:00
sebmarkbage ab3288b0d0 [Fizz] Track Key Path (#27243)
Tracks the currently executing parent path of a task, using the name of
the component and the key or index.

This can be used to uniquely identify an instance of a component between
requests - assuming nothing in the parents has changed. Even if it has
changed, if things are properly keyed, it should still line up.

It's not used yet but we'll need this for two separate features so
should land this so we can stack on top.

Can be passed to `JSON.stringify(...)` to generate a unique key.

DiffTrain build for [98f3f14d2e](https://github.com/facebook/react/commit/98f3f14d2e06fb785103296318204cd154d5d0ed)
2023-08-18 14:23:39 +00:00
gnoff 0fe197bb3e [Float][Flight][Fizz][Fiber] Implement preloadModule and preinitModule (#27220)
Stacked on #27224

### Implements `ReactDOM.preloadModule()`
`preloadModule` is a function to preload modules of various types.
Similar to `preload` this is useful when you expect to use a Resource
soon but can't render that resource directly. At the moment the only
sensible module to preload is script modules along with some other `as`
variants such as `as="serviceworker"`. In the future when there is some
notion of how to preload style module script or json module scripts this
API will be extended to support those as well.

##### Arguments
1. `href: string` -> the href or src value you want to preload.
2. `options?: {...}` ->
2.1. `options.as?: string` -> the `as` property the modulepreload link
should render with. If not provided it will be omitted which will cause
the modulepreload to be treated like a script module
2.2. `options.crossOrigin?: string` -> modules always load with CORS but
you can provide `use-credentials` if you want to change the default
behavior
2.3. `options.integrity?: string` -> an integrity hash for subresource
integrity APIs

##### Rendering
each preloaded module will emit a `<link rel="modulepreload" href="..."
/>`
if `as` is specified and is something other than `"script"` the as
attribute will also be included
if crossOrigin or integrity as specified their attributes will also be
included

During SSR these script tags will be emitted before content. If we have
not yet flushed the document head they will be emitted there after
things that block paint such as font preloads, img preloads, and
stylesheets.

On the client these link tags will be appended to the document.head.

### Implements `ReactDOM.preinitModule()`
`preinitModule` is a function to loading module scripts before they are
required. It has the same use cases as `preinit`.

During SSR you would use this to tell the browsers to start fetching
code that will be used without having to wait for bootstrapping to
initiate module fetches.

ON the client you would use this to start fetching a module script early
for an anticipated navigation or other event that is likely to depend on
this module script.

the `as` property for Float methods drew inspiration from the `as`
attribute of the `<link rel="preload" ... >` tag but it is used as a
sort of tag for the kind of thing being targetted by Float methods. For
`preinitModule` we currently only support `as: "script"` and this is
also the assumed default type so you current never need to specify this
`as` value. In the future `preinitModule` will support additional module
script types such as `style` or `json`. The support of these types will
correspond to [Module Import
Attributes](https://github.com/tc39/proposal-import-attributes).

##### Arguments
1. `href: string` -> the href or src value you want to preinitialize
2. `options?: {...}` ->
2.1 `options.as?: string` -> only supports `script` and this is the
default behavior. Until we support import attributes such as `json` and
`style` there will not be much reason to provide an `as` option.
2.2. `options.crossOrigin?: string`: modules always load with CORS but
you can provide `use-credentials` if you want to change the default
behavior
2.3 `options.integrity?: string` -> an integrity hash for subresource
integrity APIs

##### Rendering
each preinitialized `script` module will emit a `<script type="module"
async="" src"...">` During SSR these will appear behind display blocking
resources such as font preloads, img preloads, and stylesheets. In the
browser these will be appende to the head.

Note that for other `as` types the rendered output will be slightly
different. `<script type="module">import "..." with {type: "json"
}</script>`. Since this tag is an inline script variants of React that
do not use inline scripts will simply omit these preinitialization tags
from the SSR output. This is not implemented in this PR but will appear
in a future update.

DiffTrain build for [e505316920](https://github.com/facebook/react/commit/e50531692010bbda2a4627b07c7c810c3770a52a)
2023-08-17 17:35:00 +00:00
sebmarkbage 5cc1661577 Add Postpone API (#27238)
This adds an experimental `unstable_postpone(reason)` API.

Currently we don't have a way to model effectively an Infinite Promise.
I.e. something that suspends but never resolves. The reason this is
useful is because you might have something else that unblocks it later.
E.g. by updating in place later, or by client rendering.

On the client this works to model as an Infinite Promise (in fact,
that's what this implementation does). However, in Fizz and Flight that
doesn't work because the stream needs to end at some point. We don't
have any way of knowing that we're suspended on infinite promises. It's
not enough to tag the promises because you could await those and thus
creating new promises. The only way we really have to signal this
through a series of indirections like async functions, is by throwing.
It's not 100% safe because these values can be caught but it's the best
we can do.

Effectively `postpone(reason)` behaves like a built-in [Catch
Boundary](https://github.com/facebook/react/pull/26854). It's like
`raise(Postpone, reason)` except it's built-in so it needs to be able to
be encoded and caught by Suspense boundaries.

In Flight and Fizz these behave pretty much the same as errors. Flight
just forwards it to retrigger on the client. In Fizz they just trigger
client rendering which itself might just postpone again or fill in the
value. The difference is how they get logged.

In Flight and Fizz they log to `onPostpone(reason)` instead of
`onError(error)`. This log is meant to help find deopts on the server
like finding places where you fall back to client rendering. The reason
that you pass in is for that purpose to help the reason for any deopts.

I do track the stack trace in DEV but I don't currently expose it to
`onPostpone`. This seems like a limitation. It might be better to expose
the Postpone object which is an Error object but that's more of an
implementation detail. I could also pass it as a second argument.

On the client after hydration they don't get passed to
`onRecoverableError`. There's no global `onPostpone` API to capture
postponed things on the client just like there's no `onError`. At that
point it's just assumed to be intentional. It doesn't have any `digest`
or reason passed to the client since it's not logged.

There are some hacky solutions that currently just tries to reuse as
much of the existing code as possible but should be more properly
implemented.
- Fiber is currently just converting it to a fake Promise object so that
it behaves like an infinite Promise.
- Fizz is encoding the magic digest string `"POSTPONE"` in the HTML so
we know to ignore it but it should probably just be something neater
that doesn't share namespace with digests.

Next I plan on using this in the `/static` entry points for additional
features.

Why "postpone"? It's basically a synonym to "defer" but we plan on using
"defer" for other purposes and it's overloaded anyway.

DiffTrain build for [ac1a16c67e](https://github.com/facebook/react/commit/ac1a16c67e268fcb2c52e91717cbc918c7c24446)
2023-08-17 17:32:07 +00:00
gnoff d03f8fbb1b Float integrity bugfix (#27224)
Stacked on #27223

When a script resource adopts certain props from a preload for that
resource the integrity prop was incorrectly getting assinged to the
referrerPolicy prop instead. This is now fixed.

DiffTrain build for [0fb5b61ac6](https://github.com/facebook/react/commit/0fb5b61ac6951a492242618e4ace6c1826335efc)
2023-08-14 17:15:47 +00:00
gnoff 9f4e34bf23 Remove excess validation (#27223)
stacked on #27222

When I initially developed Float I was trying to be extremely clever in
how to explain when there are mismatching Resource instances. I still
think that we should do some kind of validation here but I want to
implement something much simpler. In practice there are not many cases
where you would accidentally create the same resource twice but with
differing props. Since I am going to land `preloadModule` and
`preinitModule` soon and I want to avoid adding to the overly complex
dev validation there I am going to remove it now and add something later
that is simplified.

DiffTrain build for [5ea1397b2b](https://github.com/facebook/react/commit/5ea1397b2b62875dfb521cf8de0efcc15d0df797)
2023-08-14 17:14:23 +00:00
gnoff 3ffb40aadd Should not export functions that are not imported (#27222)
These functions are not imported anywhere and should have not been
exported to begin with

DiffTrain build for [5ad8ef5772](https://github.com/facebook/react/commit/5ad8ef57729fa4a57aeec3f9b0516325248dba85)
2023-08-14 17:12:53 +00:00
gnoff 6c0314daa2 [Fizz][Float] When src or srcSet is a data URI we should not preload the image (#27218)
Data URI's in images can't effectively be preloaded (the URI contains
the data so preloading only duplicates the data in the stream. If we
encounter an image with this protocol in the src attribute we should
avoid preloading it.

DiffTrain build for [1a001dac62](https://github.com/facebook/react/commit/1a001dac6220a64d98ae33a28e89dde78100d6c5)
2023-08-12 16:26:47 +00:00
gnoff 2c0c9e7639 [Float][Fizz] Fix srcSet and sizes handling for suspensey img preloads (#27217)
imageSrcSet should have been srcSet when referencing an img tag.
imageSizes should have been sizes. This caused preloads for img tags
using srcSet and sizes to incorrectly render as having a href only,
dropping the srcSet and sizes part of the preload

DiffTrain build for [4e3618ae41](https://github.com/facebook/react/commit/4e3618ae41669c95a3377ae615c727f74f89d141)
2023-08-11 18:32:16 +00:00
gnoff fc901a8083 [Fizz] Preload "suspensey" images (#27191)
Eventually we will treat images without `loading="lazy"` as suspensey
meaning we will coordinate the reveal of boundaries when these images
have loaded and ideally decoded. As a step in that direction this change
prioritizes these images for preloading to ensure the highest chance
that they are loaded before boundaries reveal (or initial paint). every
img rendered that is non lazy loading will emit a preload just behind
fonts.

This change implements a new resource queue for high priority image
preloads

There are a number of scenarios where we end up putting a preload in
this queue

1. If you render a non-lazy image and there are fewer than 10 high
priority image preloads
2. if you render a non-lazy image with fetchPriority "high"
3. if you preload as "image" with fetchPriority "high"

This means that by default we won't overrsaturate this queue with every
img rendered on the page but the earlier encountered ones will go first.
Essentially this is React's own implementation of fetchPriority="auto".

If however you specify that the fetchPriority is higher then in theory
an unlimited number of images can preload in this queue. This gives
users some control over queuing while still providing a good default
that does not require any opting into

Additionally we use fetchPriority "low" as a signal that an image does
not require preloading. This may end up being pointless if not using
lazy (which also opts out of preloading) because it might delay initial
paint but we'll start with this hueristic and consider changes in the
future when we have more information

DiffTrain build for [f359f9b41a](https://github.com/facebook/react/commit/f359f9b41ac1a8127f5ba505e0c04675eee0d310)
2023-08-10 22:44:12 +00:00
acdlite e09bb3d726 Bugfix: Fix crash when suspending in shell during useSES re-render (#27199)
This adds a regression test for a bug where, after a store mutation, the
updated data causes the shell of the app to suspend.

When re-rendering due to a concurrent store mutation, we must check for
the RootDidNotComplete exit status again.

As a follow-up, I'm going to look into to cleaning up the places where
we check the exit status, so bugs like these are less likely. I think we
might be able to combine most of it into a single switch statement.

DiffTrain build for [201becd3d2](https://github.com/facebook/react/commit/201becd3d294b38824930a818e3412c6e04ba2eb)
2023-08-08 18:16:03 +00:00
gnoff e6bc6ee70b [Fizz]: Unify preload queue (#27190)
Currently React attempts to prioritize certain preloads over others
based on their type. This is at odds with allowing the user to control
priority by ordering which calls are made first. There are some asset
types that generally should just be prioritized first such as fonts
since we don't know when fonts will be used and they either block
display or may lead to fallback fonts being used. But for scripts and
stylesheets we can emit them in the order received with other arbitrary
preload types.

We will eventually add support for emitting suspensey image preloads
before other resources because these also block display however that
implementation will look at which images are actually rendered rather
than simply preloaded.

DiffTrain build for [cb3404a0cc](https://github.com/facebook/react/commit/cb3404a0ccd8b5edf5d2b90bd844742090e38f42)
2023-08-07 22:56:14 +00:00
gnoff eddb096d4b [Fizz] declare bootstrap script preloads to be fetchPriority: 'low' (#27189)
Generally scripts should not be preloaded before images but if they
arrive earlier than image preloads (or images) the network (or server)
may be saturated responding to inflight script preloads and not
sufficiently prioritize images arriving later. This change marks the
preloaded bootstrap script with a `low` fetch priority to signal to
supporting browsers that the request should be deprioritized. This
should make the preload operate similar to async script fetch priority
which is low by default according to https://web.dev/fetch-priority/

Additionally the bootstrap script preloads will emit before
preinitialized scripts do. Normal script preloads will continue to be
prioritized after stylesheets

This change can land separatrely but is part of a larger effort to
implement elevating image loading and making script loading less
blocking. Later changes will emit used suspensey images earlier in the
queue and will stop favoring scripts over images that are explicitly
preloaded

DiffTrain build for [9edf470d6e](https://github.com/facebook/react/commit/9edf470d6ed1f3ac12c23a248e64293f367c1797)
2023-08-07 22:50:28 +00:00
gnoff 9094b9cf83 [Fizz][Float] emit viewport meta before preloads (#27201)
Fixes: #27200

preloads for images that appear before the viewport meta may be loaded
twice because the proper device image information is not used with the
preload but is with the image itself. The viewport meta should be
emitted earlier than all preloads to avoid this.

this change moves the queue for the viewport meta to preconnects which
already has the right priority for this tag

DiffTrain build for [ea17cc18f4](https://github.com/facebook/react/commit/ea17cc18f458010c89c1bf494be08bb782d034af)
2023-08-07 22:28:35 +00:00
noahlemen c61c196106 chore: remove unused argument from schedule requestHostCallback (#27133)
Noticed this argument was left in the cleanup from
https://github.com/facebook/react/pull/27130
It seems to me like it would benefit from being cleaned up too.

DiffTrain build for [587ae49d71](https://github.com/facebook/react/commit/587ae49d71f218d34393291933d513d2975e22c3)
2023-07-20 14:35:18 +00:00
acdlite d36653fd40 Remove unused/redundant variables from Scheduler implementation (#27130)
Tidying up some redundant code left from previous iterations of the
implementation

DiffTrain build for [899cb95f52](https://github.com/facebook/react/commit/899cb95f52cc83ab5ca1eb1e268c909d3f0961e7)
2023-07-19 18:35:56 +00:00
noahlemen 1cb6c1f01b export dynamic disableSchedulerTimeoutInWorkLoop flag in www (#27117)
## Summary

This was not exposed as a dynamic flag in the build for facebook www. By
adding it, we'll be able to roll this out incrementally before cleaning
up this code altogether.

## How did you test this change?

`yarn build`

Before changes, `disableSchedulerTimeoutInWorkLoop` flag is not included
in ReactDOM-* build output for facebook www. Afterwards, it is included.

DiffTrain build for [9f4fbec5f7](https://github.com/facebook/react/commit/9f4fbec5f7bb639be6dac438f9da5f032ae12c15)
2023-07-17 19:49:57 +00:00
gnoff b7038da0f0 Add referrerPolicy option to ReactDOM.preload() (#27096)
DiffTrain build for [9377e10105](https://github.com/facebook/react/commit/9377e10105b41976c77c7f664f2363cb8c41ac8a)
2023-07-12 21:37:49 +00:00
noahlemen dd13f6d649 integrate scheduler.yield in SchedulerPostTask (#27069)
## Summary

`scheduler.yield` is entering [Origin Trial soon in Chrome
115](https://chromestatus.com/feature/6266249336586240). This diff adds
it to `SchedulerPostTask` when scheduling continuations to allow Origin
Trial participation for early feedback on the new API.

It seems the difference here versus the current use of `postTask` will
be minor – the intent behind `scheduler.yield` seems to mostly be better
ergonomics for scheduling continuations, but it may be interesting to
see if the follow aspect of it results in any tangible difference in
scheduling (from
[here](https://github.com/WICG/scheduling-apis/blob/main/explainers/yield-and-continuation.md#introduction)):

> To mitigate yielding performance penalty concerns, UAs prioritize
scheduler.yield() continuations over tasks of the same priority or
similar task sources.

## How did you test this change?

```
yarn test SchedulerPostTask
```

DiffTrain build for [0a360642dc](https://github.com/facebook/react/commit/0a360642dcc08cab469da0a0e4f1050e56b0ef7e)
2023-07-11 18:40:59 +00:00
noahlemen 7c79b2d2e1 rename SuspenseList export to unstable_SuspenseList (#27061)
## Summary

as we began [discussing
yesterday](https://github.com/facebook/react/pull/27056#discussion_r1253282784),
`SuspenseList` is not actually stable yet, and should likely be exported
with the `unstable_` prefix.

the conversation yesterday began discussing this in the context of the
fb-specific packages, but changing it there without updating everywhere
else leads to test failures, so here the change is made across packages.

## How did you test this change?

```
yarn flow dom-browser
yarn test
```

DiffTrain build for [eb2c2f7c2c](https://github.com/facebook/react/commit/eb2c2f7c2cf2652a168c2b433d2989131c69754b)
2023-07-06 18:15:41 +00:00
noahlemen 446d7988e5 Cleanup unused unstable_startTransition, unstable_useTransition, unstable_useDeferredValue exports from fb packages (#27056)
## Summary

came across these TODOs – an internal grep indicated that remaining
callsites have been cleaned up, so these can now be removed.

## How did you test this change?

```
yarn flow dom-browser
yarn test
```

DiffTrain build for [e91142dd69](https://github.com/facebook/react/commit/e91142dd69b0454e0d4e934c55dd541344fe32ca)
2023-07-05 21:28:41 +00:00
acdlite f35b3c79b8 [ESLint] Disallow hooks in async functions (#27045)
Hooks cannot be called in async functions, on either the client or the
server. This mistake sometimes happens when using Server Components,
especially when refactoring a Server Component to a Client Component.

React logs a warning at runtime, but it's even better to catch this with
a lint rule since it will show immediate inline feedback in the editor.

I added this to the existing "Rules of Hooks" ESLint rule.

DiffTrain build for [7118f5dd7b](https://github.com/facebook/react/commit/7118f5dd7bf5f1c44d0d2944ef8ad58e423909ad)
2023-07-05 15:49:31 +00:00
acdlite d8c7f591c9 Detect and warn about native async function components in development (#27031)
Adds a development warning to complement the error introduced by
https://github.com/facebook/react/pull/27019.

We can detect and warn about async client components by checking the
prototype of the function. This won't work for environments where async
functions are transpiled, but for native async functions, it allows us
to log an earlier warning during development, including in cases that
don't trigger the infinite loop guard added in
https://github.com/facebook/react/pull/27019. It does not supersede the
infinite loop guard, though, because that mechanism also prevents the
app from crashing.

I also added a warning for calling a hook inside an async function. This
one fires even during a transition. We could add a corresponding warning
to Flight, since hooks are not allowed in async Server Components,
either. (Though in both environments, this is better handled by a lint
rule.)

DiffTrain build for [5c8dabf886](https://github.com/facebook/react/commit/5c8dabf8864e1d826c831d6096b2dfa66309961a)
2023-07-02 02:49:24 +00:00
kassens 023fffcfff Revert "Fix: Detect infinite update loops caused by render phase updates (#26625)" (#27027)
This reverts commit 822386f252.

This broke a number of tests when synced internally. We'll need to
investigate the breakages before relanding this.

DiffTrain build for [7f362de158](https://github.com/facebook/react/commit/7f362de1588d98438787d652941533e21f2f332d)
2023-06-30 16:57:00 +00:00
acdlite 569cd7f8a4 Detect crashes caused by Async Client Components (#27019)
Suspending with an uncached promise is not yet supported. We only
support suspending on promises that are cached between render attempts.
(We do plan to partially support this in the future, at least in certain
constrained cases, like during a route transition.)

This includes the case where a component returns an uncached promise,
which is effectively what happens if a Client Component is authored
using async/await syntax.

This is an easy mistake to make in a Server Components app, because
async/await _is_ available in Server Components.

In the current behavior, this can sometimes cause the app to crash with
an infinite loop, because React will repeatedly keep trying to render
the component, which will result in a fresh promise, which will result
in a new render attempt, and so on. We have some strategies we can use
to prevent this — during a concurrent render, we can suspend the work
loop until the promise resolves. If it's not a concurrent render, we can
show a Suspense fallback and try again at concurrent priority.

There's one case where neither of these strategies work, though: during
a sync render when there's no parent Suspense boundary. (We refer to
this as the "shell" of the app because it exists outside of any loading
UI.)

Since we don't have any great options for this scenario, we should at
least error gracefully instead of crashing the app.

So this commit adds a detection mechanism for render loops caused by
async client components. The way it works is, if an app suspends
repeatedly in the shell during a synchronous render, without committing
anything in between, we will count the number of attempts and eventually
trigger an error once the count exceeds a threshold.

In the future, we will consider ways to make this case a warning instead
of a hard error.

See https://github.com/facebook/react/issues/26801 for more details.

DiffTrain build for [fc801116c8](https://github.com/facebook/react/commit/fc801116c80b68f7ebdaf66ac77d5f2dcd9e50eb)
2023-06-29 20:10:43 +00:00
acdlite f2e8115259 Fix: Detect infinite update loops caused by render phase updates (#26625)
This PR contains a regression test and two separate fixes: a targeted
fix, and a more general one that's designed as a last-resort guard
against these types of bugs (both bugs in app code and bugs in React).

I confirmed that each of these fixes separately are sufficient to fix
the regression test I added.

We can't realistically detect all infinite update loop scenarios because
they could be async; even a single microtask can foil our attempts to
detect a cycle. But this improves our strategy for detecting the most
common kind.

See commit messages for more details.

DiffTrain build for [822386f252](https://github.com/facebook/react/commit/822386f252fd1f0e949efa904a1ed790133329f7)
2023-06-27 17:32:08 +00:00
noahlemen c7d703ebb8 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.
-->

DiffTrain build for [80d9a40114](https://github.com/facebook/react/commit/80d9a40114bb43c07d021e8254790852f450bd2b)
2023-06-27 16:50:41 +00:00
tyao1 b52e425597 Fix disableStrictPassiveEffect not working under Suspense (#26989)
In https://github.com/facebook/react/pull/26914 I added an extra logic
to turn off double useEffect if there is an `Offscreen`
tag. But `Suspense` uses `Offscreen` tag internally and that turns off
`disableStrictPassiveEffect` for everything.

DiffTrain build for [70e998a106](https://github.com/facebook/react/commit/70e998a1064cc1e8e8f9103e0c00d37fbbcf71c1)
2023-06-22 20:18:31 +00:00
tyao1 ec1a04575d Add a temporary internal option to disable double useEffect in legacy strict mode (#26914)
<!--
  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?
-->
We are upgrading React 17 codebase to React18, and `StrictMode` has been
great for surfacing potential production bugs on React18 for class
components. There are non-trivial number of test failures caused by
double `useEffect` in StrictMode. To prioritize surfacing and fixing
issues that will break in production now, we need a flag to turn off
double `useEffect` for now in StrictMode temporarily. This is a
Meta-only hack for rolling out `createRoot` and we will fast follow to
remove it and use full strict mode.

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

DiffTrain build for [254cbdbd6d](https://github.com/facebook/react/commit/254cbdbd6d851a30bf3b649a6cb7c52786766fa4)
2023-06-21 18:20:59 +00:00
sebmarkbage 4a74dd599a Ensure updates are applied when diffInCommitPhase is on (#26977)
When we diffInCommitPhase there's no updatePayload, which caused no
update to be applied.

This is unfortunate because it would've been a lot easier to see this
oversight if we didn't have to support both flags.

I also carified that updateHostComponent is unnecessary in the new flag.
We reuse updateHostComponent for HostSingleton and HostHoistables since
it has a somewhat complex path but that means you have to remember when
editing updateHostComponent that it's not just used for that tag.
Luckily with the new flag, this is actually unnecessary since we just
need to mark it for update if any props have changed and then we diff it
later.

DiffTrain build for [d1c8cdae3b](https://github.com/facebook/react/commit/d1c8cdae3b20a670ee91b684e8e0ad0c400ae51c)
2023-06-20 01:29:40 +00:00
kassens 063f0e3001 [flow] upgrade to 0.209.0 (#26958)
Small update keeping us current with the latest version of Flow.

Flow changelog: https://github.com/facebook/flow/blob/main/Changelog.md

DiffTrain build for [613e6f5fca](https://github.com/facebook/react/commit/613e6f5fca3a7a63d115988d6312beb84d37b4db)
2023-06-16 14:02:53 +00:00
gnoff fc485c376b [Float][Fizz][Fiber] support imagesrcset and imagesizes for ReactDOM.preload() (#26940)
For float methods the href argument is usually all we need to uniquely
key the request. However when preloading responsive images it is
possible that you may need more than one preload for differing
imagesizes attributes. When using imagesrcset for preloads the href
attribute acts more like a fallback href. For keying purposes the
imagesrcset becomes the primary key conceptually.

This change updates the keying logic for `ReactDOM.preload()` when you
pass `{as: "image"}`

1. If `options.imageSrcSet` is a non-emtpy string the key is defined as
`options.imageSrcSet + options.imageSizes`. The `href` argument is still
required but does not participate in keying.
2. If `options.imageSrcSet` is empty, missing, or an invalid format the
key is defined as the `href`. Changing the `options.imageSizes` does not
affect the key as this option is inert when not using
`options.imageSrcSet`

Additionally, currently there is a bug in webkit (Safari) that causes
preload links to fail to use imageSrcSet and fallback to href even when
the browser will correctly resolve srcset on an `<img>` tag. Because the
drawbacks of preloading the wrong image (href over imagesrcset) in a
modern browser outweight the drawbacks of not preloading anything for
responsive images in browsers that do not support srcset at all we will
omit the `href` attribute whenever `options.imageSrcSet` is provided. We
still require you provide an href since we want to be able to revert
this behavior once all major browsers support it

bug link: https://bugs.webkit.org/show_bug.cgi?id=231150

DiffTrain build for [fc929cf4ea](https://github.com/facebook/react/commit/fc929cf4ead35f99c4e9612a95e8a0bb8f5df25d)
2023-06-15 21:56:16 +00:00
gnoff b437e4d88b [Float] Nonce preload support (#26939)
Some browsers, with some CSP configuration, will not preload a script if
the prelaod link tag does not provide a valid nonce attribute. This
change adds the ability to specify a nonce for `ReactDOM.preload(..., {
as: "script" })`

DiffTrain build for [86acc10f25](https://github.com/facebook/react/commit/86acc10f2596e1a6fe2fd57a5b325de85175800b)
2023-06-15 20:46:42 +00:00
gnoff 1d94a43c45 [Float][Fizz] add crossOrigin support for preloading bootstrap scripts and bootstrap modules (#26942)
The recently merged support for crossorigin in bootstrap scripts did not
implement the functionality for preloading. This adds it

see #26844

DiffTrain build for [a7bf5ba614](https://github.com/facebook/react/commit/a7bf5ba614c6ddbd1eb3057c71f72efd1b6c21a9)
2023-06-13 21:05:41 +00:00
gnoff 717bf322f9 Add support for 'crossorigin' attribute on bootstrapScripts and bootstrapModules (#26844)
base build ci job failing but this change is unrelated and I think it is just flake with the builds host application

DiffTrain build for [90229eb925](https://github.com/facebook/react/commit/90229eb925e2330667fb7c023a5c4317c7ae8363)
2023-06-13 16:17:48 +00:00
sebmarkbage b2a908fe42 [Flight] Add bundler-less version of RSC using plain ESM (#26889)
This isn't really meant to be actually used, there are many issues with
this approach, but it shows the capabilities as a proof-of-concept.

It's a new reference implementation package `react-server-dom-esm` as
well as a fixture in `fixtures/flight-esm` (fork of `fixtures/flight`).
This works pretty much the same as pieces we already have in the Webpack
implementation but instead of loading modules using Webpack on the
client it uses native browser ESM.

To really show it off, I don't use any JSX in the fixture and so it also
doesn't use Babel or any compilation of the files.

This works because we don't actually bundle the server in the reference
implementation in the first place. We instead use [Node.js
Loaders](https://nodejs.org/api/esm.html#loaders) to intercept files
that contain `"use client"` and `"use server"` and replace them. There's
a simple check for those exact bytes, and no parsing, so this is very
fast.

Since the client isn't actually bundled, there's no module map needed.
We can just send the file path to the file we want to load in the RSC
payload for client references.

Since the existing reference implementation for Node.js already used ESM
to load modules on the server, that all works the same, including Server
Actions. No bundling.

There is one case that isn't implemented here. Importing a `"use
server"` file from a Client Component. We don't have that implemented in
the Webpack reference implementation neither - only in Next.js atm. In
Webpack it would be implemented as a Webpack loader.

There are a few ways this can be implemented without a bundler:

- We can intercept the request from the browser importing this file in
the HTTP server, and do a quick scan for `"use server"` in the file and
replace it just like we do with loaders in Node.js. This is effectively
how Vite works and likely how anyone using this technique would have to
support JSX anyway.
- We can use native browser "loaders" once that's eventually available
in the same way as in Node.js.
- We can generate import maps for each file and replace it with a
pointer to a placeholder file. This requires scanning these ahead of
time which defeats the purposes.

Another case that's not implemented is the inline `"use server"` closure
in a Server Component. That would require the existing loader to be a
bit smarter but would still only "compile" files that contains those
bytes in the fast path check. This would also happen in the loader that
already exists so wouldn't do anything substantially different than what
we currently have here.

DiffTrain build for [f181ba8aa6](https://github.com/facebook/react/commit/f181ba8aa6339d62f6e2572109c61242606f16b3)
2023-06-03 20:03:38 +00:00
gnoff 650431a15f [Fizz][Float] stop automatically preloading scripts that are not script resources (#26877)
Currently we preload all scripts that are not hoisted. One of the
original reasons for this is we stopped SSR rendering async scripts that
had an onLoad/onError because we needed to be able to distinguish
between Float scripts and non-Float scripts during hydration. Hydration
has been refactored a bit and we can not get around this limitation so
we can just emit the async script in place. However, sync and defer
scripts are also preloaded. While this is sometimes desirable it is not
universally so and there are issues with conveying priority properly
(see fetchpriority) so with this change we remove the automatic
preloading of non-Float scripts altogether.

For this change to make sense we also need to emit async scripts with
loading handlers during SSR. we previously only preloaded them during
SSR because it was necessary to keep async scripts as unambiguously
resources when hydrating. One ancillary benefit was that load handlers
would always fire b/c there was no chance the script would run before
hydration. With this change we go back to having the ability to have
load handlers fired before hydration. This is already a problem with
images and we don't have a generalized solution for it however our
likely approach to this sort of thing where you need to wait for a
script to load is to use something akin to `importScripts()` rather than
rendering a script with onLoad.

DiffTrain build for [e1ad4aa361](https://github.com/facebook/react/commit/e1ad4aa3615333009d76f947ff05ddeff01039c6)
2023-06-01 20:39:44 +00:00
gnoff 54ded05484 [Fizz][Float] stop preloading stylesheets that are not stylesheet resources (#26873)
We previously preloaded stylesheets that were rendered in Fizz. The idea
was we'd get a headstart fetching these resources since we know they are
going to be rendered. However to really be effective non-float
stylesheets need to rendered in the head and the preload here is not
helpful and potentially hurtful to perf in a minor way. This change
removes this functionality to make the code smaller and simpler

DiffTrain build for [5fb2c15a89](https://github.com/facebook/react/commit/5fb2c15a89de844a1dd12a61e7674e55dc0dfa89)
2023-06-01 20:29:45 +00:00
gnoff ee61e4af9e [Float] support fetchpriority on ReactDOM.preload() and ReactDOM.preinit() (#26880)
exposes fetchPriority as an option for `ReactDOM.preload()` and
`ReactDOM.preinit()`

the typings should be `'high' | 'low' | 'auto'`

DiffTrain build for [042d8f606c](https://github.com/facebook/react/commit/042d8f606ce643d2eca955badbf07ea5b8ac266c)
2023-06-01 20:17:46 +00:00
tyao1 d6f9de5ae1 Always trigger componentWillUnmount in StrictMode (#26842)
<!--
  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 StrictMode, React currently only triggers `componentWillUnmount` if
`componentDidMount` is defined. This would miss detecting issues like
initializing resources in constructor or componentWillMount, for
example:
```
class Component {
  constructor() {
     this._subscriptions = new Subscriptions();
  }
  componentWillUnmount() {
     this._subscriptions.reset();
  }
}
```

The PR makes `componentWillUnmount` always run in StrictMode.

## 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.
-->
`yarn test ci`

DiffTrain build for [811022232e](https://github.com/facebook/react/commit/811022232efed62a3c943701bc99d18655bc78b3)
2023-06-01 17:40:28 +00:00
rickhanlonii 9908c7d696 Clean up enableSyncDefaultUpdates flag a bit (#26858)
## Overview

Does a few things:
- Renames `enableSyncDefaultUpdates` to
`forceConcurrentByDefaultForTesting`
- Changes the way it's used so it's dead-code eliminated separate from
`allowConcurrentByDefault`
- Deletes a bunch of the gated code

The gates that are deleted are unnecessary now. We were keeping them
when we originally thought we would come back to being concurrent by
default. But we've shifted and now sync-by default is the desired
behavior long term, so there's no need to keep all these forked tests
around.

I'll follow up to delete more of the forked behavior if possible.
Ideally we wouldn't need this flag even if we're still using
`allowConcurrentByDefault`.

DiffTrain build for [018c58c9c6](https://github.com/facebook/react/commit/018c58c9c65452cff25aaf1f38f78a9b90d8e5c1)
2023-06-01 13:31:21 +00:00