Commit Graph

984 Commits

Author SHA1 Message Date
Jan Kassens
65903583d2 Remove flag enableUseDeferredValueInitialArg (#30595)
This is enabled everywhere for a while and I don't think we'd be backing
this out of 19. Seems like it's good to clean up to me.
2024-08-05 11:25:05 -04:00
Jan Kassens
5fb67fa25c Cloned flag to avoid extra clones in persistent renderer (#27647)
Persistent renderers used the `Update` effect flag to check if a subtree
needs to be cloned. In some cases, that causes extra renders, such as
when a layout effect is triggered which only has an effect on the JS
side, but doesn't update the host components.

It's been a bit tricky to find the right places where this needs to be
set and I'm not 100% sure I got all the cases even though the tests
passed.
2024-08-01 15:11:19 -04:00
Sebastian Markbåge
12e9579099 [Flight] Enable owner stacks on the client when replaying logs (#30473)
There's a special case that happens when we replay logs on the client
because this doesn't happen within the context of any particular
rendered component. So we need to reimplement things that would normally
be handled by a full client like Fiber.

The implementation of `getOwnerStackByComponentInfoInDev` is the
simplest version since it doesn't have any client components in it so I
move it to `shared/`. It's only used by Flight but both `react-server/`
and `react-client/` packages. The ReactComponentInfo type is also more
generic than just Flight anyway.

In a follow up I still need to implement this in React DevTools when
native tasks are not available so that it appends it to the console.
2024-07-31 07:56:15 -04:00
Jack Pope
3f8b1333da Set enableLazyContextPropagation to dynamic on RN (#30516) 2024-07-30 18:31:31 -04:00
Jan Kassens
6b82f3c904 [RN] experiment to move Fabric completeWork to the commit phase (#30513)
There is currently a mismatch in how the persistent mode JS API and the
Fabric native code interpret `completeRoot`.

This is a short-lived experiment to see the effect of moving the Fabric
`completeRoot` call from `finalizeContainerChildren` to
`replaceContainerChildren` which in some cases does not get called.
2024-07-29 18:38:55 -04:00
Jack Pope
397646ad51 Update enableLazyContextPropagation flag (#30514)
- Flag set to true for FB
- Flag set to experimental for OSS
2024-07-29 16:50:28 -04:00
Jack Pope
1350a85980 Add unstable context bailout for profiling (#30407)
**This API is not intended to ship. This is a temporary unstable hook
for internal performance profiling.**

This PR exposes `unstable_useContextWithBailout`, which takes a compare
function in addition to Context. The comparison function is run to
determine if Context propagation and render should bail out earlier.
`unstable_useContextWithBailout` returns the full Context value, same as
`useContext`.

We can profile this API against `useContext` to better measure the cost
of Context value updates and gather more data around propagation and
render performance.

The bailout logic and test cases are based on
https://github.com/facebook/react/pull/20646

Additionally, this implementation allows multiple values to be compared
in one hook by returning a tuple to avoid requiring additional Context
consumer hooks.
2024-07-26 14:38:24 -04:00
Jack Pope
14a4699ff1 Remove allowConcurrentByDefault flag (#30445)
Following https://github.com/facebook/react/pull/30436

Concurrent by default strategy has been unshipped. Here we clean up the
`allowConcurrentByDefault` path and related logic/tests.

For now, this keeps the `concurrentUpdatesByDefaultOverride` argument in
`createContainer` and `createHydrationContainer` and ignores the value
to prevent more breaking changes to `react-reconciler` in the RC stage.
2024-07-25 11:59:50 -04:00
Sebastian Markbåge
5b37af7daa Stop filtering owner stacks (#30438)
We still filter them before passing from server to client in Flight
Server but when presenting a native stack, we don't need to filter them.
That's left to ignore listing in the presentation.

The stacks are pretty clean regardless thanks to the bottom stack
frames.

We can also unify the owner stack formatters into one shared module
since Fizz/Flight/Fiber all do the same thing. DevTools currently does
the same thing but is forked so it can support multiple versions.
2024-07-24 13:01:07 -04:00
Jack Pope
e902c45caf Remove forceConcurrentByDefaultForTesting flag (#30436)
Concurrent by default has been unshipped! Let's clean it up.

Here we remove `forceConcurrentByDefaultForTesting`, which allows us to
run tests against both concurrent strategies. In the next PR, we'll
remove the actual concurrent by default code path.
2024-07-24 10:17:33 -04:00
Jan Kassens
b7e7f1a3fa [BE] upgrade prettier to 3.3.3 (#30420)
Mostly just changes in ternary formatting.
2024-07-22 16:09:01 -04:00
Jan Kassens
d025ddd3b9 Set enableFastJSX flag to true (#30343)
When these to diffs are landed, we can merge this

- [x] D59772879
- [x] D59773043
2024-07-22 11:50:35 -04:00
Sebastian Markbåge
06763852de [Flight] Parse Stack on the Server and Transfer Structured Stack (#30410)
Stacked on #30401.

Previously we were transferring the original V8 stack trace string to
the client and then parsing it there. However, really the server is the
one that knows what format it is and it should be able to vary by server
environment.

We also don't use the raw string anymore (at least not in
enableOwnerStacks). We always create the native Error stacks.

The string also made it unclear which environment it is and it was
tempting to just use it as is.

Instead I parse it on the server and make it a structured stack in the
transfer format. It also makes it clear that it needs to be formatted in
the current environment before presented.
2024-07-22 11:18:55 -04:00
Sebastian Markbåge
b15c1983dc [Flight] Normalize Stack Using Fake Evals (#30401)
Stacked on https://github.com/facebook/react/pull/30400 and
https://github.com/facebook/react/pull/30369

Previously we were using fake evals to recreate a stack for console
replaying and thrown errors. However, for owner stacks we just used the
raw string that came from the server.

This means that the format of the owner stack could include different
formats. Like Spidermonkey format for the client components and V8 for
the server components. This means that this stack can't be parsed
natively by the browser like when printing them as error like in
https://github.com/facebook/react/pull/30289. Additionally, since
there's no source file registered with that name and no source mapping
url, it can't be source mapped.

Before:

<img width="1329" alt="before-firefox"
src="https://github.com/user-attachments/assets/cbe03f9c-96ac-48fb-b58f-f3a224a774f4">

Instead, we need to create a fake stack like we do for the other things.
That way when it's printed as an Error it gets source mapped. It also
means that the format is consistently in the native format of the
current browser.

After:

<img width="753" alt="after-firefox"
src="https://github.com/user-attachments/assets/b436f1f5-ca37-4203-b29f-df9828c9fad3">

So this is nice because you can just take the result from
`captureOwnerStack()` and append it to an `Error` stack and print it
natively. E.g. this is what React DevTools will do.

If you want to parse and present it yourself though it's a bit awkward
though. The `captureOwnerStack()` API now includes a bunch of
`rsc://React/` URLs. These don't really have any direct connection to
the source map. Only the browser knows this connection from the eval.
You basically have to strip the prefix and then manually pass the
remainder to your own `findSourceMapURL`.

Another awkward part is that since Safari doesn't support eval sourceURL
exposed into `error.stack` - it means that `captureOwnerStack()` get an
empty location for server components since the fake eval doesn't work
there. That's not a big deal since these stacks are already broken even
for client modules for many because the `eval-source-map` strategy in
Webpack doesn't work in Safari for this same reason.

A lot of this refactoring is just clarifying that there's three kind of
ReactComponentInfo fields:

- `stack` - The raw stack as described on the original server.
- `debugStack` - The Error object containing the stack as represented in
the current client as fake evals.
- `debugTask` - The same thing as `debugStack` but described in terms of
a native `console.createTask`.
2024-07-22 11:03:15 -04:00
Jan Kassens
1d5a208fda [native-fb] set disableDefaultPropsExceptForClasses flag to true (#30339)
Reflecting D59402048
2024-07-15 14:20:40 -04:00
Jan Kassens
fc1371f6bf [native-fb] set consoleManagedByDevToolsDuringStrictMode flag to true (#30338)
Reflecting D59232098.
2024-07-15 12:31:17 -04:00
Sebastian Markbåge
ff89ba7346 Disable consoleWithStackDev Transform except in RN/WWW (#30313)
Stacked on #30308.

This is now a noop module so we can stop applying the transform of
console.error using the Babel plugin in the mainline builds. I'm keeping
the transform for RN/WWW for now although it might be nice if the
transform moved into those systems as it gets synced instead of keeping
it upstream.

In jest tests we're already not running the forks for RN/WWW so we don't
need it at all there.
2024-07-12 14:39:38 -04:00
Sebastian Markbåge
400e822277 Remove Component Stack from React Logged Warnings and Error Reporting (#30308)
React transpiles some of its own `console.error` calls into a helper
that appends component stacks to those calls. However, this doesn't
cover user space `console.error` calls - which includes React helpers
that React has moved into third parties like createClass and prop-types.

The idea is that any user space component can add a warning just like
React can which is why React DevTools adds them too if they don't
already exist. Having them appended in both places is tricky because now
you have to know whether to remove them from React's logs.

Similarly it's often common for server-side frameworks to forget to
cover the `console.error` logs from other sources since React DevTools
isn't active there. However, it's also annoying to get component stacks
clogging the terminal - depending on where the log came from.

In the future `console.createTask()` will cover this use case natively
and when available we don't append them at all.

The new strategy relies on either:

- React DevTools existing to add them to React logs as well as third
parties.
- `console.createTask` being supported and surfaced.
- A third party framework showing the component stack either in an Error
Dialog or appended to terminal output.

For a third party to be able to implement this they need to be able to
get the component stack. To get the component stack from within a
`console.error` call you need to use the `React.captureOwnerStack()`
helper which is only available in `enableOwnerStacks` flag. However,
it's possible to polyfill with parent stacks using internals as a stop
gap. There's a question of whether React 19 should just go out with
`enableOwnerStacks` to expose this but regardless I think it's best it
doesn't include component stacks from the runtime for consistency.

In practice it's not really a regression though because typically either
of the other options exists and error dialogs don't implement
`console.error` overrides anyway yet. SSR terminals might miss them but
they'd only have them in DEV warnings to begin with an a subset of React
warnings. Typically those are either going to happen on the client
anyway or replayed.

Our tests are written to assert that component stacks work in various
scenarios all over the place. To ensure that this keeps working I
implement a "polyfill" that is similar to that expected a server
framework might do - in `assertConsoleErrorDev` and `toErrorDev`.

This PR doesn't yet change www or RN since they have their own forks of
consoleWithStackDev for now.
2024-07-12 13:02:22 -04:00
Lauren Tan
ff3f1fac65 [RN] Set enableOwnerStacks and enableUseDeferredValueInitialArg to false
In www, the experimental versions get a .modern.js or .classic.js prefix
and get copied into the same folder. In RN, they don't seem to have
.modern.js and .classic.js versions so they end up getting the same
name.

sebmarkbage's theory is that what happens is that they then override
the file that was already there. So depending on if experimental or
stable build finishes first you get a different version at the end.

It doesn't make sense to use `__EXPERIMENTAL__` for flags in native-fb
since there's no modern/classic split there. So that flag should just be
hardcoded to true or false and then it doesn't matter which one finishes
first.

We don't support experimental builds in OSS RN neither so the same thing
could happen with
[`enableOwnerStacks`](5dcf3ca8d4/packages/shared/forks/ReactFeatureFlags.native-oss.js (L60)).

You can see that the build errors in the previous PR but passes after
these flag changes.

ghstack-source-id: d10f37bcea
Pull Request resolved: https://github.com/facebook/react/pull/30322
2024-07-12 12:11:50 -04:00
Sebastian Markbåge
433068eece Remove top stack frame from getCurrentStack (#30306)
The full stack is the current execution stack (`new Error().stack`) +
the current owner stack (`React.captureOwnerStack()`).

The idea with the top frame was that when we append it to console.error
we'd include both since otherwise the true reason would be obscured
behind the little `>` to expand. So we'd just put both stack front and
center. By adding this into getCurrentStack it was easy to use the same
filtering. I never implemented in Fizz or Flight though.

However, with the public API `React.captureOwnerStack()` it's not
necessary to include the current stack since you already have it and
you'd have filtering capabilities in user space too.

Since I'm removing the component stacks from React itself we no longer
need this. It's expected that maybe RDT or framework polyfill would
include this same technique though.
2024-07-11 18:34:41 -04:00
Jan Kassens
af28f480e8 Feature flag to disable legacy context for function components (#30319)
While the goal is to remove legacy context completely, I think we can
already land the removal of legacy context for function components. I
didn't even know this feature existed until reading the code recently.

The win is just a couple of property lookups on function renders, but it
trims down the API already as the full removal will likely still take a
bit more time.

www: Starting with enabled test renderer and a feature flag for
production rollout.

RN: Not enabled, will follow up on this.
2024-07-11 16:21:12 -04:00
Sebastian Markbåge
85acf2d195 Delete suppressWarning in OSS (#30312)
I'm pretty sure this is completely unnecessary even in www and RN
because it's only useful if you use the mock scheduler which typically
only we do in our own tests. But all our tests pass so unless www/RN
does something with it, I don't think this is used.

Also remove unnecessary `__DEV__` check. If it gets pulled in prod, we'd
want to know about it.
2024-07-11 11:20:42 -04:00
Jan Kassens
fe9828954a Experiment with using an object literal for Fiber creation (#28734)
Object literals should be faster at least on React Native with Hermes as
the JS engine.
It might also be interesting to confirm the old comments in this file
from years ago are even still valid. Creating an object from a literal
should be a simpler operation.

It's a bit unfortunate that this introduces a bunch of copied code, but
since we rearely update the fields on fibers, this seems like an okay
tradeoff for a hot code path. An alternative would be some sort of macro
system, but that doesn't seem worth the extra complexity.
2024-07-10 16:42:08 -04:00
Sebastian Markbåge
9647333b3d Add RN fork of consoleWithStackDev so we can improve the mainline one (#30305)
We're removing this wrapper from the mainline but RN is still using
component stacks to filter out warnings.

This is unfortunate since it'll be hard to keep track of the interplay
with these, DevTools and how you're supposed to implement error dialogs
in userspace.
2024-07-10 13:37:56 -04:00
Jan Kassens
21129d34a5 Upgrade flow to 0.235.0 (#30118)
See [Flow
changelog](https://github.com/facebook/flow/blob/main/Changelog.md) for
changes in this version.
2024-07-08 14:11:11 -04:00
Sebastian Markbåge
df783f9ea1 Add unknown location information to component stacks (#30290)
This is the same change as in #30289 but for the main runtime - e.g.
parent stacks in errorInfo.componentStack, appended stacks to
console.error coming from React itself and when we add virtual frames to
owner stacks.

Since we don't add location information these frames look weird to some
stack parsers - such as the native one. This is an existing issue when
you want to use some off-the-shelf parsers to parse production component
stacks for example.

While we won't add Error objects to logs ourselves necessarily, some
third party could want to do the same thing we do in DevTools and so we
should provide the same capability to just take this trace and print it
using an Error object.
2024-07-08 11:54:14 -04:00
Sebastian Markbåge
0b5835a46f [Flight] Implement captureStackTrace and owner stacks on the Server (#30197)
Wire up owner stacks in Flight to the shared internals. This exposes it
to `captureOwnerStack()`.

In this case we install it permanently as we only allow one RSC renderer
which then supports async contexts. Same thing we do for owner.

This also ends up adding it to errors logged by React through
`consoleWithStackDev`. The plan is to eventually remove that but this is
inline with what we do in Fizz and Fiber already.

However, at the same time we've instrumented the console so we need to
strip them back out before sending to the client. This lets the client
control whether to add the stack back in or allowing
`console.createTask` to control it.

This is another reason we shouldn't append them from React but for now
we hack it by removing them after the fact.
2024-07-04 12:15:51 -04:00
Timothy Yung
ef0f44ecff Enable enableDeferRootSchedulingToMicrotask and enableInfiniteRenderLoopDetection for React Native (Meta) (#30090) 2024-06-26 08:50:06 -07:00
Jack Pope
89580f209c Set renameElementSymbol to dynamic value (#30066)
Prepare to roll this out with dynamic flag

`yarn flags --diff www canary`

<img width="514" alt="Screenshot 2024-06-24 at 11 33 55 AM"
src="https://github.com/facebook/react/assets/8965173/31508fdc-4cb1-4ce0-8e22-c02a034377b0">
2024-06-24 12:28:39 -04:00
Jack Pope
c21bcd627b Clean up enableUnifiedSyncLane flag (#30062)
`enableUnifiedSyncLane` now passes everywhere. Let's clean it up

Implemented with https://github.com/facebook/react/pull/27646

Flag enabled with https://github.com/facebook/react/pull/27646,
https://github.com/facebook/react/pull/28269,
https://github.com/facebook/react/pull/29052
2024-06-24 11:18:22 -04:00
Jan Kassens
b565373afd lint: enable reportUnusedDisableDirectives and remove unused suppressions (#28721)
This enables linting against unused suppressions and removes the ones
that were unused.
2024-06-21 12:24:32 -04:00
Jan Kassens
6ab67c35f1 Revert "www: remove dynamic feature flag enableSchedulingProfiler" (#29995)
Reverts facebook/react#29994
2024-06-20 17:17:25 -04:00
Jan Kassens
babe5a2f1b www: remove dynamic feature flag enableSchedulingProfiler (#29994) 2024-06-20 16:47:28 -04:00
Timothy Yung
f14d7f0d25 Prepare Feature Flags for React Native 0.75 (#29903)
## Summary

Configures the React Native open source feature flags in preparation for
React Native 0.75, which will be upgraded to React 19.

## How did you test this change?

```
$ yarn test
$ yarn flow fabric
```
2024-06-14 17:09:50 -07:00
Jan Kassens
88959fd54a Revert "Set disableLegacyMode to true for www" (#29901)
Reverts facebook/react#29871

Just temporarily while we're investigating something.
2024-06-14 15:27:32 -04:00
Jan Kassens
fb9a90fa48 Set disableLegacyMode to true for www (#29871)
Set disableLegacyMode to true for www
2024-06-14 09:52:49 -04:00
Jan Kassens
93826c8483 remove unstable_renderSubtreeIntoContainer (#29771)
remove unstable_renderSubtreeIntoContainer

This is finally no longer used and can be deleted.
2024-06-12 11:14:51 -04:00
Sebastian Markbåge
383b2a1845 Use the Nearest Parent of an Errored Promise as its Owner (#29814)
Stacked on #29807.

Conceptually the error's owner/task should ideally be captured when the
Error constructor is called but neither `console.createTask` does this,
nor do we override `Error` to capture our `owner`. So instead, we use
the nearest parent as the owner/task of the error. This is usually the
same thing when it's thrown from the same async component but not if you
await a promise started from a different component/task.

Before this stack the "owner" and "task" of a Lazy that errors was the
nearest Fiber but if the thing erroring is a Server Component, we need
to get that as the owner from the inner most part of debugInfo.

To get the Task for that Server Component, we need to expose it on the
ReactComponentInfo object. Unfortunately that makes the object not
serializable so we need to special case this to exclude it from
serialization. It gets restored again on the client.

Before (Shell):
<img width="813" alt="Screenshot 2024-06-06 at 5 16 20 PM"
src="https://github.com/facebook/react/assets/63648/7da2d4c9-539b-494e-ba63-1abdc58ff13c">

After (App):
<img width="811" alt="Screenshot 2024-06-08 at 12 29 23 AM"
src="https://github.com/facebook/react/assets/63648/dbf40bd7-c24d-4200-81a6-5018bef55f6d">
2024-06-11 18:10:24 -04:00
Sebastian Markbåge
2774208039 Remove Warning: prefix and toString on console Arguments (#29839)
Basically make `console.error` and `console.warn` behave like normal -
when a component stack isn't appended. I need this because I need to be
able to print rich logs with the component stack option and to be able
to disable instrumentation completely in `console.createTask`
environments that don't need it.

Currently we can't print logs with richer objects because they're
toString:ed first. In practice, pretty much all arguments we log are
already toString:ed so it's not necessary anyway. Some might be like a
number. So it would only be a problem if some environment can't handle
proper consoles but then it's up to that environment to toString it
before logging.

The `Warning: ` prefix is historic and is both noisy and confusing. It's
mostly unnecessary since the UI surrounding `console.error` and
`console.warn` tend to have visual treatment around it anyway. However,
it's actively misleading when `console.error` gets prefixed with a
Warning that we consider an error level. There's an argument to be made
that some of our `console.error` don't make the bar for an error but
then the argument is to downgrade each of those to `console.warn` - not
to brand all our actual error logging with `Warning: `.

Apparently something needs to change in React Native before landing this
because it depends on the prefix somehow which probably doesn't make
sense already.
2024-06-10 18:41:56 -04:00
Sebastian Markbåge
c2ae9e28bc Minify DEV bundles with closure (#29809)
The goal is to improve speed of the development by inlining and DCE
unused branches.

We have the ability to preserve some variable names and pretty print in
the production version so might as well do the same with DEV.
2024-06-08 11:15:57 -04:00
Jan Kassens
142b2a8230 www: make disableLegacyMode dynamic flag (#29774)
This makes the flag dynamic for Meta and turns it on for the www test
renderer.
2024-06-07 07:36:10 -04:00
Dmytro Rykun
eb259b5d3b Add enableShallowPropDiffing feature flag (#29664)
## Summary

We currently do deep diffing for object props, and also use custom
differs, if they are defined, for props with custom attribute config.

The idea is to simply do a `===` comparison instead of all that work. We
will do less computation on the JS side, but send more data to native.

The hypothesis is that this change should be neutral in terms of
performance. If that's the case, we'll be able to get rid of custom
differs, and be one step closer to deleting view configs.

This PR adds the `enableShallowPropDiffing` feature flag to support this
experiment.

## How did you test this change?

With `enableShallowPropDiffing` hardcoded to `true`:
```
yarn test packages/react-native-renderer
```
This fails on the following test cases:
- should use the diff attribute
- should do deep diffs of Objects by default
- should skip deeply-nested changed functions

Which makes sense with this change. These test cases should be deleted
if the experiment is shipped.
2024-06-05 15:07:58 +01:00
Jan Kassens
a26e90c29c www: set enableRefAsProp to true (#29756)
www: set enableRefAsProp to true
2024-06-04 11:17:19 -04:00
Sebastian Markbåge
4dcdf21325 [Fiber] Prefix owner stacks with the current stack at the console call (#29697)
This information is available in the regular stack but since that's
hidden behind an expando and our appended stack to logs is not hidden,
it hides the most important frames like the name of the current
component.

This is closer to what happens to the native stack.

We only include stacks if they're within a ReactFiberCallUserSpace call
frame. This should be most that have a current fiber but this is
critical to filtering out most React frames if the regular node_modules
filter doesn't work.

Most React warnings fire during the rendering phase and not inside a
user space function but some do like hooks warnings and setState in
render. This feature is more important if we port this to React DevTools
appending stacks to all logs where it's likely to originate from inside
a component and you want the line within that component to immediately
part of the visible stack.

One thing that kind sucks is that we don't have a reliable way to
exclude React internal stack frames. We filter node_modules but it might
not match. For other cases I try hard to only track the stack frame at
the root of React (e.g. immediately inside createElement) until the
ReactFiberCallUserSpace so we don't need the filtering to work. In this
case it's hard to achieve the same thing though. This is easier in RDT
because we have the start/end line and parsing of stack traces so we can
use that to exclude internals but that's a lot of code/complexity for
shipping within the library.

For example in Safari:

<img width="590" alt="Screenshot 2024-05-31 at 6 15 27 PM"
src="https://github.com/facebook/react/assets/63648/2820c8c0-8a03-42e9-8678-8348f66b051a">

Ideally warnOnUseFormStateInDev and useFormState wouldn't be included
since they're React internals. Before this change, the Counter.js line
also wasn't included though which points to exactly where the error is
within the user code.

(Note Server Components have V8 formatted lines and Client Components
have JSC formatted lines.)
2024-06-03 12:26:38 -04:00
Jack Pope
2787eebe52 Clean up disableDOMTestUtils (#29610)
`disableDOMTestUtils` and the FB build `ReactTestUtilsFB` allowed us to
finish migrating internal callsites off of ReactTestUtils. Now that
usage is cleaned up, we can remove the flag, build artifact, and test
coverage for the deprecated utility methods.
2024-05-28 14:55:14 -04:00
Sebastian Markbåge
ea6e05912a [Fiber] Enable Native console.createTask Stacks When Available (#29223)
Stacked on #29206 and #29221.

This disables appending owner stacks to console when
`console.createTask` is available in the environment. Instead we rely on
native "async" stacks that end up looking like this with source maps and
ignore list enabled.

<img width="673" alt="Screenshot 2024-05-22 at 4 00 27 PM"
src="https://github.com/facebook/react/assets/63648/5313ed53-b298-4386-8f76-8eb85bdfbbc7">

Unfortunately Chrome requires a string name for each async stack and,
worse, a suffix of `(async)` is automatically added which is very
confusing since it seems like it might be an async component or
something which it is not.

In this case it's not so bad because it's nice to refer to the host
component which otherwise doesn't have a stack frame since it's
internal. However, if there were more owners here there would also be a
`<Counter> (async)` which ends up being kind of duplicative.

If the Chrome DevTools is not open from the start of the app, then
`console.createTask` is disabled and so you lose the stack for those
errors (or those parents if the devtools is opened later). Unlike our
appended ones that are always added. That's unfortunate and likely to be
a bit of a DX issue but it's also nice that it saves on perf in DEV mode
for those cases. Framework dialogs can still surface the stack since we
also track it in user space in parallel.

This currently doesn't track Server Components yet. We need a more
clever hack for that part in a follow up.

I think I probably need to also add something to React DevTools to
disable its stacks for this case too. Since it looks for stacks in the
console.error and adds a stack otherwise. Since we don't add them
anymore from the runtime, the DevTools adds them instead.
2024-05-26 17:55:57 -04:00
Sebastian Markbåge
d6cfa0f295 [Fiber] Use Owner/JSX Stack When Appending Stacks to Console (#29206)
This one should be fully behind the `enableOwnerStacks` flag.

Instead of printing the parent Component stack all the way to the root,
this now prints the owner stack of every JSX callsite. It also includes
intermediate callsites between the Component and the JSX call so it has
potentially more frames. Mainly it provides the line number of the JSX
callsite. In terms of the number of components is a subset of the parent
component stack so it's less information in that regard. This is usually
better since it's more focused on components that might affect the
output but if it's contextual based on rendering it's still good to have
parent stack. Therefore, I still use the parent stack when printing DOM
nesting warnings but I plan on switching that format to a diff view
format instead (Next.js already reformats the parent stack like this).

__Follow ups__

- Server Components show up in the owner stack for client logs but logs
done by Server Components don't yet get their owner stack printed as
they're replayed. They're also not yet printed in the server logs of the
RSC server.

- Server Component stack frames are formatted as the server and added to
the end but this might be a different format than the browser. E.g. if
server is running V8 and browser is running JSC or vice versa. Ideally
we can reformat them in terms of the client formatting.

- This doesn't yet update Fizz or DevTools. Those will be follow ups.
Fizz still prints parent stacks in the server side logs. The stacks
added to user space `console.error` calls by DevTools still get the
parent stacks instead.

- It also doesn't yet expose these to user space so there's no way to
get them inside `onCaughtError` for example or inside a custom
`console.error` override.

- In another follow up I'll use `console.createTask` instead and
completely remove these stacks if it's available.
2024-05-25 11:58:17 -04:00
Sebastian Markbåge
84239da896 Move createElement/JSX Warnings into the Renderer (#29088)
This is necessary to simplify the component stack handling to make way
for owner stacks. It also solves some hacks that we used to have but
don't quite make sense. It also solves the problem where things like key
warnings get silenced in RSC because they get deduped. It also surfaces
areas where we were missing key warnings to begin with.

Almost every type of warning is issued from the renderer. React Elements
are really not anything special themselves. They're just lazily invoked
functions and its really the renderer that determines there semantics.

We have three types of warnings that previously fired in
JSX/createElement:

- Fragment props validation.
- Type validation.
- Key warning.

It's nice to be able to do some validation in the JSX/createElement
because it has a more specific stack frame at the callsite. However,
that's the case for every type of component and validation. That's the
whole point of enableOwnerStacks. It's also not sufficient to do it in
JSX/createElement so we also have validation in the renderers too. So
this validation is really just an eager validation but also happens
again later.

The problem with these is that we don't really know what types are valid
until we get to the renderer. Additionally, by placing it in the
isomorphic code it becomes harder to do deduping of warnings in a way
that makes sense for that renderer. It also means we can't reuse logic
for managing stacks etc.

Fragment props validation really should just be part of the renderer
like any other component type. This also matters once we add Fragment
refs and other fragment features. So I moved this into Fiber. However,
since some Fragments don't have Fibers, I do the validation in
ChildFiber instead of beginWork where it would normally happen.

For `type` validation we already do validation when rendering. By
leaving it to the renderer we don't have to hard code an extra list.
This list also varies by context. E.g. class components aren't allowed
in RSC but client references are but we don't have an isomorphic way to
identify client references because they're defined by the host config so
the current logic is flawed anyway. I kept the early validation for now
without the `enableOwnerStacks` since it does provide a nicer stack
frame but with that flag on it'll be handled with nice stacks anyway. I
normalized some of the errors to ensure tests pass.

For `key` validation it's the same principle. The mechanism for the
heuristic is still the same - if it passes statically through a parent
JSX/createElement call then it's considered validated. We already did
print the error later from the renderer so this also disables the early
log in the `enableOwnerStacks` flag.

I also added logging to Fizz so that key warnings can print in SSR logs.

Flight is a bit more complex. For elements that end up on the client we
just pass the `validated` flag along to the client and let the client
renderer print the error once rendered. For server components we log the
error from Flight with the server component as the owner on the stack
which will allow us to print the right stack for context. The factoring
of this is a little tricky because we only want to warn if it's in an
array parent but we want to log the error later to get the right debug
info.

Fiber/Fizz has a similar factoring problem that causes us to create a
fake Fiber for the owner which means the logs won't be associated with
the right place in DevTools.
2024-05-23 12:48:57 -04:00
Sebastian Markbåge
2e540e22b2 Set the current fiber to the source of the error during error reporting (#29044)
This lets us expose the component stack to the error reporting that
happens here as `console.error` patching. Now if you just call
`console.error` in the error handlers it'll get the component stack
added to the end by React DevTools.

However, unfortunately this happens a little too late so the Fiber will
be disconnected with its `.return` pointer set to null already. So it'll
be too late to extract a parent component stack from but you can at
least get the stack from source to error boundary. To work around this I
manually add the parent component stack in our default handlers when
owner stacks are off. We could potentially fix this but you can also
just include it yourself if you're calling `console.error` and it's not
a problem for owner stacks.

This is not a problem for owner stacks because we'll still have those
and so for those just calling `console.error` just works. However, the
main feature is that by letting React add them, we can switch to using
native error stacks when available.
2024-05-23 12:39:52 -04:00
Josh Story
217b2ccf16 [Fiber] render boundary in fallback if it contains a new stylesheet during sync update (#28965)
Updates Suspensey instances and resources to preload even during urgent
updates and to potentially suspend.

The current implementation is unchanged for transitions but for sync
updates if there is a suspense boundary above the resource/instance it
will be rendered in fallback mode instead.

Note: This behavior is not what we want for images once we make them
suspense enabled. We will need to have forked behavior here to
distinguish between stylesheets which should never commit when not
loaded and images which should commit after a small delay
2024-05-21 16:03:46 -07:00