Commit Graph

1948 Commits

Author SHA1 Message Date
Sebastian Markbåge
7909d8eabb [Flight] Encode ReadableStream and AsyncIterables (#28847)
This adds support in Flight for serializing four kinds of streams:

- `ReadableStream` with objects as a model. This is a single shot
iterator so you can read it only once. It can contain any value
including Server Components. Chunks are encoded as is so if you send in
10 typed arrays, you get the same typed arrays out on the other side.
- Binary `ReadableStream` with `type: 'bytes'` option. This supports the
BYOB protocol. In this mode, the receiving side just gets `Uint8Array`s
and they can be split across any single byte boundary into arbitrary
chunks.
- `AsyncIterable` where the `AsyncIterator` function is different than
the `AsyncIterable` itself. In this case we assume that this might be a
multi-shot iterable and so we buffer its value and you can iterate it
multiple times on the other side. We support the `return` value as a
value in the single completion slot, but you can't pass values in
`next()`. If you want single-shot, return the AsyncIterator instead.
- `AsyncIterator`. These gets serialized as a single-shot as it's just
an iterator.

`AsyncIterable`/`AsyncIterator` yield Promises that are instrumented
with our `.status`/`.value` convention so that they can be synchronously
looped over if available. They are also lazily parsed upon read.

We can't do this with `ReadableStream` because we use the native
implementation of `ReadableStream` which owns the promises.

The format is a leading row that indicates which type of stream it is.
Then a new row with the same ID is emitted for every chunk. Followed by
either an error or close row.

`AsyncIterable`s can also be returned as children of Server Components
and then they're conceptually the same as fragment arrays/iterables.
They can't actually be used as children in Fizz/Fiber but there's a
separate plan for that. Only `AsyncIterable` not `AsyncIterator` will be
valid as children - just like sync `Iterable` is already supported but
single-shot `Iterator` is not. Notably, neither of these streams
represent updates over time to a value. They represent multiple values
in a list.

When the server stream is aborted we also close the underlying stream.
However, closing a stream on the client, doesn't close the underlying
stream.

A couple of possible follow ups I'm not planning on doing right now:

- [ ] Free memory by releasing the buffer if an Iterator has been
exhausted. Single shots could be optimized further to release individual
items as you go.
- [ ] We could clean up the underlying stream if the only pending data
that's still flowing is from streams and all the streams have cleaned
up. It's not very reliable though. It's better to do cancellation for
the whole stream - e.g. at the framework level.
- [ ] Implement smarter Binary Stream chunk handling. Currently we wait
until we've received a whole row for binary chunks and copy them into
consecutive memory. We need this to preserve semantics when passing
typed arrays. However, for binary streams we don't need that. We can
just send whatever pieces we have so far.
2024-04-16 12:20:07 -04:00
Jan Kassens
8afa144bdc Enable flag disableClientCache (#28846)
Enable flag disableClientCache

Forcing a `__VARIANT__` in the mock file so we keep testing this until
fully removing it.
2024-04-16 10:59:36 -04:00
Ricky
fd35655fae Delete AUTHORS.md (#28844)
This hasn't been updated in a long time, and it getting really large. 

You can view the authors locally via the git history with:

``
git shortlog -se | perl -spe 's/^\s+\d+\s+//'
``
2024-04-15 15:23:30 -04:00
Sebastian Markbåge
ed40236036 Fix mistaken "react-server" condition (#28835)
This is a Fizz server.
2024-04-12 15:53:41 -04:00
Sebastian Silbermann
adb7173938 Fix nightly release job for real (#28825) 2024-04-11 18:28:10 +02:00
Sebastian Silbermann
a2582074b8 Fix nightly release job (#28824) 2024-04-11 18:08:13 +02:00
Ricky
608edcc90a [tests] add assertConsole<method>Dev helpers (#28732)
## Overview
**Internal React repo tests only**

Depends on https://github.com/facebook/react/pull/28710

Adds three new assertions:
- `assertConsoleLogDev`
- `assertConsoleWarnDev`
- `assertConsoleErrorDev`

These will replace this pattern:

```js
await expect(async () => {
  await expect(async () => {
    await act(() => {
      root.render(<Fail />)
    });
  }).toThrow();
}).toWarnDev('Warning');
```

With this:

```js
await expect(async () => {
  await act(() => {
    root.render(<Fail />)
  });
}).toThrow();

assertConsoleWarnDev('Warning');
```

It works similar to our other `assertLog` matchers which clear the log
and assert on it, failing the tests if the log is not asserted before
the test ends.

## Diffs

There are a few improvements I also added including better log diffs and
more logging.

When there's a failure, the output will look something like:

<img width="655" alt="Screenshot 2024-04-03 at 11 50 08 AM"
src="https://github.com/facebook/react/assets/2440089/0c4bf1b2-5f63-4204-8af3-09e0c2d752ad">


Check out the test suite for snapshots of all the failures we may log.
2024-04-11 08:19:46 -04:00
Andrew Clark
374b5d26c2 Scaffolding for requestFormReset API (#28808)
Based on:

- #28804 

---

This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.

Doing this in its own commit for review purposes.

The API itself will be explained in the next PR.
2024-04-10 16:55:15 -04:00
Ricky
3f947b1b46 [tests] Assert scheduler log empty in internalAct (#28737)
We should force `assertLog` to be called before each `act` block to
ensure the queue is empty.

Requires fixing tests:
- https://github.com/facebook/react/pull/28745
- https://github.com/facebook/react/pull/28758
- https://github.com/facebook/react/pull/28759
- https://github.com/facebook/react/pull/28760
- https://github.com/facebook/react/pull/28761
- https://github.com/facebook/react/pull/28762
- https://github.com/facebook/react/pull/28763
- https://github.com/facebook/react/pull/28812
2024-04-10 14:13:46 -04:00
Ricky
84cb3b4cb2 Hardcode disableIEWorkarounds for www (#28811)
This has landed and is true everywhere, but let's keep the flag until it
lands in the stable release.
2024-04-10 11:14:33 -04:00
Josh Story
bf40b02442 [Fizz] Stop publishing external-runtime to stable channel (#28796)
The external runtime is not vetted for stability yet. We should stop
publishing it with our stable build
2024-04-09 11:57:58 -07:00
Josh Story
67ff96e12d [Tests][Fizz] Test script runtime even when external runtime is available (#28794)
Previously if the external runtime was enabled Fizz tests would use it
exclusively. However now that this flag is enabled for OSS and Meta
builds this means we were no longer testing the inline script runtime.
This changes the test flags to produce some runs where we test the
inline script runtime and others where we test the external runtime

the external runtime will be tested if the flag is enabled and
* Meta Builds: variant is true
* OSS Builds: experiemental is true

this gives us decent coverage. long term we should probably bring
variant to OSS builds since we will eventually want to test both modes
even when the external runtime is stable.
2024-04-09 11:50:02 -07:00
Josh Story
7f93cb41c8 [DOM] Infer react-server entries bundles if not explicitly configured (#28795)
When packaging we want to infer that a bundle exists for a
`react-server` file even if it isn't explicitly configured. This is
useful in particular for the react-server entrypoints that error on
import that were recently added to `react-dom`

This change also cleans up a wayward comment left behind in a prior PR
2024-04-09 10:39:25 -07:00
Sebastian Markbåge
f613165357 Rename SECRET INTERNALS to __CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE (#28789)
Follow up to #28783 and #28786.

Since we've changed the implementations of these we can rename them to
something a bit more descriptive while we're at it, since anyone
depending on them will need to upgrade their code anyway.

"react" with no condition:
`__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE`
"react" with "react-server" condition:
`__SERVER_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE`
"react-dom":
`__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE`
2024-04-09 12:20:22 -04:00
Sebastian Markbåge
c771016e19 Rename The Secret Export of Server Internals (#28786)
We have a different set of dispatchers that Flight uses. This also
includes the `jsx-runtime` which must also be aliased to use the right
version.

To ensure the right versions are used together we rename the export of
the SharedInternals from 'react' and alias it in relevant bundles.
2024-04-08 22:34:59 -04:00
Sebastian Markbåge
d50323eb84 Flatten ReactSharedInternals (#28783)
This is similar to #28771 but for isomorphic. We need a make over for
these dispatchers anyway so this is the first step. Also helps flush out
some internals usage that will break anyway.

It flattens the inner mutable objects onto the ReactSharedInternals.
2024-04-08 19:23:23 -04:00
Josh Story
9007fdc8f1 [DOM] Shrink ReactDOMSharedInternals source representation (#28771)
Stacked on #28751 

ReactDOMSharedInternals uses properties of considerable length to model
mutuable state. These properties are not mangled during minification and
contribute a not insigificant amount to the uncompressed bundle size and
to a lesser degree compressed bundle size.

This change rewrites the DOMInternals in a way that shortens property
names so we can have smaller builds.
It also treats the entire object as a mutable container rather than
having different mutable sub objects.

The same treatment should be given to ReactSharedInternals
2024-04-08 13:39:39 -07:00
Josh Story
01bb3c5632 [TestUtils] Build limited test-utils (#28782)
We landed a flag to disable test utils in many builds but we need to
fork the entrypoint to make it work with tests properly. This also
removes test-utils implementations from builds that do not support it.
Currently in OSS builds the only thing in test-utils is a reexport of
`act`
2024-04-08 12:27:20 -07:00
Josh Story
4c12339ce3 [DOM] move flushSync out of the reconciler (#28500)
This PR moves `flushSync` out of the reconciler. there is still an
internal implementation that is used when these semantics are needed for
React methods such as `unmount` on roots.

This new isomorphic `flushSync` is only used in builds that no longer
support legacy mode.

Additionally all the internal uses of flushSync in the reconciler have
been replaced with more direct methods. There is a new
`updateContainerSync` method which updates a container but forces it to
the Sync lane and flushes passive effects if necessary. This combined
with flushSyncWork can be used to replace flushSync for all instances of
internal usage.

We still maintain the original flushSync implementation as
`flushSyncFromReconciler` because it will be used as the flushSync
implementation for FB builds. This is because it has special legacy mode
handling that the new isomorphic implementation does not need to
consider. It will be removed from production OSS builds by closure
though
2024-04-08 09:03:20 -07:00
Sebastian Markbåge
6090cab099 Use a Wrapper Error for onRecoverableError with a "cause" Field for the real Error (#28736)
We basically have four kinds of recoverable errors:

- Hydration mismatches.
- Server errored but client didn't.
- Hydration render errored but client render didn't (in Root or Suspense
boundary).
- Concurrent render errored but synchronous render didn't.

For the first three we log an additional error that the root or Suspense
boundary didn't error. This provides some context about what happened.
However, the problem is that for hydration mismatches that's unnecessary
extra context that is confusing. We also don't log any additional
context for concurrent render errors that could recover. This used to be
the only recoverable error so it didn't need extra context but now we
need to distinguish them. When we log these to `reportError` it's
confusing to just see the error because you didn't see anything error on
the page. It's also hard to group them together as one.

In this PR, I remove the unnecessary context for hydration mismatches.

For hydration and concurrent errors, I now wrap them in an error that
describes that what happened but then use the new `cause` field to link
the original error so we can keep that as the cause. The error that
happened was that hydration client rendered or you deopted to sync
render, the cause of that error is some other error.

For server errors, we control the Error object so I already had added
some context to that error object's message. Since we hide the message
in prod, it's nice not to have the raw message in DEV neither. We could
potentially split these into two errors for parity though.
2024-04-03 21:53:07 -04:00
Ricky
a5aedd1e15 Move console mocks to internal-test-utils (#28710)
Moving this to `internal-test-utils` so I can add helpers in the next PR
for:
- assertLogDev
- assertWarnDev
- assertErrorDev

Which will be exported from `internal-test-utils`. This isn't strictly
necessary, but it makes the factoring nicer, so internal-test-until
doesn't need to depend on `scripts/jest`.
2024-04-03 16:02:04 -04:00
Jan Kassens
4e8121a75e Remove @providesModule remnants (#28720)
Remove @providesModule remnants

Removes `@providesModule` from the generated RN modules and CI
validation that no `@providesModule` is added which should no longer be
needed as this has been the case for years now.
2024-04-03 09:10:00 -04:00
Josh Story
cb6dc7a6a0 [FB] use modern entrypoint in tests (#28724)
Removes the entrypoint hack in tests since we gate legacy mode tests now
2024-04-02 22:23:54 -07:00
Jan Kassens
7659c4d9e0 Remove dynamic www flag for disableInputAttributeSyncing (#28703)
Remove dynamic www flag for disableInputAttributeSyncing
2024-04-02 10:57:23 -04:00
Ricky
6e65010999 [tests] Disallow unasserted console.log (#28708)
Followup from https://github.com/facebook/react/pull/28693 and
https://github.com/facebook/react/pull/28680.

In CI, we fail the test for any unasserted console.log. In DEV, we don't
fail, but you can still use the matchers and we'll assert on them.
2024-04-01 17:45:49 -04:00
Jack Pope
95e6f032cf Clarify RTR native feature flags are fb specific (#28679)
Make it more clear that these flags aren't used in RN OSS.
- Rename
`packages/shared/forks/ReactFeatureFlags.test-renderer.native.js` to
`packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js`
- Remove RN OSS build cases consuming the feature flags since there is
no RN OSS RTR build.
2024-04-01 10:56:28 -04:00
Sebastian Markbåge
b9149cc6e6 Include regular stack trace in serialized errors from Fizz (#28684)
We previously only included the component stack.
    
Cleaned up the fields in Fizz server that wasn't using consistent hidden
classes in dev vs prod.

Added a prefix to errors serialized from server rendering. It can be a
bit confusing to see where this error came from otherwise since it
didn't come from elsewhere on the client. It's really kind of confusing
with other recoverable errors that happen on the client too.
2024-03-30 11:08:54 -04:00
Sebastian Markbåge
323b6e98a7 Remove errorHydratingContainer (#28664)
I originally added this in #21021 but I didn't mention why and I don't
quite remember why. Maybe because there were no other message? However
at the time the recoverable errors mechanism didn't exist.

Today I believe all cases where this happens will trigger another
recoverable error. Namely these two:


9f33f699e4/packages/react-reconciler/src/ReactFiberBeginWork.js (L1442-L1446)


9f33f699e4/packages/react-reconciler/src/ReactFiberBeginWork.js (L2962-L2965)

Therefore this is just an extra unnecessary log.
2024-03-27 23:48:18 -04:00
Sebastian Markbåge
a053716077 Make onUncaughtError and onCaughtError Configurable (#28641)
Stacked on #28627.

This makes error logging configurable using these
`createRoot`/`hydrateRoot` options:

```
onUncaughtError(error: mixed, errorInfo: {componentStack?: ?string}) => void
onCaughtError(error: mixed, errorInfo: {componentStack?: ?string, errorBoundary?: ?React.Component<any, any>}) => void
onRecoverableError(error: mixed, errorInfo: {digest?: ?string, componentStack?: ?string}) => void
```

We already have the `onRecoverableError` option since before.

Overriding these can be used to implement custom error dialogs (with
access to the `componentStack`).

It can also be used to silence caught errors when testing an error
boundary or if you prefer not getting logs for caught errors that you've
already handled in an error boundary.

I currently expose the error boundary instance but I think we should
probably remove that since it doesn't make sense for non-class error
boundaries and isn't very useful anyway. It's also unclear what it
should do when an error is rethrown from one boundary to another.

Since these are public APIs now we can implement the
ReactFiberErrorDialog forks using these options at the roots of the
builds. So I unforked those files and instead passed a custom option for
the native and www builds.

To do this I had to fork the ReactDOMLegacy file into ReactDOMRootFB
which is a duplication but that will go away as soon as the FB fork is
the only legacy root.
2024-03-27 00:51:37 -04:00
Sebastian Markbåge
6786563f3c [Fiber] Don't Rethrow Errors at the Root (#28627)
Stacked on top of #28498 for test fixes.

### Don't Rethrow

When we started React it was 1:1 setState calls a series of renders and
if they error, it errors where the setState was called. Simple. However,
then batching came and the error actually got thrown somewhere else.
With concurrent mode, it's not even possible to get setState itself to
throw anymore.

In fact, all APIs that can rethrow out of React are executed either at
the root of the scheduler or inside a DOM event handler.
If you throw inside a React.startTransition callback that's sync, then
that will bubble out of the startTransition but if you throw inside an
async callback or a useTransition we now need to handle it at the hook
site. So in 19 we need to make all React.startTransition swallow the
error (and report them to reportError).

The only one remaining that can throw is flushSync but it doesn't really
make sense for it to throw at the callsite neither because batching.
Just because something rendered in this flush doesn't mean it was
rendered due to what was just scheduled and doesn't mean that it should
abort any of the remaining code afterwards. setState is fire and forget.
It's send an instruction elsewhere, it's not part of the current
imperative code.

Error boundaries never rethrow. Since you should really always have
error boundaries, most of the time, it wouldn't rethrow anyway.

Rethrowing also actually currently drops errors on the floor since we
can only rethrow the first error, so to avoid that we'd need to call
reportError anyway. This happens in RN events.

The other issue with rethrowing is that it logs an extra console.error.
Since we're not sure that user code will actually log it anywhere we
still log it too just like we do with errors inside error boundaries
which leads all of these to log twice.
The goal of this PR is to never rethrow out of React instead, errors
outside of error boundaries get logged to reportError. Event system
errors too.

### Breaking Changes

The main thing this affects is testing where you want to inspect the
errors thrown. To make it easier to port, if you're inside `act` we
track the error into act in an aggregate error and then rethrow it at
the root of `act`. Unlike before though, if you flush synchronously
inside of act it'll still continue until the end of act before
rethrowing.

I expect most user code breakages would be to migrate from `flushSync`
to `act` if you assert on throwing.

However, in the React repo we also have `internalAct` and the
`waitForThrow` helpers. Since these have to use public production
implementations we track these using the global onerror or process
uncaughtException. Unlike regular act, includes both event handler
errors and onRecoverableError by default too. Not just render/commit
errors. So I had to account for that in our tests.

We restore logging an extra log for uncaught errors after the main log
with the component stack in it. We use `console.warn`. This is not yet
ignorable if you preventDefault to the main error event. To avoid
confusion if you don't end up logging the error to console I just added
`An error occurred`.

### Polyfill

All browsers we support really supports `reportError` but not all test
and server environments do, so I implemented a polyfill for browser and
node in `shared/reportGlobalError`. I don't love that this is included
in all builds and gets duplicated into isomorphic even though it's not
actually needed in production. Maybe in the future we can require a
polyfill for this.

### Follow Ups

In a follow up, I'll make caught vs uncaught error handling be
configurable too.

---------

Co-authored-by: Ricky Hanlon <rickhanlonii@gmail.com>
2024-03-26 23:44:07 -04:00
Sebastian Markbåge
f7aa5e0aa3 Move Hydration Mismatch Errors to Throw or Log Once (Kind of) (#28502)
Stacked on #28476.

We used to `console.error` for every mismatch we found, up until the
error we threw for the hydration mismatch.

This changes it so that we build up a set of diffs up until we either
throw or complete hydrating the root/suspense boundary. If we throw, we
append the diff to the error message which gets passed to
onRecoverableError (which by default is also logged to console). If we
complete, we append it to a `console.error`.

Since we early abort when something throws, it effectively means that we
can only collect multiple diffs if there were preceding non-throwing
mismatches - i.e. only properties mismatched but tag name matched.

There can still be multiple logs if multiple siblings Suspense
boundaries all error hydrating but then they're separate errors
entirely.

We still log an extra line about something erroring but I think the goal
should be that it leads to a single recoverable or console.error.

This doesn't yet actually print the diff as part of this message. That's
in a follow up PR.
2024-03-26 20:01:41 -04:00
Sebastian Markbåge
4b8dfd6215 Move Hydration Warnings from the DOM Config into the Fiber reconciliation (#28476)
Stacked on #28458.

This doesn't actually really change the messages yet, it's just a
refactor.

Hydration warnings can be presented either as HTML or React JSX format.
If presented as HTML it makes more sense to make that a DOM specific
concept, however, I think it's actually better to present it in terms of
React JSX.

Most of the time the errors aren't going to be something messing with
them at the HTML/HTTP layer. It's because the JS code does something
different. Most of the time you're working in just React. People don't
necessarily even know what the HTML form of it looks like. So this takes
the approach that the warnings are presented in React JSX in their rich
object form.

Therefore, I'm moving the approach to yield diff data to the reconciler
but it's the reconciler that's actually printing all the warnings.
2024-03-26 19:04:18 -04:00
Jack Pope
f73d11f092 [RTR] Enable warning flag (#28419)
## Summary

Based on
- https://github.com/facebook/react/pull/27903

This PR
- Silence warning in React tests
- Turn on flag

We want to finish cleaning up internal RTR usage, but let's prioritize
the deprecation process. We do this by silencing the internal warning
for now.

## How did you test this change?

`yarn build`
`yarn test ReactHooksInspectionIntegration -b`
2024-03-26 17:44:31 -04:00
Ricky
dbfbfb3312 Update error messages (#28652)
## Overview

The error messages that say:

> ReactDOM.hydrate is no longer supported in React 18

Don't make sense in the React 19 release. Instead, they should say:

> ReactDOM.hydrate was removed in React 19.

For legacy mode, they should say:

> ReactDOM.hydrate has not been supported since React 18.
2024-03-26 17:25:53 -04:00
Jan Kassens
95319ab5af Switch facebook-www build version to file content hash (#28633)
Unifies the React version string pattern with RN just to simplify the
build script a tiny bit and not have 2 mechanisms for the Meta-internal
build.
2024-03-26 12:13:46 -04:00
Ricky
fabd6d3a64 Better NEXT_MAJOR support for RN flags (#28583)
The `__NEXT_MAJOR__` value in the RN flags doesn't make sense because:

a) The flags are for the next RN major, since it only impacts the
renderers
b) The flags are off, so they're not currently in the next major, they
need enabled
c) the flag script didn't support it

This PR adds two aliases to the RN file:
- `__TODO_NEXT_RN_MAJOR__`: flags that need enabled before the next RN
major.
- `__NEXT_RN_MAJOR__`: flags that have been enabled since the last RN
major.

These values will need to be manually kept up to date when we cut a RN
version, but once RN switches to the canary build and aligns all the
flags, this entire file can be deleted.

## Script screen
Notably, I added a TODO value and a legend that prints at the end of the
script:

<img width="1078" alt="Screenshot 2024-03-18 at 8 11 27 PM"
src="https://github.com/facebook/react/assets/2440089/14da9066-f77d-437f-8188-830a31a843c5">
2024-03-22 13:02:04 -04:00
Ricky
fa0efa1ae3 Update RN dynamic flag types (#28427)
Updates the RN flag flow types to work like www does, so we can use the
`.native-fb-dynamic.js` file as the type/shim for the dynamically
imported file.
2024-03-22 12:23:38 -04:00
Jan Kassens
6708115937 Use declare const instead of declare var (#28599)
Use `declare const` instead of `declare var`
2024-03-22 11:20:18 -04:00
Sebastian Markbåge
72e02a8350 [Flight Reply] Don't allow Symbols to be passed to a reply (#28610)
As mentioned in #28609 there's a potential security risk if you allow a
passed value to the server to spoof Elements because it allows a hacker
to POST cross origin. This is only an issue if your framework allows
this which it shouldn't but it seems like we should provide an extra
layer of security here.

```js
function action(errors, payload) {
  try {
    ...
  } catch (x) {
    return [newError].concat(errors);
  }
}
```
```js
const [errors, formAction] = useActionState(action);
return <div>{errors}</div>;
```
This would allow you to construct a payload where the previous "errors"
set includes something like `<script src="danger.js" />`.

We could block only elements from being received but it could
potentially be a risk with creating other React types like Context too.
We use symbols as a way to securely brand these.

Most JS don't use this kind of branding with symbols like we do. They're
generally properties which we don't support anyway. However in theory
someone else could be using them like we do. So in an abundance of
carefulness I just ban all symbols from being passed (except by
temporary reference) - not just ours.

This means that the format isn't fully symmetric even beyond just React
Nodes.

#28611 allows code that includes symbols/elements to continue working
but may have to bail out to replaying instead of no JS sometimes.
However, you still can't access the symbols inside the server - they're
by reference only.
2024-03-21 16:53:02 -04:00
Andrew Clark
29a6ca33a5 Update gate pragma to detect global error events (#28591)
If a global error event is dispatched during a test, Jest reports that
test as a failure.

Our `@gate` pragma feature should account for this — if the gate
condition is false, and the global error event is dispatched, then the
test should be reported as a success.

The solution is to install an error event handler right before invoking
the test function. Because we install our own handler, Jest will not
report the test as a failure if a global error event is dispatched; it's
conceptually as if we wrapped the whole test event in a try-catch.
2024-03-19 21:08:37 -04:00
Jan Kassens
37676aba76 Also apply content hash for experimental files (#28590)
Also apply content hash for experimental files

In #28582 I missed that experimental files have a copy of this build
function setting the version strings.
2024-03-19 17:50:24 -04:00
Sebastian Markbåge
83409a1fdd [Flight] Encode React Elements in Replies as Temporary References (#28564)
Currently you can accidentally pass React Element to a Server Action. It
warns but in prod it actually works because we can encode the symbol and
otherwise it's mostly a plain object. It only works if you only pass
host components and no function props etc. which makes it potentially
error later. The first thing this does it just early hard error for
elements.

I made Lazy work by unwrapping though since that will be replaced by
Promises later which works.

Our protocol is not fully symmetric in that elements flow from Server ->
Client. Only the Server can resolve Components and only the client
should really be able to receive host components. It's not intended that
a Server can actually do something with them other than passing them to
the client.

In the case of a Reply, we expect the client to be stateful. It's
waiting for a response. So anything we can't serialize we can still pass
by reference to an in memory object. So I introduce the concept of a
TemporaryReferenceSet which is an opaque object that you create before
encoding the reply. This then stashes any unserializable values in this
set and encode the slot by id. When a new response from the Action then
returns we pass the same temporary set into the parser which can then
restore the objects. This lets you pass a value by reference to the
server and back into another slot.

For example it can be used to render children inside a parent tree from
a server action:

```
export async function Component({ children }) {
  "use server";
  return <div>{children}</div>;
}
```

(You wouldn't normally do this due to the waterfalls but for advanced
cases.)

A common scenario where this comes up accidentally today is in
`useActionState`.

```
export function action(state, formData) {
  "use server";
   if (errored) {
     return <div>This action <strong>errored</strong></div>;
   }
   return null;
}
```

```
const [errors, formAction] = useActionState(action);
return <div>{errors}<div>;
```

It feels like I'm just passing the JSX from server to client. However,
because `useActionState` also sends the previous state *back* to the
server this should not actually be valid. Before this PR this actually
worked accidentally. You get a DEV warning but it used to work in prod.
Once you do something like pass a client reference it won't work tho. We
could perhaps make client references work by stashing where we got them
from but it wouldn't work with all possible JSX.

By adding temporary references to the action implementation this will
work again - on the client. It'll also be more efficient since we don't
send back the JSX content that you shouldn't introspect on the server
anyway.

However, a flaw here is that the progressive enhancement of this case
won't work because we can't use temporary references for progressive
enhancement since there's no in memory stash. What is worse is that it
won't error if you hydrate. ~It also will error late in the example
above because the first state is "undefined" so invoking the form once
works - it errors on the second attempt when it tries to send the error
state back again.~ It actually errors on the first invocation because we
need to eagerly serialize "previous state" into the form. So at least
that's better.

I think maybe the solution to this particular pattern would be to allow
JSX to serialize if you have no temporary reference set, and remember
client references so that client references can be returned back to the
server as client references. That way anything you could send from the
server could also be returned to the server. But it would only deopt to
serializing it for progressive enhancement. The consequence of that
would be that there's a lot of JSX that might accidentally seem like it
should work but it's only if you've gotten it from the server before
that it works. This would have to have pair them somehow though since
you can't take a client reference from one implementation of Flight and
use it with another.
2024-03-19 16:59:52 -04:00
Jan Kassens
cb076b593c Change to content hash for RN canary VERSION strings (#28582)
With this change, the different files in RN will have *different*
hashes. This replaces the git hash and means that the file content
(including version) is only updated when the rest of the file content
actually changes. This should remove "noop" changes that need to be
synced that only update the version string.

A difference to the www implementation here is (and I'd be looking at
updating www as well if this lands well) that each file has an
individual hash instead of a combined content hash. This further reduces
the number of updated files and I couldn't find a reason we need to have
these in sync. The best I can gather is that this hash is used so folks
don't directly compare version string and make future updates harder.
2024-03-19 16:16:34 -04:00
Timothy Yung
0aab065eb3 Add alwaysThrottleDisappearingFallbacks Flag (#28550)
## Summary

Creates a new `alwaysThrottleDisappearingFallbacks` feature flag that
gates the changes from https://github.com/facebook/react/pull/26802
(instead of being controlled by `alwaysThrottleRetries`). The values of
this new flag mirror the current values of `alwaysThrottleRetries` such
that there is no behavior difference.

This additional feature flag allows us to incrementally validate the
change (arguably bug fix) from
https://github.com/facebook/react/pull/26802 independently from
`alwaysThrottleRetries`.

## How did you test this change?

```
$ yarn test
$ yarn flow dom-browser
$ yarn flow dom-fb
$ yarn flow fabric
```
2024-03-18 11:16:47 -07:00
Rubén Norte
bb0944fe5b [RN] Use microtasks in the RN renderer based on a global flag defined by RN (#28472)
## Summary

We want to enable the new event loop in React Native
(https://github.com/react-native-community/discussions-and-proposals/pull/744)
for all users in the new architecture (determined by the use of
bridgeless, not by the use of Fabric). In order to leverage that, we
need to also set the flag for the React reconciler to use microtasks for
scheduling (so we'll execute them at the right time in the new event
loop).

This migrates from the previous approach using a dynamic flag (to be
used at Meta) with the check of a global set by React Native. The reason
for doing this is:
1) We still need to determine this dynamically in OSS (based on
Bridgeless, not on Fabric).
2) We still need the ability to configure the behavior at Meta, and for
internal build system reasons we cannot access the flag that enables
microtasks in
[`ReactNativeFeatureFlags`](6c28c87c4d/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js (L121)).

## How did you test this change?

Manually synchronized the changes to React Native and ran all tests for
the new architecture on it. Also tested manually.

> [!NOTE]
> This change depends on
https://github.com/facebook/react-native/pull/43397 which has been
merged already
2024-03-13 10:00:10 +00:00
Jan Kassens
eb33bd7477 Remove renderSubtreeIntoContainer_DO_NOT_USE (#28526)
Since D54648741 we no longer need this shim. 

NOTE: There is still some work left to remove the
`unstable_renderSubtreeIntoContainer` export.
2024-03-12 11:31:34 -04:00
Sebastian Markbåge
89021fb4ec Remove invokeGuardedCallback and replay trick (#28515)
We broke the ability to "break on uncaught exceptions" by adding a
try/catch higher up in the scheduling. We're giving up on fixing that so
we can remove the replay trick inside an event handler.

The issue with that approach is that we end up double logging a lot of
errors in DEV since they get reported to the page.

It's also a lot of complexity around this feature.
2024-03-11 20:17:07 -04:00
Timothy Yung
706d95f486 Configure Dynamic Feature Flags for React Native (#28527)
## Summary

This PR is a subset of https://github.com/facebook/react/pull/28425,
which only includes the feature flags that will be configured as
dynamic.

The following list summarizes the feature flag changes:

* RN FB
  * Change to Dynamic
    * consoleManagedByDevToolsDuringStrictMode
    * enableAsyncActions
    * enableDeferRootSchedulingToMicrotask
    * enableRenderableContext
    * useModernStrictMode

## How did you test this change?

Ran the following successfully:

```
$ yarn test
$ yarn flow native
$ yarn flow fabric
```
2024-03-08 16:14:09 -08:00
Josh Story
113ab9af08 [Flight][Fizz][Fiber] Chain HostDispatcher implementations (#28488)
The idea here is that host dispatchers are not bound to renders so we
need to be able to dispatch to them at any time. This updates the
implementation to chain these dispatchers so that each renderer can
respond to the dispatch. Semantically we don't always want every
renderer to do this for instance if Fizz handles a float method we don't
want Fiber to as well so each dispatcher implementation can decide if it
makes sense to forward the call or not. For float methods server
disaptchers will handle the call if they can resolve a Request otherwise
they will forward. For client dispatchers they will handle the call and
always forward. The choice needs to be made for each dispatcher method
and may have implications on correct renderer import order. For now we
just live with the restriction that if you want to use server and client
together (such as renderToString in the browser) you need to import the
server renderer after the client renderer.
2024-03-04 12:27:15 -08:00
Josh Story
1c02b9d2bd [DOM] disable legacy mode behind flag (#28468)
Adds a flag to disable legacy mode. Currently this flag is used to cause
legacy mode apis like render and hydrate to throw. This change also
removes render, hydrate, unmountComponentAtNode, and
unstable_renderSubtreeIntoContainer from the experiemntal entrypoint.
Right now for Meta builds this flag is off (legacy mode is still
supported). In OSS builds this flag matches __NEXT_MAJOR__ which means
it currently is on in experiemental. This means that after merging
legacy mode is effectively removed from experimental builds. While this
is a breaking change, experimental builds are not stable and users can
pin to older versions or update their use of react-dom to no longer use
legacy mode APIs.
2024-03-04 08:19:17 -08:00