Commit Graph
333 Commits
Author SHA1 Message Date
hoxyq b4ab87e20a fix[devtools/useTransition]: don't check for dispatch property when determining if hook is stateful (#27365)
https://github.com/facebook/react/pull/26740 introduced regression:
React DevTools doesn't record updates for `useTransition` hook. I can
add more details about things on DevTools side, if needed.

The root cause is
https://github.com/facebook/react/blob/491aec5d6113ce5bae7c10966bc38a4a8fc091a8/packages/react-reconciler/src/ReactFiberHooks.js#L2728-L2730

React DevTools expects dispatch to be present for stateful hooks that
can schedule an update -
https://github.com/facebook/react/blob/2eed1328478e8c923fcb4e6abf5efbd9e1233402/packages/react-devtools-shared/src/backend/renderer.js#L1422-L1428

With these changes, we still call dispatch in `startTransition`, but
also patch `queue` object with it, so that React DevTools can recognise
`useTransition` as stateful hook that can schedule update.

I am not sure if this is the right approach to fix this, can we
distinguish if `startTransition` was called from `useTransition` hook or
as a standalone function?

DiffTrain build for commit https://github.com/facebook/react/commit/56b14477e902ac076018be2e7bf2ea3092ac9e7d.
2023-09-21 20:30:59 +00:00
acdlite e1f7f22c59 Use MurmurHash3 when native hashing function is not available (#27399)
DiffTrain build for commit https://github.com/facebook/react/commit/68ac6dbcf8d58a67e94e9061395dd96a52d92377.
2023-09-21 19:04:52 +00:00
sebmarkbage e316095688 [Fizz] Simplify ReplayNode data structure (#27395)
The key is that instead of storing different tags of resumable points,
we just store if a replay node has any resumable slots and if that's at
the root `number` or if it has resumable slots by index.

This is a simpler and more compact format because we don't have to
separate the three Resume forms.

This helps deal with Postpone in fallbacks because it doesn't just
double all the cases.

DiffTrain build for commit https://github.com/facebook/react/commit/47fed6961f79e8c8388f5f11fe1a531b194bb4af.
2023-09-21 17:54:48 +00:00
sophiebits 54f1ceef21 Update tracked value after resetting radio group (#27394)
Fixes #26876, I think. Review each commit separately (all assertions
pass in main already, except the last assertInputTrackingIsClean in
"should control radio buttons").

I'm actually a little confused on two things here:
* All the isCheckedDirty assertions are true. But I don't think we set
.checked unconditionally? So how does this happen?
* https://github.com/facebook/react/issues/26876#issuecomment-1611662862
claims that
https://github.com/facebook/react/compare/d962f35ca...1f248bdd7 contains
the faulty change, but it doesn't appear to change the restoration logic
that I've touched here. (One difference outside restoration is that
updateProperties did previously set `.checked` when `nextProp !==
lastProp` whereas the new logic in updateInput is to set it when
`node.checked !== !!checked`.)

But it seems to me like we need this call here anyway, and if it fixes
it then it fixes it? I think technically speaking we probably should do
all the updateInput() calls and then all the updateValueIfChanged()
calls—in particular I think if clicking A changed the checked radio
button from B to C then the code as I have it would be incorrect, but
that also seems unlikely so idk whether to care.

cc @zhengjitf @Luk-z who did some investigation on the original issue

DiffTrain build for commit https://github.com/facebook/react/commit/3c27178a2f2c74f14d90613028e3929e1f06d830.
2023-09-21 05:03:08 +00:00
acdlite bdfa4e69a2 useFormState: Hash the component key path for more compact output (#27397)
To support MPA-style form submissions, useFormState sends down a key
that represents the identity of the hook on the page. It's based on the
key path of the component within the React tree; for deeply nested
hooks, this keypath can become very long. We can hash the key to make it
shorter.

Adds a method called createFastHash to the Stream Config interface.
We're not using this for security or obfuscation, only to generate a
more compact key without sacrificing too much collision resistance.

- In Node.js builds, createFastHash uses the built-in crypto module.
- In Bun builds, createFastHash uses Bun.hash. See:
https://bun.sh/docs/api/hashing#bun-hash

I have not yet implemented createFastHash in the Edge, Browser, or FB
(Hermes) stream configs because those environments do not have a
built-in hashing function that meets our requirements. (We can't use the
web standard `crypto` API because those methods are async, and yielding
to the main thread is too costly to be worth it for this particular use
case.) We'll likely use a pure JS implementation in those environments;
for now, they just return the original string without hashing it. I'll
address this in separate PRs.

DiffTrain build for commit https://github.com/facebook/react/commit/2b3d5826836ac59f8446281976762d594e55d97e.
2023-09-20 21:18:00 +00:00
mofeiZ 57f7532544 [Fizz] Allow passing a reason to abortStream (#26992)
## Summary

Currently `ReactFizzServer.abort` allows you to pass in the a `reason`
error, which then gets passed to the `onError` handler for each task
that ends up getting aborted. This adds in the ability to pass down that
same `reason` error to `ReactDOMServerFB.abortStream` as well.

## How did you test this change?

Added a test case to ReactDOMServerFB-test.internal.js

DiffTrain build for commit https://github.com/facebook/react/commit/1f4936660dcaba2e5722013f0ad12d7369543a9f.
2023-09-20 20:45:57 +00:00
sebmarkbage d17c9581ac [Fizz] Ensure Resumable State is Serializable (#27388)
Moves writing queues to renderState.

We shouldn't need the resource tracking's value. We just need to know if
that resource has already been emitted. We can use a Set for this. To
ensure that set is directly serializable we can just use a
dictionary-like object with no value.

See individual commits for special cases.

DiffTrain build for commit https://github.com/facebook/react/commit/b775564d35d6fe9f9acead0f380bbc86bb6bdd2c.
2023-09-20 16:26:55 +00:00
hoxyq 4bb64789e7 feat[devtools/extension]: show disclaimer when page doesnt run react and refactor react polling logic (#27373)
Changes:
1. Refactored react polling logic, now each `.eval()` call is wrapped in
Promise, so we can chain them properly.
2. When user has browser DevTools opened and React DevTools panels were
mounted, user might navigate to the page, which doesn't have React
running. Previously, we would show just blank white page, now we will
show disclaimer. Disclaimer appears after 5 failed attempts to find
React. We will also show this disclaimer if it takes too long to load
the page, but once any React instance is loaded and registered, we will
update the panels.
3. Dark theme support for this disclaimer and popups in Firefox &
Chromium-based browsers

**Important**: this is only valid for case when React DevTools panels
were already created, like when user started debugging React app and
then switched to non-React page. If user starts to debug non-React app
(by opening browser DevTools for it), we will not create these panels,
just like before.

Q: "Why do we poll to get information about react?"
A: To handle case when react is loaded after the page has been loaded,
some sandboxes for example.

| Before | After |
| --- | --- |
| <img width="1840" alt="Screenshot 2023-09-14 at 15 37 37"
src="https://github.com/facebook/react/assets/28902667/2e6ffb39-5698-461d-bfd6-be2defb41aad">
| <img width="1840" alt="Screenshot 2023-09-14 at 15 26 16"
src="https://github.com/facebook/react/assets/28902667/1c8ad2b7-0955-41c5-b8cc-d0fdb03e13ca">
|

DiffTrain build for commit https://github.com/facebook/react/commit/1b1dcb8a40d002edcbca483b1f9caa78087a878f.
2023-09-20 12:36:30 +00:00
8ba46ff30f feat:-Added a delete all filters action and added title to the add filter a… (#27332)
### changes

1. A small action added to delete all filters, it can be useful to
delete when someone has a bunch of them rather than clicking on them
selectively.

2.There was no title on the `add filter` button so added the same

https://github.com/facebook/react/assets/72331432/af6c0725-05b6-4f46-b8c9-8079bd933a8e

review @hoxyq

---------

Co-authored-by: BIKI DAS <bikidas@BIKIs-MacBook-Pro.local>
Co-authored-by: Ruslan Lesiutin <rdlesyutin@gmail.com>

DiffTrain build for commit https://github.com/facebook/react/commit/a3743b2e444d2198972b190a9d97c3edcf370414.
2023-09-20 09:31:56 +00:00
sebmarkbage 95d14f5f28 [Fizz] Reuse rootSegmentID as the SuspenseBoundaryID (#27387)
Originally the intension was to have React assign an ID to a user
rendered DOM node inside a `fallback` while it was loading. If there
already were an explicit `id` defined on the DOM element we would reuse
that one instead. That's why this was a DOM Config option and not just
built in to Fizz.

This became tricky since it can load late and so we'd have to transfer
it down and detect it only once it finished rendering and if there is no
DOM element it doesn't work anyway. So instead, what we do in practice
is to always use a `<template>` tag with the ID. This has the downside
of an extra useless node and shifting child CSS selectors.

Maybe we'll get around to fixing this properly but it might not be worth
it.

This PR just gets rid of the SuspenseBoundaryID concept and instead we
just use the same ID number as the root segment ID of the boundary to
refer to the boundary to simplify the implementation.

This also solves the problem that SuspenseBoundaryID isn't currently
serializable (although that's easily fixable by itself if necessary).

DiffTrain build for commit https://github.com/facebook/react/commit/2807d781a08db8e9873687fccc25c0f12b4fb3d4.
2023-09-18 16:01:33 +00:00
sebmarkbage 2c46007254 [Fizz] Client render the nearest child or parent suspense boundary if replay errors or is aborted (#27386)
Based on #27385.

When we error or abort during replay, that doesn't actually error the
component that errored because that has already rendered. The error only
affects any child that is not yet completed. Therefore the error kind of
gets thrown at the resumable point.

The resumable point might be a hole in the replay path, in which case
throwing there errors the parent boundary just the same as if the replay
component errored. If the hole is inside a deeper Suspense boundary
though, then it's that Suspense boundary that gets client rendered. I.e.
the child boundary. We can still finish any siblings.

In the shell all resumable points are inside a boundary since we must
have finished the shell. Therefore if you error in the root, we just
simply just turn all incomplete boundaries into client renders.

DiffTrain build for commit https://github.com/facebook/react/commit/925c66a6472a61e7174dabf6c697a9a320ebc170.
2023-09-18 15:30:40 +00:00
sebmarkbage bda552c6c7 [Fizz] Don't bail out of flushing if we still have pending root tasks (#27385)
The idea for this check is that we shouldn't flush anything before we
flush the shell. That may or may not hold true in future formats like
RN.

It is a problem for resuming because with resuming it's possible to have
root tasks that are used for resuming but the shell was already flushed
so we can have completed boundaries before the shell has fully resumed.
What matters is whether the parent has already flushed or not.

It's not technically necessary to bail early because there won't be
anything in partialBoundaries or completedBoundaries because nothing
gets added there unless the parent has already flushed.

It's not exactly slow to have to check the length of three arrays so
it's probably not a big deal.

Flush partials in an early preamble needs further consideration
regardless.

DiffTrain build for commit https://github.com/facebook/react/commit/df061b396644bb7c27ea76bb27ae09784ce6444b.
2023-09-18 15:30:03 +00:00
sebmarkbage 4dfccb6f89 [Fizz] Replay Postponed Paths (#27379)
This forks Task into ReplayTask and RenderTask.

A RenderTask is the normal mode and it has a segment to write into.

A ReplayTask doesn't have a segment to write into because that has
already been written but instead it has a ReplayState which keeps track
of the next set of paths to follow. Once we hit a "Resume" node we
convert it into a RenderTask and continue rendering from there.

We can resume at either an Element position or a Slot position. An
Element pointing to a component doesn't mean we resume that component,
it means we resume in the child position directly below that component.
Slots are slots inside arrays.

Instead of statically forking most paths, I kept using the same path and
checked for the existence of a segment or replay state dynamically at
runtime.

However, there's still quite a bit of forking here like retryRenderTask
and retryReplayTask. Even in the new forks there's a lot of duplication
like resumeSuspenseBoundary, replaySuspenseBoundary and
renderSuspenseBoundary. There's opportunity to simplify this a bit.

DiffTrain build for commit https://github.com/facebook/react/commit/a5fc797db14c6e05d4d5c4dbb22a0dd70d41f5d5.
2023-09-15 19:28:44 +00:00
acdlite 7e99c2a606 Restrict React DOM imports from Server Components (#27382)
Adds a separate entry point for the react-dom package when it's accessed
from a Server Component environment, using the "react-server" export
condition.

When you're inside a Server Component module, you won't be able to
import client-only APIs like useState. This applies to almost all React
DOM exports, except for Float ones like preload.

DiffTrain build for commit https://github.com/facebook/react/commit/2d2f2af29bc3175530a158bc90189fc6f12f7855.
2023-09-15 18:57:58 +00:00
acdlite 4570bc02f2 useFormState: Only emit markers if postback state is provided (#27374)
This is an optimization where useFormState will only emit extra comment
markers if a form state is passed at the root. If no state is passed, we
don't need to emit anything because none of the hooks will match.

DiffTrain build for commit https://github.com/facebook/react/commit/d6dcad6a8beaeec0513a9851d1e0fe1181932360.
2023-09-14 15:51:13 +00:00
hoxyq 2689dea0c6 fix[devtools/extension]: unregister dynamically injected content scripts instead of filtering (#27369)
Same as https://github.com/facebook/react/pull/26765.
Related bug report -
https://bugs.chromium.org/p/chromium/issues/detail?id=1393762.

This was changed in https://github.com/facebook/react/pull/27215, when I
have refactored background logic in the extension. I've missed this
case, because the extension was working in incognito mode.

Turns out, it stops working after the first reload, and it stops only in
incognito mode, so I am rolling out back the previous workaround.

Tested on Chrome that it fixes the extension in incognito mode and that
it doesn't affect default mode.

DiffTrain build for commit https://github.com/facebook/react/commit/54c2f2a3469e296fba025cf444d0639c7bf8f39a.
2023-09-14 14:26:11 +00:00
acdlite 252ec6cbf2 useFormState: MPA submissions to a different page (#27372)
The permalink option of useFormState controls which page the form is
submitted to during an MPA form submission (i.e. a submission that
happens before hydration, or when JS is disabled). If the same
useFormState appears on the resulting page, and the permalink option
matches, it should receive the form state from the submission despite
the fact that the keypaths do not match.

So the logic for whether a form state instance is considered a match is:
- Both instances must be passed the same action signature
- If a permalink is provided, the permalinks must match.
- If a permalink is not provided, the keypaths must match.

Currently, if there are multiple matching useFormStates, they will all
match and receive the form state. We should probably only match the
first one, and/or warn when this happens. I've left this as a TODO for
now, pending further discussion.

DiffTrain build for commit https://github.com/facebook/react/commit/caa716d50bdeef3a1ac5e3e0cfcc14f4d91f2028.
2023-09-14 05:11:37 +00:00
sebmarkbage bb93490b7e [Fizz] Fix root segment IDs (#27371)
Typically we assign IDs lazily when flushing to minimize the ids we have
to assign and we try to maximize inlining.

When we prerender we could always flush into a buffer before returning
but that's not actually what we do right now. We complete rendering
before returning but we don't actually run the flush path until someone
reads the resulting stream. We assign IDs eagerly when something
postpone so that we can refer to those ids in the holes without flushing
first.

This leads to some interesting conditions that needs to consider this.

This PR also deals with rootSegmentId which is the ID of the segment
that contains the body of a Suspense boundary. The boundary needs to
know this in addition to the Suspense Boundary's ID to know how to
inject the root segment into the boundary.

Why is the suspense boundary ID and the rootSegmentID just not the same
ID? Why don't segments and suspense boundary not share ID namespace?
That's a good question and I don't really remember. It might not be a
good reason and maybe they should just be the same.

DiffTrain build for commit https://github.com/facebook/react/commit/a6e4791b11816374d015eb4531a82e6cf209c7f2.
2023-09-14 03:23:47 +00:00
acdlite 320e7a7b93 useFormState: Compare action signatures when reusing form state (#27370)
During an MPA form submission, useFormState should only reuse the form
state if same action is passed both times. (We also compare the key
paths.)

We compare the identity of the inner closure function, disregarding the
value of the bound arguments. That way you can pass an inline Server
Action closure:

```js
function FormContainer({maxLength}) {
  function submitAction(prevState, formData) {
    'use server'
    if (formData.get('field').length > maxLength) {
      return { errorMsg: 'Too many characters' };
    }
    // ...
  }
  return <Form submitAction={submitAction} />
}
```

DiffTrain build for commit https://github.com/facebook/react/commit/95c9554bc72813b0ee2b028774bb7cf0482887ba.
2023-09-14 00:51:05 +00:00
acdlite fc5a146ede useFormState: Reuse state from previous form submission (#27321)
If a Server Action is passed to useFormState, the action may be
submitted before it has hydrated. This will trigger a full page
(MPA-style) navigation. We can transfer the form state to the next page
by comparing the key path of the hook instance.

`ReactServerDOMServer.decodeFormState` is used by the server to extract
the form state from the submitted action. This value can then be passed
as an option when rendering the new page. It must be passed during both
SSR and hydration.

```js
const boundAction = await decodeAction(formData, serverManifest);
const result = await boundAction();
const formState = decodeFormState(result, formData, serverManifest);

// SSR
const response = createFromReadableStream(<App />);
const ssrStream = await renderToReadableStream(response, { formState })

// Hydration
hydrateRoot(container, <App />, { formState });
```

If the `formState` option is omitted, then the state won't be
transferred to the next page. However, it must be passed in both places,
or in neither; misconfiguring will result in a hydration mismatch.

(The `formState` option is currently prefixed with `experimental_`)

DiffTrain build for commit https://github.com/facebook/react/commit/612b2b6601abb844248c384d1e288bb824b180b7.
2023-09-13 22:35:16 +00:00
sebmarkbage 419e64c5fe [Fizz] Various smaller refactors (#27368)
Back ported from a larger PR.

DiffTrain build for commit https://github.com/facebook/react/commit/e5205658f40ad181279857dbb66e36b8ebcd8c0e.
2023-09-13 04:21:21 +00:00
acdlite 3fbdf7de41 Fix: Initialize childIndex in Task constructor (#27367)
This field was not being initialized. Although the property is part of
the Flow type, the type error wasn't caught because the constructor
itself is not covered by Flow, which is unfortunate. (I assume this is
related to the dev-only componentStack property.)

DiffTrain build for commit https://github.com/facebook/react/commit/69be472c11231056d297a7b73dd0b121905606d3.
2023-09-13 02:21:49 +00:00
acdlite f73ef32f79 Don't modify keyPath until right before recursive renderNode call (#27366)
Currently, if a component suspends, the keyPath has already been
modified to include the identity of the component itself; the path is
set before the component body is called (akin to the begin phase in
Fiber). An accidental consequence is that when the promise resolves and
component is retried, the identity gets appended to the keyPath again,
leading to a duplicate node in the path.

To address this, we should only modify contexts after any code that may
suspend. For maximum safety, this should occur as late as possible:
right before the recursive renderNode call, before the children are
rendered.

I did not add a test yet because there's no feature that currently
observes it, but I do have tests in my other WIP PR for useFormState:
#27321

DiffTrain build for commit https://github.com/facebook/react/commit/d07921eeda62613bfcf52ecdb66322db26393567.
2023-09-13 01:32:20 +00:00
sebmarkbage 6c133b6661 Track the key path difference between right before the first array (#27360)
There's a subtle difference if you suspend before the first array or
after. In Fiber, we don't deal with this because we just suspend the
parent and replay it if lazy() or Usable are used in its child slots. In
Fizz we try to optimize this a bit more and enable resuming inside the
component.

Semantically, it's different if you suspend/postpone before the first
child array or inside that child array. Because when you resume the
inner result might be another array and either that's part of the parent
path or part of the inner slot.

There might be more clever way of structuring this but I just use -1 to
indicate that we're not yet inside the array and is in the root child
position. If that renders an element, then that's just the same as the 0
slot.

We need to also encode this in the resuming. I called that resuming the
element or resuming the slot.

DiffTrain build for commit https://github.com/facebook/react/commit/7a3cb8f9cf43591afc74722ece9e3216ccc98128.
2023-09-12 16:35:31 +00:00
gnoff ab8832e345 [Float] Refactor public interface and internal HostDispatcher implementation (#27361)
When Float was first developed the internal implementation and external
interface were the same. This is problematic for a few reasons. One, the
public interface is typed but it is also untrusted and we should not
assume that it is actually respected. Two, the internal implementations
can get called from places other than the the public interface and
having to construct an options argument that ends up being destructured
to process the request is computationally wasteful and may limit JIT
optimizations to some degree. Lastly, the wire format was not as
compressed as it could be and it was untyped.

This refactor aims to address that by separating the public interface
from the internal implementations so we can solve these challenges and
also make it easier to change Float in the future

* The internal dispatcher method preinit is now preinitStyle and
preinitScript.
* The internal dispatcher method preinitModule is now
preinitModuleScript in anticipation of different implementations for
other module types in the future.
* The wire format is explicitly typed and only includes options if they
are actually used omitting undefined and nulls.
* Some function arguments are not options even if they are optional. For
instance precedence can be null/undefined because we deafult it to
'default' however we don't cosnider this an option because it is not
something we transparently apply as props to the underlying instance.
* Fixes a problem with keying images in flight where srcset and sizes
were not being taken into account.
* Moves argument validation into the ReactDOMFloat file where it is
shared with all runtimes that expose these methods
* Fixes crossOrigin serialization to use empty string except when
'use-credentials'

DiffTrain build for commit https://github.com/facebook/react/commit/bbc8530ed7a67859583a7c990ac51cd39c7746e5.
2023-09-12 15:14:50 +00:00
hoxyq d39d345b23 refactor[devtools/extension]: more stable element updates polling to avoid timed out errors (#27357)
Some context:
- When user selects an element in tree inspector, we display current
state of the component. In order to display really current state, we
start polling the backend to get available updates for the element.

Previously:
- Straight-forward sending an event to get element updates each second.
Potential race condition is not handled in any form.
- If user navigates from the page, timeout wouldn't be cleared and we
would potentially throw "Timed out ..." error.
- Bridge disconnection is not handled in any form, if it was shut down,
we could spam with "Timed out ..." errors.

With these changes:
- Requests are now chained, so there can be a single request at a time.
- Handling both navigation and shut down events.

This should reduce the number of "Timed out ..." errors that we see in
our logs for the extension. Other surfaces will also benefit from it,
but not to the full extent, as long as they utilize
"resumeElementPolling" and "pauseElementPolling" events.

Tested this on Chrome, running React DevTools on multiple tabs,
explicitly checked the case when service worker is in idle state and we
return back to the tab.

DiffTrain build for commit https://github.com/facebook/react/commit/2eed1328478e8c923fcb4e6abf5efbd9e1233402.
2023-09-12 14:10:27 +00:00
sebmarkbage 2c322d6f56 Encode lazy Node slots properly in key path and resumable paths (#27359)
It's possible to postpone a specific node and not using a wrapper
component. Therefore we encode the resumable slot as the index slot.
When it's a plain client component that postpones, it's encoded as the
child slot inside that component which is the one that's postponed
rather than the component itself.

Since it's possible for a child slot to suspend (e.g. React.lazy's
microtask in this case) retryTask might need to keep its index around
when it resolves.

DiffTrain build for commit https://github.com/facebook/react/commit/bb1d8d166799eb97892be6c7826179270ba283d0.
2023-09-11 23:30:00 +00:00
acdlite 9dfb8f125a Fix: Skip hidden inputs before text instance (#27358)
Found a hydration bug that happens when you pass a Server Action to
`formAction` and the next node is a text instance.

The HTML generated by Fizz is something like this:

```html
<button name="$ACTION_REF_5" formAction="" formEncType="multipart/form-data" formMethod="POST">
  <input type="hidden" name="$ACTION_5:0" value="..."/>
  <input type="hidden" name="$ACTION_5:1" value="..."/>
  <input type="hidden" name="$ACTION_KEY" value="..."/>Count: <!-- -->0
</button>
```

Fiber is supposed to skip over the extra hidden inputs, but it doesn't
handle this correctly if the next expected node isn't a host instance.
In this case, it's a text instance.

Not sure if the proper fix is to change the HTML that is generated, or
to change the hydration logic, but in this PR I've done the latter.

DiffTrain build for commit https://github.com/facebook/react/commit/a4aceafc63a4a54b507ab60d530b25d9ff189024.
2023-09-11 22:28:25 +00:00
hoxyq 67b0ae0a6e feat[devtools/extension]: add dark theme for popup (#27330)
## Summary

If the system/browser uses a dark theme, then the extension popup still
remains with a light background. And so that the eyes do not hurt in a
dark room, you need a dark theme.

## How did you test this change?

Make sure the dark theme is enabled on your system/browser.

**Before:**

![Screenshot 2023-09-02 at 22 20
56](https://github.com/facebook/react/assets/19418601/f7166ea7-f562-4d11-8851-be08fa9629a7)

**After:**

![Screenshot 2023-09-02 at 22 21
30](https://github.com/facebook/react/assets/19418601/e51ecd5f-3e71-4193-83ff-a548bce76bd4)

DiffTrain build for commit https://github.com/facebook/react/commit/627b7abd62eb27f70af3934ca45b858103d4f30d.
2023-09-11 13:07:39 +00:00
gnoff d704c7b2a7 [Float][Fizz] include preloadModule and preinitModule on react-dom/server-rendering-stub (#27347)
When implementing `preloadModule` and `preinitModule` these methods were
not exposed on the server rendering stub when they should have been.
This PR corrects that omission.

DiffTrain build for commit https://github.com/facebook/react/commit/41f0e9dae3b81396dc29a4735b355ea318cc5772.
2023-09-07 21:54:03 +00:00
acdlite e19570a39f useFormState: Emit comment to mark whether state matches (#27307)
A planned feature of useFormState is that if the page load is the result
of an MPA-style form submission — i.e. a form was submitted before it
was hydrated, using Server Actions — the state of the hook should
transfer to the next page.

I haven't implemented that part yet, but as a prerequisite, we need some
way for Fizz to indicate whether a useFormState hook was rendered using
the "postback" state. That way we can do all state matching logic on the
server without having to replicate it on the client, too.

The approach here is to emit a comment node for each useFormState hook.
We use one of two comment types: `<!--F-->` for a normal useFormState
hook, and `<!--F!-->` for a hook that was rendered using the postback
state. React will read these markers during hydration. This is similar
to how we encode Suspense boundaries.

Again, the actual matching algorithm is not yet implemented — for now,
the "not matching" marker is always emitted.

We can optimize this further by not emitting any markers for a render
that is not the result of a form postback, which I'll do in subsequent
PRs.

DiffTrain build for commit https://github.com/facebook/react/commit/8b26f07a883bb341c20283c0099bf5ee6f87bd1f.
2023-09-07 20:10:49 +00:00
gnoff d6a6e0665d [Fizz][Float] <img> inside <picture> should not preload during SSR (#27346)
img tags inside picture tags should not automatically be preloaded
because usually the img is a fallback. We will consider a more
comprehensive way of preloading picture tags which may require a
technique like using an inline script to construct the image in the
browser but for now we simply omit the preloads to avoid harming load
times by loading fallbacks.

DiffTrain build for commit https://github.com/facebook/react/commit/3566de59e2046e7e8478462375aaa71716f1095b.
2023-09-07 20:02:21 +00:00
sebmarkbage d3c09be2e6 [Fizz] Split createRequest into createRequest, createPrerenderRequest and resumeRequest (#27342)
Just moving some internal code around again.

I originally encoded what type of work using startRender vs
startPrerender. I had intended to do more forking of the work loop but
we've decided not to go with that strategy. It also turns out that
forking when we start working is actually too late because of a subtle
thing where you can call abort before work begins. Therefore it's
important that starting the work comes later.

DiffTrain build for commit https://github.com/facebook/react/commit/953cb02f6de2a9f3eb52456b263e11f839584bc6.
2023-09-07 04:25:34 +00:00
acdlite 91e2f1b928 useId: Remove unnecessary try/finally blocks (#27340)
To generate IDs for useId, we modify a context variable whenever
multiple siblings are rendered, or when a component includes a useId
hook.

When this happens, we must ensure that the context is reset properly on
unwind if something errors or suspends. When I originally implemented
this, I did this by wrapping the child's rendering with a try/finally
block. But a better way to do this is by using the non-destructive
renderNode path instead of renderNodeDestructive.

DiffTrain build for commit https://github.com/facebook/react/commit/ee7f9c9351f8902e07ceacf4234ef75e7e4ecd73.
2023-09-06 20:35:23 +00:00
gnoff 23d1b68ba6 [Flight] provide property descriptors for client references (#27328)
Client reference proxy should implement getOwnPropertyDescriptor. One
practical place where this shows up is when consuming CJS module.exports
in ESM modules. Node creates named exports it statically infers from the
underlying source but it only sets the named export if the CJS exports
hasOwnProperty. This trap will allow the proxy to respond affirmatively.

I did not add unit tests because contriving the ESM <-> CJS scenario in
Jest is challenging. I did add new components to the flight fixture
which demonstrate that the named exports are properly constructed with
the client reference whereas they were not before.

DiffTrain build for commit https://github.com/facebook/react/commit/b9be4537c2459f8fc0312b796570003620bc8600.
2023-09-05 20:50:23 +00:00
sebmarkbage a19664648a [Fizz] Move /static build into /server builds (#27327)
This joins the static (prerender) builds with the server builds but
doesn't change the public entry points.

The idea of two separate bundles is that we'd have a specialized build
for Fizz just for the prerender that could do a lot more. However, in
practice the code is implemented with a dynamic check so it's in both.
It's also not a lot of code.

At the same time if you do have a set up that includes both the
prerender and the render in the same build output, this just doubles the
server bundle size for no reason.

So we might as well merge them into one build. However, I don't expose
the `prerender` from `/server`. Instead it's just exposed from the
public `/static` entry point. This leaves us with the option to go back
to separate builds later if it diverges more in the future.

DiffTrain build for commit https://github.com/facebook/react/commit/2c2bdd0ffe54df60201ee93b29de5cb7b93ff029.
2023-09-05 20:00:18 +00:00
sebmarkbage e96a8b2e72 [Fizz] Move formatContext tracking back to the task (#27325)
In https://github.com/facebook/react/pull/21113 I moved this over to the
segment from the task. This partially reverts this two use two fields
instead. I was just trying to micro-optimize by reusing a single field.

This is really conceptually two different values. Task is keeping track
of the working state of the currently executing context.

The segment just needs to keep track of which parent context it was
created in so that it can be wrapped correctly when a segment is
written. We just happened to rely on the working state returning to the
top before completing.

The main motivation is that there is no `segment` for replaying.

DiffTrain build for commit https://github.com/facebook/react/commit/3cc8a9347bd540ac68acfb181fbc7fba7c371648.
2023-09-05 20:00:00 +00:00
hoxyq e497667204 React DevTools 4.28.2 -> 4.28.3 (#27337)
This is a patch version to fix some bugs in a previous internal release.
I am expecting this one also to be internal-only, need to make sure that
extension is stable in Chrome. Some changes and improvements are
expected for Firefox, though, before going public.

* refactor[devtools/extension]: handle ports disconnection, instead of
frequent reconnection ([hoxyq](https://github.com/hoxyq) in
[#27336](https://github.com/facebook/react/pull/27336))
* refactor[devtools/extension]: migrate from using setInterval for
polling if react is loaded ([hoxyq](https://github.com/hoxyq) in
[#27323](https://github.com/facebook/react/pull/27323))
* fix[devtools/extension]: fixed duplicating panels in firefox
([hoxyq](https://github.com/hoxyq) in
[#27320](https://github.com/facebook/react/pull/27320))

DiffTrain build for commit https://github.com/facebook/react/commit/a374287feae1b37f19fb43d428463b153d552b20.
2023-09-05 18:05:18 +00:00
hoxyq 3e339bec6e refactor[devtools/extension]: handle ports disconnection, instead of frequent reconnection (#27336)
- Instead of reconnecting ports from devtools page and proxy content
script, now handling their disconnection properly
- `proxy.js` is now dynamically registered as a content script, which
loaded for each page. This will probably not work well for Firefox,
since we are still on manifest v2, I will try to fix this in the next
few PRs.
- Handling the case when devtools page port was reconnected and bridge
is still present. This could happen if user switches the tab and Chrome
decides to kill service worker, devtools page port gets disconnected,
and then user returns back to the tab. When port is reconnected, we
check if bridge message listener is present, connecting them if so.
- Added simple debounce when evaluating if page has react application
running. We start this check in `chrome.network.onNavigated` listener,
which is asynchronous. Also, this check itself is asynchronous, so
previously we could mount React DevTools multiple times if navigates
multiple times while `chrome.devtools.inspectedWindow.eval` (which is
also asynchronous) can be executed.
https://github.com/hoxyq/react/blob/00b7c4331819289548b40714aea12335368e10f4/packages/react-devtools-extensions/src/main/index.js#L575-L583

https://github.com/facebook/react/assets/28902667/9d519a77-145e-413c-b142-b5063223d073

DiffTrain build for commit https://github.com/facebook/react/commit/a27df56a5cc54b77a9206d1344b457af4ec64b30.
2023-09-05 17:46:25 +00:00
hoxyq 7922199303 refactor[devtools/extension]: migrate from using setInterval for polling if react is loaded (#27323)
`chrome.devtools.inspectedWindow.eval` is asynchronous, so using it in
`setInterval` is a mistake.
Sometimes this results into mounting React DevTools twice, and user sees
errors about duplicated fibers in store.

With these changes, `executeIfReactHasLoaded` executed recursively with
a threshold (in case if page doesn't have react).

Although we minimize the risk of mounting DevTools twice here, this
approach is not the best way to have this problem solved. Dumping some
thoughts and ideas that I've tried, but which are out of the scope for
this release, because they can be too risky and time-consuming.
Potential changes:
- Have 2 content scripts:
  - One `prepareInjection` to notify service worker on renderer attached
- One which runs on `document_idle` to finalize check, in case if there
is no react
- Service worker will notify devtools page that it is ready to mount
React DevTools panels or should show that there is no React to be found
- Extension port from devtools page should be persistent and connected
when `main.js` is executed
- Might require refactoring the logic of how we connect devtools and
proxy ports

Some corner cases:
- Navigating to restricted pages, like `chrome://<something>` and back
- When react is lazily loaded, like in an attached iframe, or just
opened modal
- In-tab navigation with pre-cached pages, I think only Chrome does it
- Firefox is still on manifest v2 and it doesn't allow running content
scripts in ExecutionWorld.MAIN, so it requires a different approach

DiffTrain build for commit https://github.com/facebook/react/commit/9b4f847d93aa302c953543ae0631023c06408ad3.
2023-09-01 15:29:44 +00:00
hoxyq ae2f6ca48a fix[devtools/extension]: fixed duplicating panels in firefox (#27320)
Multiple `chrome.panels.create` calls result into having duplicate
panels created in Firefox, these changes fix that.

Now calling `chrome.panels.create` only if there are no panels created
yet.

DiffTrain build for commit https://github.com/facebook/react/commit/7022e8d6a3222c97d287dfa0f2361acc8a30683a.
2023-08-31 17:29:44 +00:00
sebmarkbage de20faf8f2 [Fizz] Track postponed holes in the prerender pass (#27317)
This is basically the implementation for the prerender pass.

Instead of forking basically the whole implementation for prerender, I
just add a conditional field on the request. If it's `null` it behaves
like before. If it's non-`null` then instead of triggering client
rendered boundaries it triggers those into a "postponed" state which is
basically just a variant of "pending". It's supposed to be filled in
later.

It also builds up a serializable tree of which path can be followed to
find the holes. This is basically a reverse `KeyPath` tree.

It is unfortunate that this approach adds more code to the regular Fizz
builds but in practice. It seems like this side is not going to add much
code and we might instead just want to merge the builds so that it's
smaller when you have `prerender` and `resume` in the same bundle -
which I think will be common in practice.

This just implements the prerender side, and not the resume side, which
is why the tests have a TODO. That's in a follow up PR.

DiffTrain build for commit https://github.com/facebook/react/commit/b70a0d70224ceb4e277bd8ac535a2caafa5c075a.
2023-08-31 16:28:03 +00:00
hoxyq 1d5a5ee429 React DevTools 4.28.1 -> 4.28.2 (#27318)
List of changes:
* fix[devtools/extension]: handle tab navigation events before react is
loaded ([hoxyq](https://github.com/hoxyq) in
[#27316](https://github.com/facebook/react/pull/27316))

DiffTrain build for commit https://github.com/facebook/react/commit/3808b01b3a6d116151b5de742866360ed70450c7.
2023-08-30 19:30:56 +00:00
hoxyq 34060f6c7b fix[devtools/extension]: handle tab navigation events before react is loaded (#27316)
This is mostly hotfix for https://github.com/facebook/react/pull/27215.

Contains 3 fixes:
- Handle cases when `react` is not loaded yet and user performs in-tab
navigation. Previously, because of the uncleared interval we would try
to mount DevTools twice, resulting into multiple errors.
- Handle case when extension port disconnected (probably by the browser
or just due to its lifetime)
- Removed duplicate `render()` call on line 327

DiffTrain build for commit https://github.com/facebook/react/commit/29b405b2de6b4abaa67ff53f3b5e067f80b106d3.
2023-08-30 18:44:05 +00:00
gnoff 7e18719bef [Flight] use opaque config for flight in dom-legacy renderer (#27313)
`dom-legacy` does not make sense for Flight. we could still type check
the files but it adds maintenance burden in the inlinedHostConfigs
whenever things change there. Going to make these configs opaque mixed
types to quiet flow since no entrypoints use the flight code

DiffTrain build for commit https://github.com/facebook/react/commit/d23b8b5dbf72cd0a3a1a85e22af19772b32feacd.
2023-08-30 17:39:14 +00:00
acdlite 9b694f4365 useFormState fix: action -> target (#27309)
I mixed these attributes up in
https://github.com/facebook/react/pull/27302

DiffTrain build for commit https://github.com/facebook/react/commit/2fba484cd095ea79b940364cea5107fa4ca9f0c8.
2023-08-30 02:21:54 +00:00
acdlite ec7b510b9e useFormState's permalink option changes form target (#27302)
When the `permalink` option is passed to `useFormState`, and the form is
submitted before it has hydrated, the permalink will be used as the
target of the form action, enabling MPA-style form submissions.

(Note that submitting a form without hydration is a feature of Server
Actions; it doesn't work with regular client actions.)

It does not have any effect after the form has hydrated.

DiffTrain build for commit https://github.com/facebook/react/commit/ddff504695f33c19e8c0792bff82bd8f8b8f7c05.
2023-08-29 16:03:31 +00:00
hoxyq 3930ad525c 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 commit https://github.com/facebook/react/commit/eaa696876ee40bb048727aefe995be1bbb7384a8.
2023-08-29 15:47:34 +00:00
noahlemen 33e4ca38df 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 commit https://github.com/facebook/react/commit/4129ea8c922b950be3964f98d2bb74ff4a1c5431.
2023-08-29 13:11:28 +00:00
hoxyq 5a1020ef91 React DevTools 4.28.0 -> 4.28.1 (#27305)
List of changes:
* refactor: refactored devtools browser extension scripts to improve
port management and service worker lifetime
([hoxyq](https://github.com/hoxyq) in
[#27215](https://github.com/facebook/react/pull/27215))
* refactor[devtools/extension]: minify production builds to strip
comments ([hoxyq](https://github.com/hoxyq) in
[#27304](https://github.com/facebook/react/pull/27304))
* fix[devtools]: allow element updates polling only if bridge is alive
([hoxyq](https://github.com/hoxyq) in
[#27067](https://github.com/facebook/react/pull/27067))
* refactor: resolve browser via env variables based on build rather than
user agent ([hoxyq](https://github.com/hoxyq) in
[#27179](https://github.com/facebook/react/pull/27179))
* fix[devtools/updateFiberRecursively]: mount suspense fallback set in
timed out case ([hoxyq](https://github.com/hoxyq) in
[#27147](https://github.com/facebook/react/pull/27147))
* Feat:-Added open in editor to appear by default
([Biki-das](https://github.com/Biki-das) in
[#26949](https://github.com/facebook/react/pull/26949))
* fix[devtools/inspect]: null check memoized props before trying to call
hasOwnProperty ([hoxyq](https://github.com/hoxyq) in
[#27057](https://github.com/facebook/react/pull/27057))
* rename SuspenseList export to unstable_SuspenseList
([noahlemen](https://github.com/noahlemen) in
[#27061](https://github.com/facebook/react/pull/27061))

DiffTrain build for commit https://github.com/facebook/react/commit/2f368725fb37f4911f6a14f0993a8a7b688df8bd.
2023-08-29 12:42:17 +00:00