Following #28768, add a path to testing Fast JSX on www.
We want to measure the impact of Fast JSX and enable a path to testing
before string refs are completely removed in www (which is a work in
progress).
Without `disableStringRefs`, we need to copy any object with a `ref` key
so we can pass it through `coerceStringRef()` and copy it into the
object. This de-opt path is what is gated behind
`enableFastJSXWithStringRefs`.
The additional checks should have no perf impact in OSS as the flags
remain true there and the build output is not changed. For www, I've
benchmarked the addition of the boolean checks with values cached at
module scope. There is no significant change observed from our
benchmarks and any latency will apply to test and control branches
evenly. This added experiment complexity is temporary. We should be able
to clean it up, along with the flag checks for `enableRefAsProp` and
`disableStringRefs` shortly.
## Summary
This PR introduces a faster version of the `addProperties` function.
This new function is basically the `diffProperties` with `prevProps` set
to `null`, propagated constants, and all the unreachable code paths
collapsed.
## How did you test this change?
I've tested this change with [the benchmark
app](https://github.com/react-native-community/RNNewArchitectureApp/tree/new-architecture-benchmarks)
and got ~4.4% improvement in the view creation time.
This removes the automatic patching of the global `fetch` function in
Server Components environments to dedupe requests using `React.cache`, a
behavior that some RSC framework maintainers have objected to.
We may revisit this decision in the future, but for now it's not worth
the controversy.
Frameworks that have already shipped this behavior, like Next.js, can
reimplement it in userspace.
I considered keeping the implementation in the codebase and disabling it
by setting `enableFetchInstrumentation` to `false` everywhere, but since
that also disables the tests, it doesn't seem worth it because without
test coverage the behavior is likely to drift regardless. We can just
revert this PR later if desired.
Stacked on #28849, #28854, #28853. Behind a flag.
If you're following along from the side-lines. This is probably not what
you think it is.
It's NOT a way to get updates to a component over time. The
AsyncIterable works like an Iterable already works in React which is how
an Array works. I.e. it's a list of children - not the value of a child
over time.
It also doesn't actually render one component at a time. The way it
works is more like awaiting the entire list to become an array and then
it shows up. Before that it suspends the parent.
To actually get these to display one at a time, you have to opt-in with
`<SuspenseList>` to describe how they should appear. That's really the
interesting part and that not implemented yet.
Additionally, since these are effectively Async Functions and uncached
promises, they're not actually fully "supported" on the client yet for
the same reason rendering plain Promises and Async Functions aren't.
They warn. It's only really useful when paired with RSC that produces
instrumented versions of these. Ideally we'd published instrumented
helpers to help with map/filter style operations that yield new
instrumented AsyncIterables.
The way the implementation works basically just relies on unwrapThenable
and otherwise works like a plain Iterator.
There is one quirk with these that are different than just promises. We
ask for a new iterator each time we rerender. This means that upon retry
we kick off another iteration which itself might kick off new requests
that block iterating further. To solve this and make it actually
efficient enough to use on the client we'd need to stash something like
a buffer of the previous iteration and maybe iterator on the iterable so
that we can continue where we left off or synchronously iterate if we've
seen it before. Similar to our `.value` convention on Promises.
In Fizz, I had to do a special case because when we render an iterator
child we don't actually rerender the parent again like we do in Fiber.
However, it's more efficient to just continue on where we left off by
reusing the entries from the thenable state from before in that case.
We have changed the shape (and the runtime) of React Elements. To help
avoid precompiled or inlined JSX having subtle breakages or deopting
hidden classes, I renamed the symbol so that we can early error if
private implementation details are used or mismatching versions are
used.
Why "transitional"? Well, because this is not the last time we'll change
the shape. This is just a stepping stone to removing the `ref` field on
the elements in the next version so we'll likely have to do it again.
Adds an experimental feature flag to the implementation of useMemoCache,
the internal cache used by the React Compiler (Forget).
When enabled, instead of treating the cache as copy-on-write, like we do
with fibers, we share the same cache instance across all render
attempts, even if the component is interrupted before it commits.
If an update is interrupted, either because it suspended or because of
another update, we can reuse the memoized computations from the previous
attempt. We can do this because the React Compiler performs atomic
writes to the memo cache, i.e. it will not record the inputs to a
memoization without also recording its output.
This gives us a form of "resuming" within components and hooks.
This only works when updating a component that already mounted. It has
no impact during initial render, because the memo cache is stored on the
fiber, and since we have not implemented resuming for fibers, it's
always a fresh memo cache, anyway.
However, this alone is pretty useful — it happens whenever you update
the UI with fresh data after a mutation/action, which is extremely
common in a Suspense-driven (e.g. RSC or Relay) app.
So the impact of this feature is faster data mutations/actions (when the
React Compiler is used).
## Summary
This PR adds early return to the `diff` function. We don't need to go
through all the entries of `nextProps`, process and deep-diff the values
if `nextProps` is the same object as `prevProps`. Roughly 6% of all
`diffProperties` calls can be skipped.
## How did you test this change?
RNTester.
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.
Per team discussion, this upgrades the `initialValue` argument for
`useDeferredValue` from experimental to canary.
- Original implementation PR:
https://github.com/facebook/react/pull/27500
- API documentation PR: https://github.com/reactjs/react.dev/pull/6747
I left it disabled at Meta for now in case there's old code somewhere
that is still passing an `options` object as the second argument.
This removes defaultProps support for all component types except for
classes. We've chosen to continue supporting defaultProps for classes
because lots of older code relies on it, and unlike function components,
(which can use default params), there's no straightforward alternative.
By implication, it also removes support for setting defaultProps on
`React.lazy` wrapper. So this will not work:
```js
const MyClassComponent = React.lazy(() => import('./MyClassComponent'));
// MyClassComponent is not actually a class; it's a lazy wrapper. So
// defaultProps does not work.
MyClassComponent.defaultProps = { foo: 'bar' };
```
However, if you set the default props on the class itself, then it's
fine.
For classes, this change also moves where defaultProps are resolved.
Previously, defaultProps were resolved by the JSX runtime. This change
is only observable if you introspect a JSX element, which is relatively
rare but does happen.
In other words, previously `<ClassWithDefaultProp />.props.aDefaultProp`
would resolve to the default prop value, but now it does not.
Cleanup enableUseRefAccessWarning flag
I don't think this flag has a path forward in the current
implementation. The detection by stack trace is too brittle to detect
the lazy initialization pattern reliably (see e.g. some internal tests
that expect the warning because they use lazy intialization, but a
slightly different pattern then the expected pattern.
I think a new version of this could be to fully ban ref access during
render with an alternative API for the exceptional cases that today
require ref access during render.
Only the FB entry point has legacy mode now so we can move the remaining
code in there.
Also enable disableLegacyMode in modern www builds since it doesn't
expose those entry points.
Now dependent on #28709.
---------
Co-authored-by: Josh Story <story@hey.com>
We've rolled out this flag internally on WWW. This PR removed flag
`enableCustomElementPropertySupport`
Test plan:
-- `yarn test`
Co-authored-by: Ricky Hanlon <rickhanlonii@gmail.com>
Remove module pattern function component support (flag only)
> This is a redo of #27742, but only including the flag removal,
excluding further simplifications.
The module pattern
```
function MyComponent() {
return {
render() {
return this.state.foo
}
}
}
```
has been deprecated for approximately 5 years now. This PR removes
support for this pattern.
This breaks internal tests, so must be something in the refactor. Since
it's the top commit let's revert and split into two PRs, one that
removes the flag and one that does the refactor, so we can find the bug.
The module pattern
```
function MyComponent() {
return {
render() {
return this.state.foo
}
}
}
```
has been deprecated for approximately 5 years now. This PR removes
support for this pattern. It also simplifies a number of code paths in
particular related to the concept of `IndeterminateComponent` types.
## Overview
This has landed, so we can remove the flag
## Changelog
This change blocks using javascript URLs such as:
```html
<a href="javascript:notfine">p0wned</a>
```
We previously announced dropping support for this via a warning:
> A future version of React will block javascript: URLs as a security
precaution. Use event handlers instead if you can. If you need to
generate unsafe HTML try using dangerouslySetInnerHTML instead.
If false, this ignores text comparison checks during hydration at the
risk of privacy safety.
Since React 18 we recreate the DOM starting from the nearest Suspense
boundary if any of the text content mismatches. This ensures that if we
have nodes that otherwise line up correctly such as if they're the same
type of Component but in a different order, then we don't accidentally
transfer state or attributes to the wrong one.
If we didn't do this e.g. attributes like image src might not line up
with the text. E.g. you might show the wrong profile picture with the
wrong name. However, the main reason we do this is because it's a
security/privacy concern if state from the original node can transfer to
the other one. For example if you start typing into a text field to
reply to a story but then it turns out that the hydration was in a
different order, you might submit that text into a different story than
you intended. Similarly, if you've already clicked an item and that gets
replayed using Action replaying or is synchronously force hydrated -
that click might end up applying to a different item in the list than
you intended. E.g. liking the wrong photo.
Unfortunately a common case where this happens is when Google Translate
is applied to a page. It'll always cause mismatches and recreate the
tree. Most of the time this wouldn't be visible to users because it'd
just recreate to the same thing and then translate again. It can affect
metrics that trace when this hydration happened though.
Meta can use this flag to decide if they favor this perf metric over the
risk to user privacy.
This is similar to the old enableClientRenderFallbackOnTextMismatch flag
except this flag doesn't patch up the text when there's a mismatch.
Because we don't have the patching anymore. The assumption is that it is
safe to ignore the safety concern because we assume it's a match and
therefore favoring not patching it will lead to better perf.
## 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`
## Summary
After realizing that this feature flag is entangled with
`alwaysThrottleRetries`, we're going to undo
https://github.com/facebook/react/pull/28550
## How did you test this change?
```
$ yarn test
$ yarn flow dom-browser
$ yarn flow dom-fb
$ yarn flow fabric
```
## 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
```
## 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
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.
## Summary
Looks like this was added years ago for instrumentation at meta that
never ended up rolling out. Should be safe to clean up.
## How did you test this change?
`yarn test`
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.
Depends on:
- https://github.com/facebook/react/pull/28398
---
This removes string refs, which has been deprecated in Strict Mode for
seven years.
I've left them behind a flag for Meta, but in open source this fully
removes the feature.
## Summary
Moving towards deprecation of ReactTestRenderer. Log a warning on each
render so we can remove the exports in a future major version.
We can enable this flag in web RTR without disrupting RN tests by
flipping the flag in
`packages/shared/forks/ReactFeatureFlags.test-renderer.js`
## How did you test this change?
`yarn test
packages/react-test-renderer/src/__tests__/ReactTestRenderer-test.js`
When developing in an RSC environment, you should be able to work in a
single environment as if it was a unified environment. With thrown
errors we already serialize them and then rethrow them on the client.
Since by default we log them via onError both in Flight and Fizz, you
can get the same log in the RSC runtime, the SSR runtime and on the
client.
With console logs made in SSR renders, you typically replay the same
code during hydration on the client. So for example warnings already
show up both in the SSR logs and on the client (although not guaranteed
to be the same). You could just spend your time in the client and you'd
be fine.
Previously, RSC logs would not be replayed because they don't hydrate.
So it's easy to miss warnings for example.
With this approach, we replay RSC logs both during SSR so they end up in
the SSR logs and on the client. That way you can just stay in the
browser window during normal development cycles. You shouldn't have to
care if your component is a server or client component when working on
logical things or iterating on a product.
With this change, you probably should mostly ignore the Flight log
stream and just look at the client or maybe the SSR one. Unless you're
digging into something specific. In particular if you just naively run
both Flight and Fizz in the same terminal you get duplicates. I like to
run out fixtures `yarn dev:region` and `yarn dev:global` in two separate
terminals.
Console logs may contain complex objects which can be inspected. Ideally
a DevTools inspector could reach into the RSC server and remotely
inspect objects using the remote inspection protocol. That way complex
objects can be loaded on demand as you expand into them. However, that
is a complex environment to set up and the server might not even be
alive anymore by the time you inspect the objects. Therefore, I do a
best effort to serialize the objects using the RSC protocol but limit
the depth that can be rendered.
This feature is only own in dev mode since it can be expensive.
In a follow up, I'll give the logs a special styling treatment to
clearly differentiate them from logs coming from the client. As well as
deal with stacks.
Depends on:
- #28317
- #28320
---
Changes the behavior of the JSX runtime to pass through `ref` as a
normal prop, rather than plucking it from the props object and storing
on the element.
This is a breaking change since it changes the type of the receiving
component. However, most code is unaffected since it's unlikely that a
component would have attempted to access a `ref` prop, since it was not
possible to get a reference to one.
`forwardRef` _will_ still pluck `ref` from the props object, though,
since it's extremely common for users to spread the props object onto
the inner component and pass `ref` as a differently named prop. This is
for maximum compatibility with existing code — the real impact of this
change is that `forwardRef` is no longer required.
Currently, refs are resolved during child reconciliation and stored on
the fiber. As a result of this change, we can move ref resolution to
happen only much later, and only for components that actually use them.
Then we can remove the `ref` field from the Fiber type. I have not yet
done that in this step, though.
Previously, `<Context>` was equivalent to `<Context.Consumer>`. However,
since the introduction of Hooks, the `<Context.Consumer>` API is rarely
used. The goal here is to make the common case cleaner:
```js
const ThemeContext = createContext('light')
function App() {
return (
<ThemeContext value="dark">
...
</ThemeContext>
)
}
function Button() {
const theme = use(ThemeContext)
// ...
}
```
This is technically a breaking change, but we've been warning about
rendering `<Context>` directly for several years by now, so it's
unlikely much code in the wild depends on the old behavior. [Proof that
it warns today (check
console).](https://codesandbox.io/p/sandbox/peaceful-nobel-pdxtfl)
---
**The relevant commit is 5696782b428a5ace96e66c1857e13249b6c07958.** It
switches `createContext` implementation so that `Context.Provider ===
Context`.
The main assumption that changed is that a Provider's fiber type is now
the context itself (rather than an intermediate object). Whereas a
Consumer's fiber type is now always an intermediate object (rather than
it being sometimes the context itself and sometimes an intermediate
object).
My methodology was to start with the relevant symbols, work tags, and
types, and work my way backwards to all usages.
This might break tooling that depends on inspecting React's internal
fields. I've added DevTools support in the second commit. This didn't
need explicit versioning—the structure tells us enough.
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.
5d1ce65139 (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>
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.
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)
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.
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.
There's no need to separate strict mode from strict effects mode any
more.
I didn't clean up the `StrictEffectMode` fiber flag, because it's used
to prevent strict effects in legacy mode. I could replace those checks
with `LegacyMode` checks, but when we remove legacy mode, we can remove
that flag and condense them into one StrictMode flag away.
This wires up the use of `async_hooks` in the Node build (as well as the
Edge build when a global is available) in DEV mode only. This will be
used to track debug info about what suspended during an RSC pass.
Enabled behind a flag for now.
It seems worthwhile to me to run a test to experiment with different
expiration times. This moves the expiration times for scheduler and
reconciler into FeatureFlags for the facebook build. Non-facebook should
not be affected by these changes.
An attempt to see if we can bring back expiration of retry lanes to
avoid cases resolving Suspense can be starved by frequent updates.
In the past, this caused increase browser crashes, but a lot of time has
passed since then. Just trying if we can re-enable this.
Old PR that reverted adding the timeout:
https://github.com/facebook/react/pull/21300
<!--
Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.
Before submitting a pull request, please make sure the following is
done:
1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn test --debug --watch TestName`,
open `chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
10. If you haven't already, complete the CLA.
Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->
## Summary
<!--
Explain the **motivation** for making this change. What existing problem
does the pull request solve?
-->
The flag has been tested internally on WWW, should be good to set to
true for OSS. Added a dynamic flag for fb RN.
## How did you test this change?
<!--
Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes the user
interface.
How exactly did you verify that your PR solves the issue you wanted to
solve?
If you leave this empty, your PR will very likely be closed.
-->
yarn test
Adds a second argument to useDeferredValue called initialValue:
```js
const value = useDeferredValue(finalValue, initialValue);
```
During the initial render of a component, useDeferredValue will return
initialValue. Once that render finishes, it will spawn an additional
render to switch to finalValue.
This same sequence should occur whenever the hook is hidden and revealed
again, i.e. by a Suspense or Activity, though this part is not yet
implemented.
When initialValue is not provided, useDeferredValue has no effect during
initial render, but during an update, it will remain on the previous
value, then spawn an additional render to switch to the new value. (This
is the same behavior that exists today.)
During SSR, initialValue is always used, if provided.
This feature is currently behind an experimental flag. We plan to ship
it in a non-breaking release.
## Summary
Currently when cloning nodes in Fabric, we reset a node's children on
each clone, and then repeatedly call appendChild to restore the previous
list of children (even if it was quasi-identical to before). This causes
unnecessary invalidation of the layout state in Fabric's ShadowNode data
(which in turn may require additional yoga clones) and extra JSI calls.
This PR adds a feature flag to pass in the children as part of the clone
call, so Fabric always has a complete view of the node that's being
mutated.
This feature flag requires matching changes in the react-native repo:
https://github.com/facebook/react-native/pull/39817
## How did you test this change?
Unit test added demonstrates the new behaviour
```
yarn test -r www-modern ReactFabric-test
yarn test ReactFabric-test.internal
```
Tested a manual sync into React Native and verified core surfaces render
correctly.
Upgrades the stability of Server Actions from experimental to canary.
- Turns on enableAsyncActions and enableFormActions
- Removes "experimental_" prefix from useOptimistic, useFormStatus, and
useFormState
This lets a registered object or value be "tainted", which we block from
crossing the serialization boundary. It's only allowed to stay
in-memory.
This is an extra layer of protection against mistakes of transferring
data from a data access layer to a client. It doesn't provide perfect
protection, because it doesn't trace through derived values and
substrings. So it shouldn't be used as the only security layer but more
layers are better.
`taintObjectReference` is for specific object instances, not any nested
objects or values inside that object. It's useful to avoid specific
objects from getting passed as is. It ensures that you don't
accidentally leak values in a specific context. It can be for security
reasons like tokens, privacy reasons like personal data or performance
reasons like avoiding passing large objects over the wire.
It might be privacy violation to leak the age of a specific user, but
the number itself isn't blocked in any other context. As soon as the
value is extracted and passed specifically without the object, it can
therefore leak.
`taintUniqueValue` is useful for high entropy values such as hashes,
tokens or crypto keys that are very unique values. In that case it can
be useful to taint the actual primitive values themselves. These can be
encoded as a string, bigint or typed array. We don't currently check for
this value in a substring or inside other typed arrays.
Since values can be created from different sources they don't just
follow garbage collection. In this case an additional object must be
provided that defines the life time of this value for how long it should
be blocked. It can be `globalThis` for essentially forever, but that
risks leaking memory for ever when you're dealing with dynamic values
like reading a token from a database. So in that case the idea is that
you pass the object that might end up in cache.
A request is the only thing that is expected to do any work. The
principle is that you can derive values from out of a tainted
entry during a request. Including stashing it in a per request cache.
What you can't do is store a derived value in a global module level
cache. At least not without also tainting the object.
## Summary
This is part of an effort to align the event loop in React Native with
its behavior on the Web. In this case, we're going to test enabling
microtasks in React Native (Fabric) and we need React to schedule work
using microtasks if available there. This just adds a feature flag to
configure that behavior at runtime.
## How did you test this change?
* Reviewed the generated code, which looks ok.
* Did a manual sync of this PR to Meta's internal infra and tested it
with my changes to enable microtasks in RN/Hermes.
This adds an experimental `unstable_postpone(reason)` API.
Currently we don't have a way to model effectively an Infinite Promise.
I.e. something that suspends but never resolves. The reason this is
useful is because you might have something else that unblocks it later.
E.g. by updating in place later, or by client rendering.
On the client this works to model as an Infinite Promise (in fact,
that's what this implementation does). However, in Fizz and Flight that
doesn't work because the stream needs to end at some point. We don't
have any way of knowing that we're suspended on infinite promises. It's
not enough to tag the promises because you could await those and thus
creating new promises. The only way we really have to signal this
through a series of indirections like async functions, is by throwing.
It's not 100% safe because these values can be caught but it's the best
we can do.
Effectively `postpone(reason)` behaves like a built-in [Catch
Boundary](https://github.com/facebook/react/pull/26854). It's like
`raise(Postpone, reason)` except it's built-in so it needs to be able to
be encoded and caught by Suspense boundaries.
In Flight and Fizz these behave pretty much the same as errors. Flight
just forwards it to retrigger on the client. In Fizz they just trigger
client rendering which itself might just postpone again or fill in the
value. The difference is how they get logged.
In Flight and Fizz they log to `onPostpone(reason)` instead of
`onError(error)`. This log is meant to help find deopts on the server
like finding places where you fall back to client rendering. The reason
that you pass in is for that purpose to help the reason for any deopts.
I do track the stack trace in DEV but I don't currently expose it to
`onPostpone`. This seems like a limitation. It might be better to expose
the Postpone object which is an Error object but that's more of an
implementation detail. I could also pass it as a second argument.
On the client after hydration they don't get passed to
`onRecoverableError`. There's no global `onPostpone` API to capture
postponed things on the client just like there's no `onError`. At that
point it's just assumed to be intentional. It doesn't have any `digest`
or reason passed to the client since it's not logged.
There are some hacky solutions that currently just tries to reuse as
much of the existing code as possible but should be more properly
implemented.
- Fiber is currently just converting it to a fake Promise object so that
it behaves like an infinite Promise.
- Fizz is encoding the magic digest string `"POSTPONE"` in the HTML so
we know to ignore it but it should probably just be something neater
that doesn't share namespace with digests.
Next I plan on using this in the `/static` entry points for additional
features.
Why "postpone"? It's basically a synonym to "defer" but we plan on using
"defer" for other purposes and it's overloaded anyway.
This uses the same mechanism as [large
strings](https://github.com/facebook/react/pull/26932) to encode chunks
of length based binary data in the RSC payload behind a flag.
I introduce a new BinaryChunk type that's specific to each stream and
ways to convert into it. That's because we sometimes need all chunks to
be Uint8Array for the output, even if the source is another array buffer
view, and sometimes we need to clone it before transferring.
Each type of typed array is its own row tag. This lets us ensure that
the instance is directly in the right format in the cached entry instead
of creating a wrapper at each reference. Ideally this is also how
Map/Set should work but those are lazy which complicates that approach a
bit.
We assume both server and client use little-endian for now. If we want
to support other modes, we'd convert it to/from little-endian so that
the transfer protocol is always little-endian. That way the common
clients can be the fastest possible.
So far this only implements Server to Client. Still need to implement
Client to Server for parity.
NOTE: This is the first time we make RSC effectively a binary format.
This is not compatible with existing SSR techniques which serialize the
stream as unicode in the HTML. To be compatible, those implementations
would have to use base64 or something like that. Which is what we'll do
when we move this technique to be built-in to Fizz.
## Summary
This PR cleans up `useMutableSource`. This has been blocked by a
remaining dependency internally at Meta, but that has now been deleted.
<!--
Explain the **motivation** for making this change. What existing problem
does the pull request solve?
-->
## How did you test this change?
```
yarn flow
yarn lint
yarn test --prod
```
<!--
Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes the user
interface.
How exactly did you verify that your PR solves the issue you wanted to
solve?
If you leave this empty, your PR will very likely be closed.
-->
<!--
Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.
Before submitting a pull request, please make sure the following is
done:
1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn test --debug --watch TestName`,
open `chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
10. If you haven't already, complete the CLA.
Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->
## Summary
<!--
Explain the **motivation** for making this change. What existing problem
does the pull request solve?
-->
We are upgrading React 17 codebase to React18, and `StrictMode` has been
great for surfacing potential production bugs on React18 for class
components. There are non-trivial number of test failures caused by
double `useEffect` in StrictMode. To prioritize surfacing and fixing
issues that will break in production now, we need a flag to turn off
double `useEffect` for now in StrictMode temporarily. This is a
Meta-only hack for rolling out `createRoot` and we will fast follow to
remove it and use full strict mode.
## How did you test this change?
<!--
Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes the user
interface.
How exactly did you verify that your PR solves the issue you wanted to
solve?
If you leave this empty, your PR will very likely be closed.
-->
jest
## Overview
Does a few things:
- Renames `enableSyncDefaultUpdates` to
`forceConcurrentByDefaultForTesting`
- Changes the way it's used so it's dead-code eliminated separate from
`allowConcurrentByDefault`
- Deletes a bunch of the gated code
The gates that are deleted are unnecessary now. We were keeping them
when we originally thought we would come back to being concurrent by
default. But we've shifted and now sync-by default is the desired
behavior long term, so there's no need to keep all these forked tests
around.
I'll follow up to delete more of the forked behavior if possible.
Ideally we wouldn't need this flag even if we're still using
`allowConcurrentByDefault`.
This puts the change introduced by #26611 behind a flag until Meta is
able to roll it out. Disabling the flag reverts back to the old
behavior, where retries are throttled if there's still data remaining in
the tree, but not if all the data has finished loading.
The new behavior is still enabled in the public builds.
This lets you pass a function to `<form action={...}>` or `<button
formAction={...}>` or `<input type="submit formAction={...}>`. This will
behave basically like a `javascript:` URL except not quite implemented
that way. This is a convenience for the `onSubmit={e => {
e.preventDefault(); const fromData = new FormData(e.target); ... }`
pattern.
You can still implement a custom `onSubmit` handler and if it calls
`preventDefault`, it won't invoke the action, just like it would if you
used a full page form navigation or javascript urls. It behaves just
like a navigation and we might implement it with the Navigation API in
the future.
Currently this is just a synchronous function but in a follow up this
will accept async functions, handle pending states and handle errors.
This is implemented by setting `javascript:` URLs, but these only exist
to trigger an error message if something goes wrong instead of
navigating away. Like if you called `stopPropagation` to prevent React
from handling it or if you called `form.submit()` instead of
`form.requestSubmit()` which by-passes the `submit` event. If CSP is
used to ban `javascript:` urls, those will trigger errors when these
URLs are invoked which would be a different error message but it's still
there to notify the user that something went wrong in the plumbing.
Next up is improving the SSR state with action replaying and progressive
enhancement.
Implements initial (client-only) support for async actions behind a
flag. This is an experimental feature and the design isn't completely
finalized but we're getting closer. It will be layered alongside other
features we're working on, so it may not feel complete when considered
in isolation.
The basic description is you can pass an async function to
`startTransition` and all the transition updates that are scheduled
inside that async function will be grouped together. The `isPending`
flag will be set to true immediately, and only set back to false once
the async action has completed (as well as all the updates that it
triggers).
The ideal behavior would be that all updates spawned by the async action
are automatically inferred and grouped together; however, doing this
properly requires the upcoming (stage 2) Async Context API, which is not
yet implemented by browsers. In the meantime, we will fake this by
grouping together all transition updates that occur until the async
function has terminated. This can lead to overgrouping between unrelated
actions, which is not wrong per se, just not ideal.
If the `useTransition` hook is removed from the UI before an async
action has completed — for example, if the user navigates to a new page
— subsequent transitions will no longer be grouped with together with
that action.
Another consequence of the lack of Async Context is that if you call
`setState` inside an action but after an `await`, it must be wrapped in
`startTransition` in order to be grouped properly. If we didn't require
this, then there would be no way to distinguish action updates from
urgent updates caused by user input, too. This is an unfortunate footgun
but we can likely detect the most common mistakes using a lint rule.
Once Async Context lands in browsers, we can start warning in dev if we
detect an update that hasn't been wrapped in `startTransition`. Then,
longer term, once the feature is ubiquitous, we can rely on it for real
and allow you to call `setState` without the additional wrapper.
Things that are _not_ yet implemented in this PR, but will be added as
follow ups:
- Support for non-hook form of `startTransition`
- Canceling the async action scope if the `useTransition` hook is
deleted from the UI
- Anything related to server actions
This removes the concept of `prepareUpdate()`, behind a flag.
React Native already does everything in the commit phase, but generates
a temporary update payload before applying it.
React Fabric does it both in the render phase. Now it just moves it to a
single host config.
For DOM I forked updateProperties into one that does diffing and
updating in one pass vs just applying a pre-diffed updatePayload.
There are a few downsides of this approach:
- If only "children" has changed, we end up scheduling an update to be
done in the commit phase. Since we traverse through it anyway, it's
probably not much extra.
- It does more work in the commit phase so for a large tree that is
mostly unchanged, it'll stall longer.
- It does some extra work for special cases since that work happens if
anything has changed. We no longer have a deep bailout.
- The special cases now have to each replicate the "clean up old props"
loop, leading to extra code.
The benefit is that this doesn't allocate temporary extra objects
(possibly multiple per element if the array has to resize). It's less
work overall. It also gives us an option to reuse this function for a
sync render optimization.
Another benefit is that if we do the loop in the commit phase I can do
further optimizations by reading all props that I need for special cases
in that loop instead of polymorphic reads from props. This is what I'd
like to do in future refactors that would be stacked on top of this
change.
This reverts commit b2ae9ddb3b.
While the feature flag is fully rolled out, these tests are also testing
behavior set with an unstable flag on root, which for now we want to
preserve.
Not sure if there's a better way then adding a dynamic feature flag to
the www build?
When React receives new input (via `setState`, a Suspense promise
resolution, and so on), it needs to ensure there's a rendering task
associated with the update. Most of this happens
`ensureRootIsScheduled`.
If a single event contains multiple updates, we end up running the
scheduling code once per update. But this is wasteful because we really
only need to run it once, at the end of the event (or in the case of
flushSync, at the end of the scope function's execution).
So this PR moves the scheduling logic to happen in a microtask instead.
In some cases, we will force it run earlier than that, like for
`flushSync`, but since updates are batched by default, it will almost
always happen in the microtask. Even for discrete updates.
In production, this should have no observable behavior difference. In a
testing environment that uses `act`, this should also not have a
behavior difference because React will push these tasks to an internal
`act` queue.
However, tests that do not use `act` and do not simulate an actual
production environment (like an e2e test) may be affected. For example,
before this change, if a test were to call `setState` outside of `act`
and then immediately call `jest.runAllTimers()`, the update would be
synchronously applied. After this change, that will no longer work
because the rendering task (a timer, in this case) isn't scheduled until
after the microtask queue has run.
I don't expect this to be an issue in practice because most people do
not write their tests this way. They either use `act`, or they write
e2e-style tests.
The biggest exception has been... our own internal test suite. Until
recently, many of our tests were written in a way that accidentally
relied on the updates being scheduled synchronously. Over the past few
weeks, @tyao1 and I have gradually converted the test suite to use a new
set of testing helpers that are resilient to this implementation detail.
(There are also some old Relay tests that were written in the style of
React's internal test suite. Those will need to be fixed, too.)
The larger motivation behind this change, aside from a minor performance
improvement, is we intend to use this new microtask to perform
additional logic that doesn't yet exist. Like inferring the priority of
a custom event.
This flag is already enabled everywhere except for www, which is blocked
by a few tests that assert on the old behavior. Once www is ready, I'll
land this.
This is a change to some undefined behavior that we though we would do
at one point but decided not to roll out. It's already disabled
everywhere, so this just deletes the branch from the implementation and
the tests.
Today if something suspends, React will continue rendering the siblings
of that component.
Our original rationale for prerendering the siblings of a suspended
component was to initiate any lazy fetches that they might contain. This
was when we were more bullish about lazy fetching being a good idea some
of the time (when combined with prefetching), as opposed to our latest
thinking, which is that it's almost always a bad idea.
Another rationale for the original behavior was that the render was I/O
bound, anyway, so we might as do some extra work in the meantime. But
this was before we had the concept of instant loading states: when
navigating to a new screen, it's better to show a loading state as soon
as you can (often a skeleton UI), rather than delay the transition.
(There are still cases where we block the render, when a suitable
loading state is not available; it's just not _all_ cases where
something suspends.) So the biggest issue with our existing
implementation is that the prerendering of the siblings happens within
the same render pass as the one that suspended — _before_ the loading
state appears.
What we should do instead is immediately unwind the stack as soon as
something suspends, to unblock the loading state.
If we want to preserve the ability to prerender the siblings, what we
could do is schedule special render pass immediately after the fallback
is displayed. This is likely what we'll do in the future. However, in
the new implementation of `use`, there's another reason we don't
prerender siblings: so we can preserve the state of the stack when
something suspends, and resume where we left of when the promise
resolves without replaying the parents. The only way to do this
currently is to suspend the entire work loop. Fiber does not currently
support rendering multiple siblings in "parallel". Once you move onto
the next sibling, the stack of the previous sibling is discarded and
cannot be restored. We do plan to implement this feature, but it will
require a not-insignificant refactor.
Given that lazy data fetching is already bad for performance, the best
trade off for now seems to be to disable prerendering of siblings. This
gives us the best performance characteristics when you're following best
practices (i.e. hoist data fetches to Server Components or route
loaders), at the expense of making an already bad pattern a bit worse.
Later, when we implement resumable context stacks, we can reenable
sibling prerendering. Though even then the use case will mostly be to
prerender the CPU-bound work, not lazy fetches.
We disallow empty strings for `href` and `src` since they're common
mistakes that end up loading the current page as a preload, image or
link. We also disallow it for `action`. You have to pass `null` which is
the same.
However, for `formAction` passing `null` is not the same as passing
empty string. Passing empty string overrides the form's action to be the
current page even if the form's action was set to something else.
There's no easy way to express the same thing `#` show up in the user
visible URLs and `?` clears the search params.
Since this is also not a common mistake, we can just allow this.
There is a problem with <style> as resource. For css-in-js libs there
may be an very large number of these hoistables being created. The
number of style tags can grow quickly and to help reduce the prevalence
of this FIzz now aggregates all style tags for a given precedence into a
single tag. The client can 'hydrate' against these compound tags but
currently on the client insertions are done individually.
additionally drops the implementation where style tags are embedding in
a template for one where `media="not all"` is set. The idea is to have
the browser construct the underlying stylesheet eagerly which does not
happen if the tag is embedded in a template
Key Decision:
One choice made in this PR is that we flush style tags eagerly even if a
boundary is blocked that is the only thing that depends on that style
rule. The reason we are starting with this implementation is that it
allows a very condensed representation of the style resources. If we
tracked which rules were used in which boundaries we would need a style
resource for every rendered <style> tag. This could be problematic for
css-in-js libs that might render hundreds or thousands of style tags.
The tradeoff here is we slightly delay content reveal in some cases (we
send extra bytes) but we have fewer DOM tags and faster SSR runtime
The old version of prettier we were using didn't support the Flow syntax
to access properties in a type using `SomeType['prop']`. This updates
`prettier` and `rollup-plugin-prettier` to the latest versions.
I added the prettier config `arrowParens: "avoid"` to reduce the diff
size as the default has changed in Prettier 2.0. The largest amount of
changes comes from function expressions now having a space. This doesn't
have an option to preserve the old behavior, so we have to update this.
I noticed this was an experiment concluded 16 months ago (#21679) that
this extra work is beneficial
to break up cycles leaking memory in product code.
<!--
Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.
Before submitting a pull request, please make sure the following is
done:
1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn debug-test --watch TestName`, open
`chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
10. If you haven't already, complete the CLA.
Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->
## Summary
<!--
Explain the **motivation** for making this change. What existing problem
does the pull request solve?
-->
This is the other approach for unifying default and sync lane
https://github.com/facebook/react/pull/25524.
The approach in that PR is to merge default and continuous lane into the
sync lane, and use a new field to track the priority. But there are a
couple places that field will be needed, and it is difficult to
correctly reset the field when there is no sync lane.
In this PR we take the other approach that doesn't remove any lane, but
batch them to get the behavior we want.
## How did you test this change?
<!--
Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes the user
interface.
How exactly did you verify that your PR solves the issue you wanted to
solve?
If you leave this empty, your PR will very likely be closed.
-->
yarn test
Co-authored-by: Andrew Clark <hi@andrewclark.io>
We originally had grand plans for using this Event concept for more but
now it's only meant to be used in combination with effects.
It's an Event in the FRP terms, that is triggered from an Effect.
Technically it can also be from another function that itself is
triggered from an existing side-effect but that's kind of an advanced
case.
The canonical case is an effect that triggers an event:
```js
const onHappened = useEffectEvent(() => ...);
useEffect(() => {
onHappened();
}, []);
```
We've heard from multiple contributors that the Reconciler forking
mechanism was confusing and/or annoying to deal with. Since it's
currently unused and there's no immediate plans to start using it again,
this removes the forking.
Fully removing the fork is split into 2 steps to preserve file history:
**This PR**
- remove `enableNewReconciler` feature flag.
- remove `unstable_isNewReconciler` export
- remove eslint rules for cross fork imports
- remove `*.new.js` files and update imports
- merge non-suffixed files into `*.old` files where both exist
(sometimes types were defined there)
**#25775**
- rename `*.old` files
This improves the error message a bit and ensures that we recommend
putting the key first, not last, which ensures that the faster
`jsx-runtime` is used.
This only affects the modern "automatic" JSX transform.
* Add fetch instrumentation in cached contexts
* Avoid unhandled rejection errors for Promises that we intentionally ignore
In the final passes, we ignore the newly generated Promises and use
the previous ones. This ensures that if those generate errors, that we
intentionally ignore those.
* Add extra fetch properties if there were any
* Facebook -> Meta in copyright
rg --files | xargs sed -i 's#Copyright (c) Facebook, Inc. and its affiliates.#Copyright (c) Meta Platforms, Inc. and affiliates.#g'
* Manual tweaks
* Add feature flag for external Fizz runtime
Only enabled for www for now
* Add option to load Fizz runtime from external file
When unstable_externalRuntimeSrc is provided, React will inject a script
tag that points to the provided URL.
Then, instead of emitting inline scripts, the Fizz stream will emit
HTML nodes with data attributes that encode the instructions. The
external runtime will detect these with a mutation observer and
translate them into runtime commands. This part isn't implemented in
this PR, though — all this does is set up the option to use
an external runtime, and inject the script tag.
The external runtime is injected at the same time as bootstrap scripts.
This commit adds a new hook `useEvent` per the RFC [here](https://github.com/reactjs/rfcs/pull/220), gated as experimental.
Co-authored-by: Rick Hanlon <rickhanlonii@gmail.com>
Co-authored-by: Rick Hanlon <rickhanlonii@fb.com>
Co-authored-by: Lauren Tan <poteto@users.noreply.github.com>
* Internal `act`: Unwrapping resolved promises
This update our internal implementation of `act` to support React's new
behavior for unwrapping promises. Like we did with Scheduler, when
something suspends, it will yield to the main thread so the microtasks
can run, then continue in a new task.
I need to implement the same behavior in the public version of `act`,
but there are some additional considerations so I'll do that in a
separate commit.
* Move throwException to after work loop resumes
throwException is the function that finds the nearest boundary and
schedules it for a second render pass. We should only call it right
before we unwind the stack — not if we receive an immediate ping and
render the fiber again.
This was an oversight in 8ef3a7c that I didn't notice because it happens
to mostly work, anyway. What made me notice the mistake is that
throwException also marks the entire render phase as suspended
(RootDidSuspend or RootDidSuspendWithDelay), which is only supposed to
be happen if we show a fallback. One consequence was that, in the
RootDidSuspendWithDelay case, the entire commit phase was blocked,
because that's the exit status we use to block a bad fallback
from appearing.
* Use expando to check whether promise has resolved
Add a `status` expando to a thrown thenable to track when its value has
resolved.
In a later step, we'll also use `value` and `reason` expandos to track
the resolved value.
This is not part of the official JavaScript spec — think of
it as an extension of the Promise API, or a custom interface that is a
superset of Thenable. However, it's inspired by the terminology used
by `Promise.allSettled`.
The intent is that this will be a public API — Suspense implementations
can set these expandos to allow React to unwrap the value synchronously
without waiting a microtask.
* Scaffolding for `experimental_use` hook
Sets up a new experimental hook behind a feature flag, but does not
implement it yet.
* use(promise)
Adds experimental support to Fiber for unwrapping the value of a promise
inside a component. It is not yet implemented for Server Components,
but that is planned.
If promise has already resolved, the value can be unwrapped
"immediately" without showing a fallback. The trick we use to implement
this is to yield to the main thread (literally suspending the work
loop), wait for the microtask queue to drain, then check if the promise
resolved in the meantime. If so, we can resume the last attempted fiber
without unwinding the stack. This functionality was implemented in
previous commits.
Another feature is that the promises do not need to be cached between
attempts. Because we assume idempotent execution of components, React
will track the promises that were used during the previous attempt and
reuse the result. You shouldn't rely on this property, but during
initial render it mostly just works. Updates are trickier, though,
because if you used an uncached promise, we have no way of knowing
whether the underlying data has changed, so we have to unwrap the
promise every time. It will still work, but it's inefficient and can
lead to unnecessary fallbacks if it happens during a discrete update.
When we implement this for Server Components, this will be less of an
issue because there are no updates in that environment. However, it's
still better for performance to cache data requests, so the same
principles largely apply.
The intention is that this will eventually be the only supported way to
suspend on arbitrary promises. Throwing a promise directly will
be deprecated.
Implement basic support for "Resources". In the context of this commit, the only thing that is currently a Resource are
<link rel="stylesheet" precedence="some-value" ...>
Resources can be rendered anywhere in the react tree, even outside of normal parenting rules, for instance you can render a resource before you have rendered the <html><head> tags for your application. In the stream we reorder this so the browser always receives valid HTML and resources are emitted either in place (normal circumstances) or at the top of the <head> (when you render them above or before the <head> in your react tree)
On the client, resources opt into an entirely different hydration path. Instead of matching the location within the Document these resources are queried for in the entire document. It is an error to have more than one resource with the same href attribute.
The use of precedence here as an opt-in signal for resourcifying the link is in preparation for a more complete Resource implementation which will dedupe resource references (multiple will be valid), hoist to the appropriate container (body, head, or elsewhere), order (according to precedence) and Suspend boundaries that depend on them. More details will come in the coming weeks on this plan.
This feature is gated by an experimental flag and will only be made available in experimental builds until some future time.
This reverts commit 327e4a1f96.
Turns out we hadn't rolled this out internally yet — I mistook
enableClientRenderFallbackOnHydrationMismatch for
said enableClientRenderFallbackOnTextMismatch. Need to revert
until we finish rolling out the change.
* Flight side of server context
* 1 more test
* rm unused function
* flow+prettier
* flow again =)
* duplicate ReactServerContext across packages
* store default value when lazily initializing server context
* .
* better comment
* derp... missing import
* rm optional chaining
* missed feature flag
* React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ??
* add warning if non ServerContext passed into useServerContext
* pass context in as array of arrays
* make importServerContext nott pollute the global context state
* merge main
* remove useServerContext
* dont rely on object getters in ReactServerContext and disallow JSX
* add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry
* gate test case as experimental
* feedback
* remove unions
* Lint
* fix oopsies (tests/lint/mismatching arguments/signatures
* lint again
* replace-fork
* remove extraneous change
* rebase
* 1 more test
* rm unused function
* flow+prettier
* flow again =)
* duplicate ReactServerContext across packages
* store default value when lazily initializing server context
* .
* better comment
* derp... missing import
* rm optional chaining
* missed feature flag
* React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ??
* add warning if non ServerContext passed into useServerContext
* pass context in as array of arrays
* make importServerContext nott pollute the global context state
* merge main
* remove useServerContext
* dont rely on object getters in ReactServerContext and disallow JSX
* add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry
* gate test case as experimental
* feedback
* remove unions
* Lint
* fix oopsies (tests/lint/mismatching arguments/signatures
* lint again
* replace-fork
* remove extraneous change
* rebase
* reinline
* rebase
* add back changes lost due to rebase being hard
* emit chunk for provider
* remove case for React provider type
* update type for SomeChunk
* enable flag with experimental
* add missing types
* fix flow type
* missing type
* t: any
* revert extraneous type change
* better type
* better type
* feedback
* change import to type import
* test?
* test?
* remove react-dom
* remove react-native-renderer from react-server-native-relay/package.json
* gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer
* getComponentNameFromTpe: server context type gated and use displayName if available
* fallthrough
* lint....
* POP
* lint
There are a few internal tests that still need to be updated, so I'm
adding this flag back for www only.
The desired behavior rolled out to 10% public, so we're confident there
are no issues.
The open source behavior remains (skipUnmountedBoundaries = true).
@sebmarkbage and I audited the feature flags file to review the status
of each feature or experiment. Based on that, I've added some more
comments to the main ReactFeatureFlags module and rearranged them
into groups.
I haven't changed the value of any flags, yet. There are a few we're
going to land but I'll do them as separate PRs.
This is an old feature that we no longer support. `hydrateRoot` already
throws if you pass a comment node; this change makes `createRoot`
throw, too.
Still enabled in the Facebook build until we migrate the callers.
* custom element props
* custom element events
* use function type for on*
* tests, htmlFor
* className
* fix ReactDOMComponent-test
* started on adding feature flag
* added feature flag to all feature flag files
* everything passes
* tried to fix getPropertyInfo
* used @gate and __experimental__
* remove flag gating for test which already passes
* fix onClick test
* add __EXPERIMENTAL__ to www flags, rename eventProxy
* Add innerText and textContent to reservedProps
* Emit warning when assigning to read only properties in client
* Revert "Emit warning when assigning to read only properties in client"
This reverts commit 1a093e584ce50e2e634aa743e04f9cb8fc2b3f7d.
* Emit warning when assigning to read only properties during hydration
* yarn prettier-all
* Gate hydration warning test on flag
* Fix gating in hydration warning test
* Fix assignment to boolean properties
* Replace _listeners with random suffix matching
* Improve gating for hydration warning test
* Add outerText and outerHTML to server warning properties
* remove nameLower logic
* fix capture event listener test
* Add coverage for changing custom event listeners
* yarn prettier-all
* yarn lint --fix
* replace getCustomElementEventHandlersFromNode with getFiberCurrentPropsFromNode
* Remove previous value when adding event listener
* flow, lint, prettier
* Add dispatchEvent to make sure nothing crashes
* Add state change to reserved attribute tests
* Add missing feature flag test gate
* Reimplement SSR changes in ReactDOMServerFormatConfig
* Test hydration for objects and functions
* add missing test gate
* remove extraneous comment
* Add attribute->property test