Commit Graph

15470 Commits

Author SHA1 Message Date
Andrew Clark 4a2d86bddb Don't reset work loop until stack is unwound
When replaying a suspended function components, we want to reuse the
hooks that were computed during the original render.

Currently we reset the state of the hooks right after the component 
suspends (or throws an error). This is too early because it doesn't 
give us an opportunity to wait for the promise to resolve.

This refactors the work loop to reset the hooks right before unwinding
instead of right after throwing. It doesn't include any other changes
yet, so there should be no observable behavioral change.
2022-11-17 14:48:42 -05:00
Andrew Clark 9dfbd9fa90 use: Don't suspend if there are pending updates
Before suspending, check if there are other pending updates that might
possibly unblock the suspended component. If so, interrupt the current
render and switch to working on that.

This logic was already implemented for the old "throw a Promise"
Suspense but has to be replicated for `use` because it suspends the
work loop much earlier.

I'm getting a little anxious about the divergence between the two
Suspense patterns. I'm going to look into enabling the new behavior for
the old pattern so that we can unify the implementations.
2022-11-17 14:48:42 -05:00
Andrew Clark 44c4e6f4dd
Force unwind work loop during selective hydration (#25695)
When an update flows into a dehydrated boundary, React cannot apply the
update until the boundary has finished hydrating. The way this currently
works is by scheduling a slightly higher priority task on the boundary,
using a special lane that's reserved only for this purpose. Because the
task is slightly higher priority, on the next turn of the work loop, the
Scheduler will force the work loop to yield (i.e. shouldYield starts
returning `true` because there's a higher priority task).

The downside of this approach is that it only works when time slicing is
enabled. It doesn't work for synchronous updates, because the
synchronous work loop does not consult the Scheduler on each iteration.

We plan to add support for selective hydration during synchronous
updates, too, so we need to model this some other way.

I've added a special internal exception that can be thrown to force the
work loop to interrupt the work-in-progress tree. Because it's thrown
from a React-only execution stack, throwing isn't strictly necessary —
we could instead modify some internal work loop state. But using an
exception means we don't need to check for this case on every iteration
of the work loop. So doing it this way moves the check out of the fast
path.

The ideal implementation wouldn't need to unwind the stack at all — we
should be able to hydrate the subtree and then apply the update all
within a single render phase. This is how we intend to implement it in
the future, but this requires a refactor to how we handle "stack"
variables, which are currently pushed to a per-render array. We need to
make this stack resumable, like how context works in Flight and Fizz.
2022-11-17 13:51:33 -05:00
Sebastian Markbåge 7b17f7bbf3
Enable warning for defaultProps on function components for everyone (#25699)
This also fixes a gap where were weren't warning on memo components.
2022-11-17 12:22:23 -05:00
Sebastian Silbermann 6fb8133ed3
Turn on string ref deprecation warning for everybody (not codemoddable) (#25383)
## Summary
 
Alternate to https://github.com/facebook/react/pull/25334 without any
prod runtime changes i.e. the proposed codemod in
https://github.com/reactjs/rfcs/blob/createlement-rfc/text/0000-create-element-changes.md#deprecate-string-refs-and-remove-production-mode-_owner-field
would not work.

## How did you test this change?

- [x] CI
- [x] `yarn test` with and without `warnAboutStringRefs`
2022-11-16 19:15:57 -05:00
Sebastian Markbåge 07f46ecf2e
Turn on key spread warning in jsx-runtime for everyone (#25697)
This improves the error message a bit and ensures that we recommend
putting the key first, not last, which ensures that the faster
`jsx-runtime` is used.

This only affects the modern "automatic" JSX transform.
2022-11-16 18:57:50 -05:00
Sebastian Markbåge d65b88d031
Eagerly initialize an mutable object for instance.refs (#25696)
This micro-optimization never made sense and less so now that they're
rare.

This still initializes the class with a shared immutable object in the
constructor - which is also what createClass() does.

Then we override it during mount. This is done in case someone messes up
the initialization of the super() constructor for example, which was
more common in polyfills.

This change means that if a ref is initialized during the constructor
itself it wouldn't be lazily initialized but that's not user code that
does it, it's React so that shouldn't happen.

This makes string refs codemoddable as described in.
https://github.com/facebook/react/pull/25334
2022-11-16 15:16:54 -05:00
dependabot[bot] db8a3fcc31
Bump loader-utils from 1.4.0 to 1.4.2 in /fixtures/fizz (#25680)
[//]: # (dependabot-start)
⚠️  **Dependabot is rebasing this PR** ⚠️ 

Rebasing might not happen immediately, so don't worry if this takes some
time.

Note: if you make any changes to this PR yourself, they will take
precedence over the rebase.

---

[//]: # (dependabot-end)

Bumps [loader-utils](https://github.com/webpack/loader-utils) from 1.4.0
to 1.4.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/webpack/loader-utils/releases">loader-utils's
releases</a>.</em></p>
<blockquote>
<h2>v1.4.2</h2>
<h3><a
href="https://github.com/webpack/loader-utils/compare/v1.4.1...v1.4.2">1.4.2</a>
(2022-11-11)</h3>
<h3>Bug Fixes</h3>
<ul>
<li>ReDoS problem (<a
href="https://github-redirect.dependabot.com/webpack/loader-utils/issues/226">#226</a>)
(<a
href="17cbf8fa89">17cbf8f</a>)</li>
</ul>
<h2>v1.4.1</h2>
<h3><a
href="https://github.com/webpack/loader-utils/compare/v1.4.0...v1.4.1">1.4.1</a>
(2022-11-07)</h3>
<h3>Bug Fixes</h3>
<ul>
<li>security problem (<a
href="https://github-redirect.dependabot.com/webpack/loader-utils/issues/220">#220</a>)
(<a
href="4504e34c47">4504e34</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/webpack/loader-utils/blob/v1.4.2/CHANGELOG.md">loader-utils's
changelog</a>.</em></p>
<blockquote>
<h3><a
href="https://github.com/webpack/loader-utils/compare/v1.4.1...v1.4.2">1.4.2</a>
(2022-11-11)</h3>
<h3>Bug Fixes</h3>
<ul>
<li>ReDoS problem (<a
href="https://github-redirect.dependabot.com/webpack/loader-utils/issues/226">#226</a>)
(<a
href="17cbf8fa89">17cbf8f</a>)</li>
</ul>
<h3><a
href="https://github.com/webpack/loader-utils/compare/v1.4.0...v1.4.1">1.4.1</a>
(2022-11-07)</h3>
<h3>Bug Fixes</h3>
<ul>
<li>security problem (<a
href="https://github-redirect.dependabot.com/webpack/loader-utils/issues/220">#220</a>)
(<a
href="4504e34c47">4504e34</a>)</li>
</ul>
<p><!-- raw HTML omitted --><!-- raw HTML omitted --></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="331ad5067d"><code>331ad50</code></a>
chore(release): 1.4.2</li>
<li><a
href="17cbf8fa89"><code>17cbf8f</code></a>
fix: ReDoS problem (<a
href="https://github-redirect.dependabot.com/webpack/loader-utils/issues/226">#226</a>)</li>
<li><a
href="8f082b39f6"><code>8f082b3</code></a>
chore(release): 1.4.1</li>
<li><a
href="4504e34c47"><code>4504e34</code></a>
fix: security problem (<a
href="https://github-redirect.dependabot.com/webpack/loader-utils/issues/220">#220</a>)</li>
<li>See full diff in <a
href="https://github.com/webpack/loader-utils/compare/v1.4.0...v1.4.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=loader-utils&package-manager=npm_and_yarn&previous-version=1.4.0&new-version=1.4.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
- `@dependabot use these labels` will set the current labels as the
default for future PRs for this repo and language
- `@dependabot use these reviewers` will set the current reviewers as
the default for future PRs for this repo and language
- `@dependabot use these assignees` will set the current assignees as
the default for future PRs for this repo and language
- `@dependabot use this milestone` will set the current milestone as the
default for future PRs for this repo and language

You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/facebook/react/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-16 13:19:42 -05:00
dependabot[bot] 355dd7d9dc
Bump loader-utils from 2.0.0 to 2.0.4 in /fixtures/flight (#25694)
Bumps [loader-utils](https://github.com/webpack/loader-utils) from 2.0.0
to 2.0.4.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/webpack/loader-utils/releases">loader-utils's
releases</a>.</em></p>
<blockquote>
<h2>v2.0.4</h2>
<h3><a
href="https://github.com/webpack/loader-utils/compare/v2.0.3...v2.0.4">2.0.4</a>
(2022-11-11)</h3>
<h3>Bug Fixes</h3>
<ul>
<li>ReDoS problem (<a
href="https://github-redirect.dependabot.com/webpack/loader-utils/issues/225">#225</a>)
(<a
href="ac09944dfa">ac09944</a>)</li>
</ul>
<h2>v2.0.3</h2>
<h3><a
href="https://github.com/webpack/loader-utils/compare/v2.0.1...v2.0.3">2.0.3</a>
(2022-10-20)</h3>
<h3>Bug Fixes</h3>
<ul>
<li><strong>security:</strong> prototype pollution exploit (<a
href="https://github-redirect.dependabot.com/webpack/loader-utils/issues/217">#217</a>)
(<a
href="a93cf6f470">a93cf6f</a>)</li>
</ul>
<h2>v2.0.2</h2>
<h3><a
href="https://github.com/webpack/loader-utils/compare/v2.0.1...v2.0.2">2.0.2</a>
(2021-11-04)</h3>
<h3>Bug Fixes</h3>
<ul>
<li>base64 generation and unicode characters (<a
href="https://github-redirect.dependabot.com/webpack/loader-utils/issues/197">#197</a>)
(<a
href="8c2d24ee40">8c2d24e</a>)</li>
</ul>
<h2>v2.0.1</h2>
<h3><a
href="https://github.com/webpack/loader-utils/compare/v2.0.0...v2.0.1">2.0.1</a>
(2021-10-29)</h3>
<h3>Bug Fixes</h3>
<ul>
<li>md4 support on Node.js v17 (<a
href="https://github-redirect.dependabot.com/webpack/loader-utils/issues/193">#193</a>)
(<a
href="1069f61284">1069f61</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/webpack/loader-utils/blob/v2.0.4/CHANGELOG.md">loader-utils's
changelog</a>.</em></p>
<blockquote>
<h3><a
href="https://github.com/webpack/loader-utils/compare/v2.0.3...v2.0.4">2.0.4</a>
(2022-11-11)</h3>
<h3>Bug Fixes</h3>
<ul>
<li>ReDoS problem (<a
href="https://github-redirect.dependabot.com/webpack/loader-utils/issues/225">#225</a>)
(<a
href="ac09944dfa">ac09944</a>)</li>
</ul>
<h3><a
href="https://github.com/webpack/loader-utils/compare/v2.0.1...v2.0.3">2.0.3</a>
(2022-10-20)</h3>
<h3>Bug Fixes</h3>
<ul>
<li><strong>security:</strong> prototype pollution exploit (<a
href="https://github-redirect.dependabot.com/webpack/loader-utils/issues/217">#217</a>)
(<a
href="a93cf6f470">a93cf6f</a>)</li>
</ul>
<h3><a
href="https://github.com/webpack/loader-utils/compare/v2.0.1...v2.0.2">2.0.2</a>
(2021-11-04)</h3>
<h3>Bug Fixes</h3>
<ul>
<li>base64 generation and unicode characters (<a
href="https://github-redirect.dependabot.com/webpack/loader-utils/issues/197">#197</a>)
(<a
href="8c2d24ee40">8c2d24e</a>)</li>
</ul>
<h3><a
href="https://github.com/webpack/loader-utils/compare/v2.0.0...v2.0.1">2.0.1</a>
(2021-10-29)</h3>
<h3>Bug Fixes</h3>
<ul>
<li>md4 support on Node.js v17 (<a
href="https://github-redirect.dependabot.com/webpack/loader-utils/issues/193">#193</a>)
(<a
href="1069f61284">1069f61</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="6688b50281"><code>6688b50</code></a>
chore(release): 2.0.4</li>
<li><a
href="ac09944dfa"><code>ac09944</code></a>
fix: ReDoS problem (<a
href="https://github-redirect.dependabot.com/webpack/loader-utils/issues/225">#225</a>)</li>
<li><a
href="7162619fb9"><code>7162619</code></a>
chore(release): 2.0.3</li>
<li><a
href="a93cf6f470"><code>a93cf6f</code></a>
fix(security): prototype polution exploit (<a
href="https://github-redirect.dependabot.com/webpack/loader-utils/issues/217">#217</a>)</li>
<li><a
href="90c7c4be17"><code>90c7c4b</code></a>
chore(release): 2.0.2</li>
<li><a
href="8c2d24ee40"><code>8c2d24e</code></a>
fix: base64 generation and unicode characters (<a
href="https://github-redirect.dependabot.com/webpack/loader-utils/issues/197">#197</a>)</li>
<li><a
href="5fb5562084"><code>5fb5562</code></a>
chore(release): 2.0.1</li>
<li><a
href="1069f61284"><code>1069f61</code></a>
fix: md4 support on Node.js v17 (<a
href="https://github-redirect.dependabot.com/webpack/loader-utils/issues/193">#193</a>)</li>
<li>See full diff in <a
href="https://github.com/webpack/loader-utils/compare/v2.0.0...v2.0.4">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=loader-utils&package-manager=npm_and_yarn&previous-version=2.0.0&new-version=2.0.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
- `@dependabot use these labels` will set the current labels as the
default for future PRs for this repo and language
- `@dependabot use these reviewers` will set the current reviewers as
the default for future PRs for this repo and language
- `@dependabot use these assignees` will set the current assignees as
the default for future PRs for this repo and language
- `@dependabot use this milestone` will set the current milestone as the
default for future PRs for this repo and language

You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/facebook/react/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-16 13:16:39 -05:00
Jan Kassens c343f80254
[react-float] feature detect getRootNode (#25689)
Some old environments like IE11 or very old versions of jsdom are
missing `getRootNode()`. Use feature detection to fall back to
`ownerDocuments` in these environments that also won't be supporting
shadow DOM anyway.
2022-11-16 13:12:04 -05:00
Sebastian Markbåge e1dd0a2f54
Remove recoverable error when a sync update flows into a dehydrated boundary (#25692)
This just removes the error but the underlying issue is still there, and
it's likely that the best course of action is to not update in effects
and to wrap most updates in startTransition. However, that's more of a
performance concern which is not something we generally do even in
recoverable errors since they're less actionable and likely belong in
another channel. It is also likely that in many cases this happens so
rarely because you have to interact quickly enough that it can often be
ignored.

After changes to other parts of the model, this only happens for
sync/discrete updates. There are three scenarios that can happen:
- We replace a server rendered fallback with a client rendered fallback.
Other than this potentially causing some flickering in the loading
state, it's not a big deal.
- We replace the server rendered content with a client side fallback if
this suspends on the client. This is in line with what would happen
anyway. We will loose state of forms which is not intended semantics.
State and animations etc would've been lost anyway if it was client-side
so that's not a concern.
- We replace the server rendered content with a client side rendered
tree and lose selection/state and form state. While the content looks
the same, which is unfortunate.

In most scenarios it's a bad loading state but it's the same scenario as
flushing sync client-side. So it's not so bad.

The big change here is that we consider this a bug of React that we
should fix. Therefore it's not actionable to users today because it
should just get fixed. So we're removing the error early. Although
anyone that has fixed these issues already are probably better off for
it.

To fix this while still hydrating we need to be able to rewind a sync
tree and then replay it.

@tyao1 is going to add a Sync hydration lane. This is will allow us to
rewind the tree when we hit this state, and replay it given the previous
Context, hydrate and then reapply the update. The reason we didn't do
this originally is because it causes sync mode to unwind where as for
backwards compatibility we didn't want to cause that breaking semantic -
outside Suspense boundaries - and we don't want that semantic longer
term. We're only do this as a short term fix.

We should also have a way to leave a partial tree in place. If the sync
hydration lane suspends, we should be able to switch to a client side
fallback without throwing away the state of the DOM and then hydrate
later.

We now know how we want to fix this longer term. We're going to move all
Contexts into resumable trees like what Fizz/Flight does. That way we
can leave the original Context at the hydration boundaries and then
resume from there. That way the rewinding would never happen even in the
existence of a sync hydration lane which would only apply locally to the
dehydrated tree.

So the steps are 1) remove the error 2) add the sync hydration lane with
rewinding 3) Allow hiding server-rendered content while still not
hydrated 4) add resumable contexts at these boundaries.

Fixes #25625 and #24959.
2022-11-15 22:10:54 -05:00
Mengdi Chen c54e3541b2
[DevTools] bug fix for Hydrating fibers (#25663)
## Summary

This PR is to fix a bug: an "element cannot be found" error when
hydrating Server Components

### The problem
<img width="1061" alt="image"
src="https://user-images.githubusercontent.com/1001890/201206046-ac32a5e3-b08a-4dc2-99f4-221dad504b28.png">

To reproduce:
1. setting up a vercel next.js 13 playground locally
https://github.com/vercel/app-playground
2. visit http://localhost:3000/loading
3. click "electronics" button to navigate to
http://localhost:3000/loading/electronics to trigger hydrating
4. inspect one of the skeleton card UI from React DevTools extension

### The root cause & fix
This bug was introduced in #22527. When syncing reconciler changes, the
value of `Hydrating` was copied from another variable `Visibility` (one
more zero in the binary number).
To avoid this kind of issue in the future, a new file `ReactFiberFlags`
is created following the same format of the one in reconciler, so that
it's easier to sync the number without making mistakes.
The reconciler fiber flag file is also updated to reflect which of the
flags are used in devtools

## How did you test this change?

I build it locally and the bug no longer exist on
http://localhost:3000/loading
2022-11-11 15:18:06 -05:00
Samuel Susla d1e35c7039
Don't disappear layout effects unnecessarily (#25660)
Nested Offscreens can run into a case where outer Offscreen is revealed
while inner one is hidden in a single commit. This is an edge case that
was previously missed. We need to prevent call to disappear layout
effects.

When we go from state:
```jsx
<Offscreen mode={'hidden'}> // outer offscreen
  <Offscreen mode={'visible'}> // inner offscreen
    {children}
  </Offscreen>
</Offscreen>
```

To following. Notice that visibility of each offscreen flips.

```jsx
<Offscreen mode={'visible'}> // outer offscreen
  <Offscreen mode={'hidden'}> // inner offscreen
    {children}
  </Offscreen>
</Offscreen>
```

Inner offscreen must not call
`recursivelyTraverseDisappearLayoutEffects`.
Check unit tests for an example of this.
2022-11-10 14:49:30 +00:00
Aurélien Chivot-Buhler 1e3e30dae2
Fix useSyncExternalStore dropped update when state is dispatched in render phase (#25578)
Fix https://github.com/facebook/react/issues/25565
2022-11-08 11:25:42 +01:00
Mengdi Chen 18dff7990a
[DevTools] add support for HostSingleton & HostResource (#25616)
## Summary

This is to support two new reconciler work tags `HostSingleton` and
`HostResource` introduced in PRs #25243 #25426. The behavior is
described below.
I also renamed an option in components settings from an internal concept
"host" to more understood "dom nodes"

## How did you test this change?

Tested on the latest Vercel playground app
https://github.com/vercel/app-playground/

Before the change, devtools cannot show correct display name for these
new elements. Also, some unnecessary internal details are exposed to
users.
<img width="1395" alt="image"
src="https://user-images.githubusercontent.com/1001890/199578181-c4e4ea74-baa1-4507-83d0-91a62ad7de5f.png">

After the change, the display names are correctly shown and the "state"
would always be hidden in the detail view.
<img width="1417" alt="image"
src="https://user-images.githubusercontent.com/1001890/199578442-adc1951d-7d5b-4b84-ad64-85bcf7a8ebcc.png">

These elements will also be hidden just like other native dom elements
(e.g. `<div>`)
<img width="836" alt="image"
src="https://user-images.githubusercontent.com/1001890/199578598-2dfacf64-ddc9-42b5-a246-dd0b09f629af.png">
2022-11-07 15:23:17 -05:00
Samuel Susla 4bd245e9ee
Do not unmount layout effects if ancestor Offscreen is hidden (#25628)
This is a follow up on https://github.com/facebook/react/pull/25592

There is another condition Offscreen calls
`recursivelyTraverseDisappearLayoutEffects` when it shouldn't. Offscreen
may be nested. When nested Offscreen is hidden, it should only unmount
layout effects if it meets following conditions:
1. This is an update, not first mount.
2. This Offscreen was hidden before.
3. No ancestor Offscreen is hidden.

Previously, we were not accounting for the third condition.
2022-11-04 13:31:07 +00:00
Andrew Clark df61e708c8
Remove check in renderDidSuspendDelayIfPossible (#25630)
I don't think we need this anymore. It was added originally because
RootSuspended would take priority over RootSuspendedWithDelay. But we've
since changed it: any "bad" fallback state is permitted to block a
"good" fallback state.

The other status flags that this check used to account for are
RootDidNotComplete and RootFatalErrored:

- RootFatalErrored is like an invariant violation, it means something
went really wrong already and we can't recover from it
- RootCompleted and RootDidNotComplete are only set at the very end of
the work loop, there's no way for renderDidSuspendDelayIfPossible to
sneak in after that (at least none that I can think of — it's only
called from the render phase)

So I think we can just delete this.

It's entirely possible there's some scenario I haven't considered,
though, which is why I'm submitting this change as its own PR. To
preserve the ability to bisect to it later.
2022-11-03 16:15:55 -04:00
mofeiZ 1a08f1478d
[ServerRenderer] Move fizz external runtime implementation to react-dom-bindings (#25617)
<!--
  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 debug-test --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
-->

Following
[comment](https://github.com/facebook/react/pull/25437#discussion_r1010944983)
in #25437 , the external runtime implementation should be moved from
`react-dom` to `react-dom-bindings`.

I did have a question here:
I set the entrypoint to `react-dom/unstable_server-external-runtime.js`,
since a.) I was following #25436 as an example and b.)
`react-dom-bindings` was missing a `README.md` and `npm/`. This also
involved adding the external runtime to `package.json`.
However, the external runtime isn't really a `react-dom` entrypoint. Is
this change alright, or should I change the bundling code instead?
## 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.
-->
2022-11-03 11:15:29 -04:00
Andrew Clark 1a902623a8
Unwrap sync resolved thenables without suspending (#25615)
If a thenable resolves synchronously, `use` should unwrap its result
without suspending or interrupting the component's execution.
2022-11-02 13:53:23 -04:00
Josh Story 4ea063b56f
refactor isHostResourceType to not receive the context from reconciler and not leak types (#25610)
type validateDOMNesting
move `isHostResourceType` to ReactDOMHostConfig
type `AncestorInfo`
refactor `resourceFormOnly` into `ancestorInfo.containerTagInScope`
provide hostContext from reconciler
2022-11-01 17:14:46 -07:00
Sebastian Markbåge 8e69bc45aa
Make host context use null as empty and only error in dev (#25609)
Makes it slightly more blazing.

No host config actually uses null as any useful and we use this as a
placeholder value anyway. It's also better for perf since it doesn't let
two different hidden classes pass around. It's also a magic place holder
that triggers error if we do try to access anything from it.
2022-11-01 19:02:37 -04:00
Josh Story 5f7ef8c4cb
[Float] handle resource Resource creation inside svg context (#25599)
`title` is a valid element descendent of `svg`. this PR adds a
prohibition on turning titles in svg into Resources.

This PR also adds additional warnings if you render something that is
almost a Resource inside an svg.
2022-11-01 14:57:45 -07:00
Andrew Clark 36426e6cb6
Allow uncached IO to stablize (#25561)
Initial draft. I need to test this more.

If a promise is passed to `use`, but the I/O isn't cached, we should
still be able to unwrap it.

This already worked in Server Components, and during SSR.

For Fiber (in the browser), before this fix the state would get lost
between attempts unless the promise resolved immediately in a microtask,
which requires IO to be cached. This was due to an implementation quirk
of Fiber where the state is reset as soon as the stack unwinds. The
workaround is to suspend the entire Fiber work loop until the promise
resolves.

The Server Components and SSR runtimes don't require a workaround: they
can maintain multiple parallel child tasks and reuse the state
indefinitely across attempts. That's ideally how Fiber should work, too,
but it will require larger refactor.

The downside of our approach in Fiber is that it won't "warm up" the
siblings while you're suspended, but to avoid waterfalls you're supposed
to hoist data fetches higher in the tree regardless. But we have other
ideas for how we can add this back in the future. (Though again, this
doesn't affect Server Components, which already have the ideal
behavior.)
2022-11-01 15:00:34 -04:00
mofeiZ 6883d79445
[ServerRenderer] Setup for adding data attributes streaming format (#25567) 2022-11-01 12:04:50 -04:00
Samuel Susla ab075a2324
Do not unmount layout effects on initial Offscreen mount (#25592)
`wasHidden` is evaluted to false if `current` is null. This means
Offscreen has never been shown but this code assumes it is going from
'visible' to 'hidden' and unmounts layout effects.
To fix this, only unmount layout effects if `current` is not null.

I'm not able to repro this problem or write unit test for it. I see this
crash bug in production test.
The problem with repro is that if Offscreen starts as hidden, it's
render is deferred and current is no longer null.
2022-11-01 15:11:28 +00:00
Sebastian Markbåge 765805bf88
Fix type check for null (#25595) 2022-10-31 17:29:01 -04:00
Andrew Clark 2ac77aab94
Clean up vestige of useOpaqueIdentifier (#25587)
Found some code that was left over from the experimental
useOpaqueIdentifier hook, which we eventually replaced with useId.

This deletes it.
2022-10-29 20:46:54 -04:00
Andrew Clark bdd3d0807c Extract logic for detecting bad fallback to helper
Pure refactor, no change in behavior.

Extracts the logic for detecting whether a suspended component will
result in a "bad" Suspense fallback into a helper function. An example
of a bad Suspense fallback is one that causes already-visible content
to disappear.

I want to reuse this same logic in the work loop, too.
2022-10-28 17:19:45 -07:00
Andrew Clark 952dfff3f1 Split suspended work loop logic into separate functions
Refactors the logic for handling when the work loop is suspended into
separate functions for replaying versus unwinding. This allows us to
hoist certain checks into the caller.

For example, when rendering due to flushSync, we will always unwind the
stack without yielding the microtasks.

No intentional behavior change in this commit.
2022-10-28 17:19:45 -07:00
Andrew Clark d2c0ab10de In work loop, add enum of reasons for suspending
This is a pure refactor, no change to behavior.

When a component throws, the work loop can handle that in one of several
ways — unwind immediately, wait for microtasks, and so on. I'm about
to add another one, too. So I've changed the variable that tracks
whether the work loop is suspended from a boolean
(workInProgressIsSuspended) to an enum (workInProgressSuspendedReason).
2022-10-28 17:19:45 -07:00
Andrew Clark 5450dd4098
Strict Mode: Reuse memoized result from first pass (#25583)
In Strict Mode, during development, user functions are double invoked to
help detect side effects. Currently, the way we implement this is to
completely discard the first pass and start over. Theoretically this
should be fine because components are idempotent. However, it's a bit
tricky to get right because our implementation (i.e. `renderWithHooks`)
is not completely idempotent with respect to internal data structures,
like the work-in-progress fiber. In the past we've had to be really
careful to avoid subtle bugs — for example, during the initial mount,
`setState` functions are bound to the particular hook instances that
were created during that render. If we compute new hook instances, we
must also compute new children, and they must correspond to each other.

This commit addresses a similar issue that came up related to `use`:
when something suspends, `use` reuses the promise that was passed during
the first attempt. This is itself a form of memoization. We need to be
able to memoize the reactive inputs to the `use` call using a hook (i.e.
`useMemo`), which means, the reactive inputs to `use` must come from the
same component invocation as the output.

The solution I've chosen is, rather than double invoke the entire
`renderWithHook` function, we should double invoke each individual user
function. It's a bit confusing but here's how it works:

We will invoke the entire component function twice. However, during the
second invocation of the component, the hook state from the first
invocation will be reused. That means things like `useMemo` functions
won't run again, because the deps will match and the memoized result
will be reused.

We want memoized functions to run twice, too, so account for this, user
functions are double invoked during the *first* invocation of the
component function, and are *not* double invoked during the second
incovation:

- First execution of component function: user functions are double
invoked
- Second execution of component function (in Strict Mode, during
development): user functions are not double invoked.

It's hard to explain verbally but much clearer when you run the test
cases I've added.
2022-10-28 17:46:20 -04:00
Andrew Clark d2a0176a13
Detect and warn if use(promise) is wrapped with try/catch block (#25543)
The old (unstable) mechanism for suspending was to throw a promise. The
purpose of throwing is to interrupt the component's execution, and also
to signal to React that the interruption was caused by Suspense as
opposed to some other error.

A flaw is that throwing is meant to be an implementation detail — if
code in userspace catches the promise, it can lead to unexpected
behavior.

With `use`, userspace code does not throw promises directly, but `use`
itself still needs to throw something to interrupt the component and
unwind the stack.

The solution is to throw an internal error. In development, we can
detect whether the error was caught by a userspace try/catch block and
log a warning — though it's not foolproof, since a clever user could
catch the object and rethrow it later.

The error message includes advice to move `use` outside of the try/catch
block.

I did not yet implement the warning in Flight.
2022-10-28 17:46:03 -04:00
Sebastian Markbåge cf3932be5c
Remove old react-fetch, react-fs and react-pg libraries (#25577)
To avoid confusion. We are patching `fetch`, and only `fetch`, for a
small fix scoped to react renders elsewhere, but this code is not it.

This code was for the strategy used in the original [React Server
Components demo](https://github.com/reactjs/server-components-demo).
Which [we
announced](https://reactjs.org/blog/2022/06/15/react-labs-what-we-have-been-working-on-june-2022.html)
that we're moving away from in favor of [First class support for
promises and async/await](https://github.com/reactjs/rfcs/pull/229).

We might explore using these package for other instrumentation in the
future but not now and not like this.
2022-10-27 17:52:53 -04:00
Sebastian Markbåge 28a574ea8f
Try assigning fetch to globalThis if global assignment fails (#25571)
In case it's a more modern yet rigid environment.
2022-10-27 02:43:17 -04:00
Josh Story 09def5990b
[Float] handle noscript context for Resources (#25559)
stacked on https://github.com/facebook/react/pull/25569

On the client noscript already never renders children so no resources
will be extracted from this context. On the server we now track if we
are in a noscript context and turn off Resource semantics in this scope
2022-10-26 23:11:31 -07:00
Josh Story 17204056d5
[Float] fix coordination of resource identity and hydration (#25569)
there are a few bugs where dom representations from SSR aren't
identified as Resources when they should be.

There are 3 semantics

Resource -> hoist to head, deduping, etc...
hydratable Component -> SSR'd and hydrated in place
non-hydratable Component -> never SSR'd, never hydrated, always inserted
on the client

this last category is small
(non stylesheet) links with onLoad and/or onError
async scripts with onLoad and/or onError

The reason we have this distinction for now is we need every SSR'd async
script to be assumable to be a Resource. we don't currently encode
onLoad on the server and so we couldn't otherwise tell if an async
script is a Resource or is an async script with an onLoad which would
not be a resource. To avoid this ambiguity we never emit the scripts in
SSR and assume they need to be inserted on the client.

We can explore changes to these semantics in the future or possibly
encode some identifier when we want to opt out of resource semantics but
still SSR the link or script.
2022-10-26 19:53:29 -07:00
Robert Balicki fecc288b7d
[react devtools] Device storage support (#25452)
# Summary
* This PR adds support for persisting certain settings to device
storage, allowing e.g. RN apps to properly patch the console when
restarted.
* The device storage APIs have signature `getConsolePatchSettings()` and
`setConsolePatchSettings(string)`, in iOS, are thin wrappers around the
`Library/Settings` turbomodule, and wrap a new TM that uses the `SharedPreferences` class in Android.
* Pass device storage getters/setters from RN to DevTools'
`connectToDevtools`. The setters are then used to populate values on
`window`. Later, the console is patched using these values.
* If we receive a notification from DevTools that the console patching
fields have been updated, we write values back to local storage.
* See https://github.com/facebook/react-native/pull/34903

# How did you test this change?
Manual testing, `yarn run test-build-devtools`, `yarn run prettier`,
`yarn run flow dom`

## Manual testing setup:

### React DevTools Frontend
* Get the DevTools frontend in flipper:
* `nvm install -g react-devtools-core`, then replace that package with a
symlink to the local package
  * enable "use globally installed devtools" in flipper
* yarn run start in react-devtools, etc. as well

### React DevTools Backend
* `yarn run build:backend` in react-devtools-core, then copy-paste that
file to the expo app's node_modules directory

### React Native
* A local version of React Native can be patched in by modifying an expo
app's package.json, as in `"react-native":
"rbalicki2/react-native#branch-name"`

# Versioning safety
* There are three versioned modules to worry about: react native, the
devtools frontend and the devtools backend.
* The react devtools backend checks for whether a `cachedSettingsStore`
is passed from react native. If not (e.g. if React Native is outdated),
then no behavior changes.
* The devtools backend reads the patched console values from the cached
settings store. However, if nothing has been stored, for example because
the frontend is outdated or has never synced its settings, then behavior
doesn't change.
* The devtools frontend sends no new messages. However, if it did send a
new message (e.g. "store this value at this key"), and the backend was
outdated, that message would be silently ignored.
2022-10-25 13:25:33 +11:00
Josh Story d925a8d0be
Flight client error stack (#25560)
restore error message into stack for flight prod errors
2022-10-24 16:32:33 -07:00
Leo Lamprecht 996b00b787
[Tiny] Fixed incorrect import in `react-server-dom-webpack` (#25554)
<!--
  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 debug-test --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

In https://github.com/facebook/react/pull/25504,
`react-server-dom-webpack/` was deprecated in favor of
`react-server-dom-webpack/client`, but a remaining import wasn't
adjusted accordingly.

As a result, the remaining conditions within the file are no longer
firing appropriately, which I ran into while playing around with a fork
of
[server-components-demo](https://github.com/reactjs/server-components-demo).

The `index.js` file now contains a
[placeholder](https://github.com/facebook/react/blob/main/packages/react-server-dom-webpack/index.js)
and the actual logic of the client now sits in `/client`.

## How did you test this change?

I replaced `require.resolve('../')` with `require.resolve('../client')`
in the `react-server-dom-webpack` package in `node_modules` and
confirmed that the output of the build looked good again.
2022-10-24 10:40:18 -07:00
Sebastian Markbåge e7c5af45ce
Update cache() and use() to the canary aka next channel (#25502)
Testing what it would look like to move this to the `next` channel.
2022-10-23 23:20:52 -04:00
Andrew Clark fa77f52e74 Unify promise switch statements
There are two different switch statements that we use to unwrap a
`use`-ed promise, but there really only needs to be one. This was a
factoring artifact that arose because I implemented the yieldy `status`
instrumentation thing before I implemented `use` (for promises that are
thrown directly during render, which is the old Suspense pattern that
will be superseded by `use`).
2022-10-23 18:43:30 -04:00
Andrew Clark 7572e4931f Track thenable state in work loop
This is a refactor to track the array of thenables that is preserved
across replays in the work loop instead of the Thenable module.

The reason is that I'm about to add additional state to the Thenable
module that is specific to a particular attempt — like the current
index — and is reset between replays. So it's helpful to keep the two
kinds of state separate so it's clearer which state gets reset when.

The array of thenables is not reset until the work-in-progress either
completes or unwinds.

This also makes the structure more similar to Fizz and Flight.
2022-10-23 18:43:30 -04:00
Andrew Clark 7fc3eefd85 Revert yieldy behavior for non-use Suspense (in Flight, too)
Same as #25537 but for Flight.

I was going to wait to do this later because the temporary
implementation of async components uses some of the same code that
non-used wakables do, but it's not so bad. I just had to inline one bit
of code, which we'll remove when we unify the implementation with `use`.
2022-10-23 18:43:30 -04:00
Josh Story 61f9b5e97b
[Float] support <base> as Resource (#25546)
keys off `target` and `href`.
prepends on insertion similar to title.
only flushes on the server in the shell (should probably add a warning
if there are any to flush in a boundary)
2022-10-23 15:03:52 -07:00
Sebastian Markbåge 1d3fc9c9c4
Bug fix when resolving cache (#25545)
We must use the asynclocalstorage one if it's available.
2022-10-23 14:12:47 -04:00
Sebastian Markbåge cce18e3504
[Flight] Use AsyncLocalStorage to extend the scope of the cache to micro tasks (#25542)
This extends the scope of the cache and fetch instrumentation using
AsyncLocalStorage for microtasks. This is an intermediate step. It sets
up the dispatcher only once. This is unique to RSC because it uses the
react.shared-subset module for its shared state.

Ideally we should support multiple renderers. We should also have this
take over from an outer SSR's instrumented fetch. We should also be able
to have a fallback to global state per request where AsyncLocalStorage
doesn't exist and then the whole client-side solutions. I'm still
figuring out the right wiring for that so this is a temporary hack.
2022-10-23 01:06:58 -04:00
Sebastian Markbåge caa84c8da0
Revert fetch instrumentation to only RSC (#25540)
Revert fetch instrumentation so that it only affects RSC by applying it
only in the react-server condition of "react".

This helps make the rollout a little smoother because these affects
existing libraries that fetch during client components, and then gets
forever cached. We need to implement the GC first.

I haven't fully implemented the SSR part anyway.

The main problem that we discovered is that `"react"` and
`"react/react.shared-subset"` have separate dispatchers in an
environment that runs both Fizz and Flight. That's intentional and
sometimes a feature. However, in this case it means that we instrument
fetch twice and when you run Flight inside Fizz, that fetch goes into
both caches when it's supposed to only see the inner one. I'm not sure
how to solve that atm.
2022-10-22 22:58:30 -04:00
Josh Story 0c11baa6ab
add warnings for non-resources rendered outside body or head (#25532)
Adds some clarifying warnings when you render a component that is almost
a resource but isn't and the element was rendered outside the main
document tree (outside of `<body>` or `<head>`
2022-10-22 15:19:42 -07:00
Josh Story 9236abdb5a
when float is enabled only push title and script as a single unit (#25536)
replaces: https://github.com/facebook/react/pull/25535

This takes a more huerstic based approach with no new conditionals on
the hot path of fizz rendering.

If float is enabled
* title and script can only have simple children
* if non-simple children are found they will be ignored
* title and script are pushed in a single unit during pushStartInstance
including their children and closing tags

If float is not enabled
* the original pushing behaviors are in place and you can have complex
children but you will get warnings
2022-10-22 15:11:26 -07:00
Andrew Clark dd5c208257
Revert yieldy behavior for non-use Suspense (#25537)
To derisk the rollout of `use`, and simplify the implementation, this
reverts the yield-to-microtasks behavior for promises that are thrown
directly (as opposed to being unwrapped by `use`).

We may add this back later. However, the plan is to deprecate throwing a
promise directly and migrate all existing Suspense code to `use`, so the
extra code probably isn't worth it.
2022-10-22 17:52:20 -04:00