Commit Graph
16348 Commits
Author SHA1 Message Date
Sebastian Markbåge 3f93ca1c8d [Fiber] Transfer _debugInfo from Arrays, Lazy, Thenables and Elements to the inner Fibers. (#28286)
That way we can use it for debug information like component stacks and
DevTools. I used an extra stack argument in Child Fiber to track this as
it's flowing down since it's not just elements where we have this info
readily available but parent arrays and lazy can merge this into the
Fiber too. It's not great that this is a dev-only argument and I could
track it globally but seems more likely to make mistakes.

It is possible for the same debug info to appear for multiple child
fibers like when it's attached to a fragment or a lazy that resolves to
a fragment at the root. The object identity could be used in these
scenarios to infer if that's really one server component that's a parent
of all children or if each child has a server component with the same
name.

This is effectively a public API because you can use it to stash
information on Promises from a third-party service - not just Server
Components. I started outline the types for this for some things I was
planning to add but it's not final.

I was also planning on storing it from `use(thenable)` for when you
suspend on a Promise. However, I realized that there's no Hook instance
for those to stash it on. So it might need a separate data structure to
stash the previous pass over of `use()` that resets each render.

No tests yet since I didn't want to test internals but it'll be covered
once we have debugging features like component stacks.
2024-02-12 14:56:59 -05:00
Sebastian Markbåge 9e7944f67c Suspend Thenable/Lazy if it's used in React.Children and unwrap (#28284)
This pains me because `React.Children` is really already
pseudo-deprecated.

`React.Children` takes any children that `React.Node` takes. We now
support Lazy and Thenable in this position elsewhere, but it errors in
`React.Children`.

This becomes an issue with async Server Components which can resolve
into a Lazy and in the future Lazy will just become Thenables. Which
causes this to error.

There are a few different semantics we could have:

1) Error like we already do (#28280). `React.Children` is about
introspecting children. It was always sketchy because you can't
introspect inside an abstraction anyway. With Server Components we fold
away the components so you can actually introspect inside of them kind
of but what they do is an implementation detail and you should be able
to turn it into a Client Component at any point. The type of an Element
passing the boundary actually reduces to `React.Node`.
2) Suspend and unwrap the Node (this PR). If we assume that Children is
called inside of render, then throwing a Promise if it's not already
loaded or unwrapping would treat it as if it wasn't there. Just like if
you rendered it in React. This lets you introspect what's inside which
isn't really something you should be able to do. This isn't compatible
with deprecating throwing-a-Promise and enable static compilation like
`use()` does. We'd have to deprecate `React.Children` before doing that
which we might anyway.
3) Wrap in a Fragment. If a Server Component was instead a Client
Component, you couldn't introspect through it anyway. Another
alternative might be to let it pass through but then it wouldn't be
given a flat key. We could also wrap it in a Fragment that is keyed.
That way you're always seeing an element. The issue with this solution
is that it wouldn't see the key of the Server Component since that gets
forwarded to the child that is yet to resolve. The nice thing about that
strategy is it doesn't depend on throw-a-Promise but it might not be
keyed correctly when things move.
2024-02-12 13:39:30 -05:00
Sebastian Markbåge 629541bcc0 [Flight] Transfer Debug Info in Server-to-Server Flight Requests (#28275)
A Flight Server can be a consumer of a stream from another Server. In
this case the meta data is attached to debugInfo properties on lazy,
Promises, Arrays or Elements that might in turn get forwarded to the
next stream. In this case we want to forward this debug information to
the client in the stream.

I also added a DEV only `environmentName` option to the Flight Server.
This lets you name the server that is producing the debug info so that
you can trace the origin of where that component is executing. This
defaults to `"server"`. DevTools could use this for badges or different
colors.
2024-02-12 13:38:14 -05:00
Ruslan Lesiutin 947e7962ad fix[devtools/useModalDismissSignal]: use getRootNode for shadow root case support (#28145)
In our custom implementation for handling modals dismiss signal, we use
element's `ownerDocument` field, which expectedly doesn't work well with
shadow root. Now using
[`getRootNode`](https://developer.mozilla.org/en-US/docs/Web/API/Node/getRootNode)
instead of `ownerDocument` to support shadow root case.

Without this, if RDT Frontend is hosted inside the shadow root, the
modal gets closed after any click, including on the buttons hosted by
modal:

https://github.com/facebook/react/blob/00d42ac3542179c55f936f395ede7abaeb5900a3/packages/react-devtools-shared/src/devtools/views/hooks.js#L228-L238

Test plan:
- Modals work as expected for Chrome DevTools integration
- Modals work as expected at every other surfaces: browser extension,
electron wrapper for RN, inline version for web
2024-02-12 16:56:28 +00:00
dan 269edb88b2 Add jsx-runtime.react-server.js to file allowlist (#28301)
https://github.com/facebook/react/pull/28217 doesn't work without this
since it's not included in the files list.

See https://github.com/dai-shi/waku/pull/467#issuecomment-1936965080.

This should fix that.
2024-02-11 03:19:30 +00:00
dan 35b2c28178 Remove deprecated methods from react-is (#28224)
These aren't being used anywhere and don't even correspond to real APIs.
2024-02-11 00:25:17 +00:00
Ricky 06e410ec60 Move modern strict to experimental (#28152)
Turn this on 

Edited: ope, nvm
<details>
Looks like there's still an outstanding issue with this. The original PR
turned off a strict effects test, which causes a stray
`componentWillUnmount` to fire.


https://github.com/facebook/react/commit/5d1ce651393524639a3b4b1e861a0413a4d25629#diff-19df471970763c4790c2cc0811fd2726cc6a891b0e1d5dedbf6d0599240c127aR70


Before:
```js
expect(log).toEqual([
      'constructor',
      'constructor',
      'getDerivedStateFromProps',
      'getDerivedStateFromProps',
      'render',
      'render',
      'componentDidMount',
    ]);
```

After:

```js
expect(log).toEqual([
      'constructor',
      'constructor',
      'getDerivedStateFromProps',
      'getDerivedStateFromProps',
      'render',
      'render',
      'componentDidMount',
      'componentWillUnmount',
      'componentDidMount',
    ]);
```

So there's a bug somewhere
</details>
2024-02-09 16:59:47 -05:00
Ruslan Lesiutin 374fd68a50 fix: define IS_ACT_ENVIRONMENT global for tests with concurrent mode and synchronous act (#28296) 2024-02-09 19:03:40 +00:00
Jan Kassens d27c1ac112 Upgrade flow to 0.228.0 (#28294)
Upgrade flow to 0.228.0
2024-02-09 11:17:00 -05:00
Jan Kassens d8c1fa6b0b Add infinite update loop detection (#28279)
This is a partial redo of https://github.com/facebook/react/pull/26625.
Since that was unlanded due to some detected breakages. This now
includes a feature flag to be careful in rolling this out.
2024-02-09 11:14:37 -05:00
Ruslan Lesiutin 03d6f7cf00 chore: gate legacy apis for react-devtools-shell (#28273)
- `react-devtools-shell` is only used for e2e tests
- Based on the React version we testing against, we will show/hide roots
using legacy render
2024-02-09 11:27:12 +00:00
Samuel Susla 36b078cc7a unify feature flags between fb and oss for React Native renderer (#28269)
# Affected flags:

### alwaysThrottleRetries

In RN OSS changed from `true` to `false`. This is what FB build uses.
This flag was a root cause for big perf regression internally.

### enableDeferRootSchedulingToMicrotask

In RN OSS build changed from `true` to `false`. This is what FB build
uses.

### debugRenderPhaseSideEffectsForStrictMode

Changed from true to __DEV__ in FB and OSS build. The flag is only used
in debug builds and was previously `false` in RN OSS builds

### enableUnifiedSyncLane

Changed from `__VARIANT__` to `true` in FB build. This is what OSS build
uses. This flag is shipped internally. cc @tyao1

### enableLegacyHidden

In RN FB changed from `true` to `false`.  This is what OSS uses.

### allowConcurrentByDefault

In RN FB changed from `true` to `false`. 




I ran `yarn flags --diff rn rn-fb` to get the difference between feature
flags and unify them.

## Before
```
yarn run v1.22.19
$ node ./scripts/flags/flags.js --diff rn rn-fb
┌───────────────────────────────────────────────┬────────┬───────┐
│                    (index)                    │ RN OSS │ RN FB │
├───────────────────────────────────────────────┼────────┼───────┤
│ allowConcurrentByDefault                      │  ''  │ ''  │
│ debugRenderPhaseSideEffectsForStrictMode      │  ''  │ ''  │
│ disableModulePatternComponents                │  ''  │ ''  │
│ enableCPUSuspense                             │  ''  │ ''  │
│ enableCacheElement                            │  ''  │ ''  │
│ enableGetInspectorDataForInstanceInProduction │  ''  │ ''  │
│ enableLegacyHidden                            │  ''  │ ''  │
│ enableSchedulingProfiler                      │  ''  │ '📊'  │
│ enableUseDeferredValueInitialArg              │  ''  │ ''  │
│ enableUseMemoCacheHook                        │  ''  │ ''  │
│ enableUseRefAccessWarning                     │  ''  │ '🧪'  │
│ passChildrenWhenCloningPersistedNodes         │  ''  │ '🧪'  │
│ useMicrotasksForSchedulingInFabric            │  ''  │ '🧪'  │
│ alwaysThrottleRetries                         │  ''  │ '🧪'  │
│ enableDeferRootSchedulingToMicrotask          │  ''  │ '🧪'  │
│ enableUnifiedSyncLane                         │  ''  │ '🧪'  │
└───────────────────────────────────────────────┴────────┴───────┘
```

## After
```
yarn run v1.22.19
$ node ./scripts/flags/flags.js --diff rn rn-fb
┌───────────────────────────────────────────────┬────────┬───────┐
│                    (index)                    │ RN OSS │ RN FB │
├───────────────────────────────────────────────┼────────┼───────┤
│ alwaysThrottleRetries                         │  ''  │ '🧪'  │
│ disableModulePatternComponents                │  ''  │ ''  │
│ enableCPUSuspense                             │  ''  │ ''  │
│ enableCacheElement                            │  ''  │ ''  │
│ enableDeferRootSchedulingToMicrotask          │  ''  │ '🧪'  │
│ enableGetInspectorDataForInstanceInProduction │  ''  │ ''  │
│ enableSchedulingProfiler                      │  ''  │ '📊'  │
│ enableUseDeferredValueInitialArg              │  ''  │ ''  │
│ enableUseMemoCacheHook                        │  ''  │ ''  │
│ enableUseRefAccessWarning                     │  ''  │ '🧪'  │
│ passChildrenWhenCloningPersistedNodes         │  ''  │ '🧪'  │
│ useMicrotasksForSchedulingInFabric            │  ''  │ '🧪'  │
└───────────────────────────────────────────────┴────────┴───────┘
```
2024-02-09 09:46:42 +00:00
Sebastian Markbåge ba5e6a8329 [Flight] Serialize deduped elements by direct reference even if they suspend (#28283)
In #28123 I switched these to be lazy references. However that creates a
lazy wrapper even if they're synchronously available. We try to as much
as possible preserve the original data structure in these cases.

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

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

For now I just went back to direct reference which might be an issue
since it can suspend something higher up when deduped.
2024-02-08 18:45:40 -05:00
Sebastian Markbåge e41ee9ea70 Throw a better error when Lazy/Promise is used in React.Children (#28280)
We could in theory actually support this case by throwing a Promise when
it's used inside a render. Allowing it to be synchronously unwrapped.
However, it's a bit sketchy because we officially only support this in
the render's child position or in `use()`.

Another alternative could be to actually pass the Promise/Lazy to the
callback so that you can reason about it and just return it again or
even unwrapping with `use()` - at least for the forEach case maybe.
2024-02-08 17:10:19 -05:00
Ricky cd63ef7921 Add simulateEventDispatch to test ReactDOMEventListener (#28079)
## Overview

For events, the browser will yield to microtasks between calling event
handers, allowing time to flush work inbetween. For example, in the
browser, this code will log the flushes between events:

```js
<body onclick="console.log('body'); Promise.resolve().then(() => console.log('flush body'));">
  <div onclick="console.log('div'); Promise.resolve().then(() => console.log('flush div'));">
    hi
  </div>
</body>

// Logs
div 
flush div 
body 
flush body 
```


[Sandbox](https://codesandbox.io/s/eloquent-noether-mw2cjg?file=/index.html)

The problem is, `dispatchEvent` (either in the browser, or JSDOM) does
not yield to microtasks. Which means, this code will log the flushes
after the events:

```js
const target = document.getElementsByTagName("div")[0];
const nativeEvent = document.createEvent("Event");

nativeEvent.initEvent("click", true, true);
target.dispatchEvent(nativeEvent);

// Logs
div
body
flush div
flush body
```

## The problem
This mostly isn't a problem because React attaches event handler at the
root, and calls the event handlers on components via the synthetic event
system. We handle flushing between calling event handlers as needed.

However, if you're mixing capture and bubbling events, or using multiple
roots, then the problem of not flushing microtasks between events can
come into play. This was found when converting a test to `createRoot` in
https://github.com/facebook/react/pull/28050#discussion_r1462118422, and
that test is an example of where this is an issue with nested roots.

Here's a sandox for
[discrete](https://codesandbox.io/p/sandbox/red-http-2wg8k5) and
[continuous](https://codesandbox.io/p/sandbox/gracious-voice-6r7tsc?file=%2Fsrc%2Findex.js%3A25%2C28)
events, showing how the test should behave. The existing test, when
switched to `createRoot` matches the browser behavior for continuous
events, but not discrete. Continuous events should be batched, and
discrete should flush individually.

## The fix

This PR implements the fix suggested by @sebmarkbage, to manually
traverse the path up from the element and dispatch events, yielding
between each call.
2024-02-08 16:06:03 -05:00
Sebastian Silbermann 04b59928d8 DevTools: Add support for use(Context) (#28233) 2024-02-08 18:47:40 +01:00
Andrew Clark d3def47935 Delete more redundant JSX code (#28276)
Found another redundant implementation of JSX code. Not being used
anywhere so safe to delete.
2024-02-08 11:04:09 -05:00
Sebastian Markbåge b229f540e2 [Flight] Emit debug info for a Server Component (#28272)
This adds a new DEV-only row type `D` for DebugInfo. If we see this in
prod, that's an error. It can contain extra debug information about the
Server Components (or Promises) that were compiled away during the
server render. It's DEV-only since this can contain sensitive
information (similar to errors) and since it'll be a lot of data, but
it's worth using the same stream for simplicity rather than a
side-channel.

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

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

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

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

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

If it's a synchronous render that returns a string or number (text node)
then we don't have anywhere to attach them to. We could add a
`React.Lazy` wrapper for those but I chose to prioritize keeping the
data structure untouched. Can be useful if you use Server Components to
render data instead of React Nodes.
2024-02-08 11:01:32 -05:00
Sebastian Markbåge 37d901e2b8 Remove __self and __source location from elements (#28265)
Along with all the places using it like the `_debugSource` on Fiber.
This still lets them be passed into `createElement` (and JSX dev
runtime) since those can still be used in existing already compiled code
and we don't want that to start spreading to DOM attributes.

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

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

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

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

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

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

With this change the DEV only Babel transforms are effectively
deprecated since they're not necessary for anything.
2024-02-07 16:38:00 -05:00
Sebastian Markbåge 5c08662301 Add enableServerComponentKeys to NEXT_MAJOR (#28259) 2024-02-07 15:21:59 -05:00
RickyandSebastian Silbermann 2cd19ed1dd Convert ReactRenderDocument to hydrateRoot (#28153)
Co-authored-by: Sebastian Silbermann <sebastian.silbermann@klarna.com>
2024-02-07 09:54:46 -05:00
Ruslan Lesiutin bfdc12c191 chore: use versioned render in inspectedElement test (#28246) 2024-02-07 10:50:26 +00:00
Ruslan Lesiutin d1829775ad chore: use versioned render in TimelineProfiler test and gate some for legacy rendering (#28218) 2024-02-07 10:30:54 +00:00
Josh Story a1ace9d3c2 Improve flagging of React.cache to remove indirection in bundled code (#28263)
Uses a better technique for conditionally disabling cache on the client
2024-02-06 17:40:06 -08:00
Andrew Clark 91caa96e42 jsx(): Treat __self and __source as normal props (#28257)
These used to be reserved props because the classic React.createElement
runtime passed this data as props, whereas the jsxDEV() runtime passes
them as separate arguments.

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

The React.createElement runtime is unaffected.
2024-02-06 20:03:02 -05:00
Sebastian Markbåge f07ac1e268 [Flight] Unify plain Server Component and forwardRef under one function (#28261)
This used to be trivial but it's no longer trivial.

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

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

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

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

The practical change in this PR is that returning a Promise from a
forwardRef now turns it into a lazy. We previously didn't support async
forwardRef since it wasn't supported on the client. However, since
eventually this will be supported by child-as-a-promise it seems fine to
support it.
2024-02-06 19:41:05 -05:00
Andrew Clark 1beb94133a jsx(): Inline reserved prop checks (#28262)
The JSX runtime (both the new one and the classic createElement runtime)
check for reserved props like `key` and `ref` by doing a lookup in a
plain object map with `hasOwnProperty`.

There are only a few reserved props so this inlines the checks instead.
2024-02-06 18:56:18 -05:00
Sebastian Markbåge 0d11563b4a [Flight] Move pendingChunks ref count increment into createTask (#28260)
Every time we create a task we need to wait for it so we increase a ref
count. We can do this in `createTask`. This is in line with what Fizz
does too.

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

Flight should probably count them when they complete so it's possible to
wait for the end before flushing for buffering purposes.
2024-02-06 16:17:59 -05:00
Andrew Clark 6692445759 Delete duplicate jsx() implementation (#28258)
Not sure how this happened but there are two identical implementations
of the jsx and jsxDEV functions. One of them was unreachable. I deleted
that one.
2024-02-06 15:05:08 -05:00
Damian Stasik 7cbd026ff4 [Fresh] Update the list of built-in hooks (#27864) 2024-02-06 19:57:46 +01:00
Ricky 30e2938e04 [Tests] Reset modules by default (#28254)
## Overview

Sets `resetModules: true` in the base Jest config, and deletes all the
`jest.resetModule()` calls we don't need.
2024-02-06 12:43:27 -05:00
Ruslan Lesiutin 8b5f0c43ad chore: use versioned render in preprocessData test and gate some for … (#28219) 2024-02-06 17:34:41 +00:00
Sebastian Silbermann 97fd3e7064 Ensure useState and useReducer initializer functions are double invoked in StrictMode (#28248) 2024-02-06 17:53:08 +01:00
Ruslan Lesiutin 08d6cef46a chore: use versioned render in storeStressSync test and gate them for legacy rendering (#28216) 2024-02-06 16:51:58 +00:00
Sathya Gunasekaran db120f69ec Patch devtools before running useMemo function in strict mode (#28249)
This fixes a regression https://github.com/facebook/react/pull/25583
where we stopped patching before calling useMemo function.

Fixes https://github.com/facebook/react/issues/27989
2024-02-06 16:45:18 +00:00
Ruslan Lesiutin 12d56fca3d chore: use versioned render in storeComponentFilters test (#28241) 2024-02-06 16:25:03 +00:00
Ruslan Lesiutin ad720f36ec chore: use versioned render in profilerContext test (#28243) 2024-02-06 15:58:11 +00:00
Ricky 5446b098a8 Convert ReactBrowserEventEmitter to createRoot (#28253)
pretty boring
2024-02-06 10:43:37 -05:00
Ruslan Lesiutin 65d95b837e fix: gate react/jsx-runtime upgrade only for React >= 17 tests (#28256)
https://github.com/facebook/react/pull/28252 broke RDT tests with React
16.x.

These changes gate the `jsx-runtime` upgrade only for cases when we are
testing against React >= 17.

Validated with:
```
 ./scripts/circleci/download_devtools_regression_build.js 16.0 --replaceBuild && node ./scripts/jest/jest-cli.js --build --project devtools --release-channel=experimental --reactVersion 16.0 --ci && ./scripts/circleci/download_devtools_regression_build.js 16.5 --replaceBuild && node ./scripts/jest/jest-cli.js --build --project devtools --release-channel=experimental --reactVersion 16.5 --ci && ./scripts/circleci/download_devtools_regression_build.js 16.8 --replaceBuild && node ./scripts/jest/jest-cli.js --build --project devtools --release-channel=experimental --reactVersion 16.8 --ci && ./scripts/circleci/download_devtools_regression_build.js 17.0 --replaceBuild && node ./scripts/jest/jest-cli.js --build --project devtools --release-channel=experimental --reactVersion 17.0 --ci && ./scripts/circleci/download_devtools_regression_build.js 18.0 --replaceBuild && node ./scripts/jest/jest-cli.js --build --project devtools --release-channel=experimental --reactVersion 18.0 --ci
 ```
2024-02-06 15:03:36 +00:00
Ruslan Lesiutin 103cddbb9d chore: use versioned render in profilingCommitTreeBuilder test and gate some for legacy rendering (#28236) 2024-02-06 12:26:50 +00:00
Ruslan Lesiutin 6fef0cb568 chore: use versioned render in profilingHostRoot test and gate some for legacy rendering (#28237) 2024-02-06 11:40:50 +00:00
Ruslan Lesiutin cb78d2f1f3 chore: use versioned render in profilingCache test (#28242) 2024-02-06 11:24:54 +00:00
Josh Story 0a53c46574 Update ReactDOMServerSuspense-test to not use legacy rendering APIs (#28251)
Updates ReactDOMServerSuspense-test to not use legacy rendering APIs
Also removes an experimental only gate that is not necessary
2024-02-05 21:25:22 -08:00
Andrew Clark 952aa74f8e Upgrade tests to use react/jsx-runtime (#28252)
Instead of createElement.

We should have done this when we initially released jsx-runtime but
better late than never. The general principle is that our tests should
be written using the most up-to-date idioms that we recommend for users,
except when explicitly testing an edge case or legacy behavior, like for
backwards compatibility.

Most of the diff is related to tweaking test output and isn't very
interesting.

I did have to workaround an issue related to component stacks. The
component stack logic depends on shared state that lives in the React
module. The problem is that most of our tests reset the React module
state and re-require a fresh instance of React, React DOM, etc. However,
the JSX runtime is not re-required because it's injected by the compiler
as a static import. This means its copy of the shared state is no longer
the same as the one used by React, causing any warning logged by the JSX
runtime to not include a component stack. (This same issue also breaks
string refs, but since we're removing those soon I'm not so concerned
about that.) The solution I went with for now is to mock the JSX runtime
with a proxy that re-requires the module on every function invocation. I
don't love this but it will have to do for now. What we should really do
is migrate our tests away from manually resetting the module state and
use import syntax instead.
2024-02-05 23:07:41 -05:00
Josh Story 2bc7d336ae Add flag to disable caching behavior of React.cache on the client (#28250)
Adds a feature flag to control whether the client cache function is just
a passthrough. before we land breaking changes for the next major it
will be off and then we can flag it on when we want to break it.

flag is off for OSS for now and on elsewhere (though the parent flag
enableCache is off in some cases)
2024-02-05 16:32:03 -08:00
dan 472854820b [Flight] Delete Server Context (#28225)
Server Context was never documented, and has been deprecated in
https://github.com/facebook/react/pull/27424.

This PR removes it completely, including the implementation code.

Notably, `useContext` is removed from the shared subset, so importing it
from a React Server environment would now should be a build error in
environments that are able to enforce that.
2024-02-05 22:39:15 +00:00
Sebastian Markbåge 95ec128399 [Flight] Support Keyed Server Components (#28123)
Conceptually a Server Component in the tree is the same as a Client
Component.

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

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

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

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

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

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

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

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

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

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

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

Another compromise of this approach is that when combining keys we don't
escape them fully. We instead just use a simple `,` separated concat.
This is probably good enough in practice. Additionally, since we don't
encode the implicit 0 index slot key, you can move things around between
parents which shouldn't really reconcile but does. This keeps the keys
shorter and more human readable.
2024-02-05 09:33:35 -08:00
Ruslan Lesiutin 86b95edb0a chore: use versioned render in ownersListContext test (#28240) 2024-02-05 17:32:31 +00:00
Ruslan Lesiutin 6a21244671 chore: use versioned render in editing test (#28239) 2024-02-05 17:30:46 +00:00
Ruslan Lesiutin 09de4b2cfe chore: use versioned render in treeContext test (#28245) 2024-02-05 17:29:10 +00:00