Commit Graph

257 Commits

Author SHA1 Message Date
Ricky
08dfd0b805 Remove enableBinaryflight (#31759)
Based off https://github.com/facebook/react/pull/31757

This has landed everywhere.
2024-12-13 14:50:13 -05:00
Sebastian Markbåge
130095f76b [Flight Parcel] Align with more recent changes (#31741)
Follow up to #31725.

I diffed against the Turbopack one to find any unexpected discrepancies.
Some parts are forked enough that it's hard to diff but I think I got
most of it.
2024-12-12 14:39:25 -05:00
Sebastian Markbåge
6928bf2f7c [Flight] Log Server Component into Performance Track (#31729)
<img width="966" alt="Screenshot 2024-12-10 at 10 49 19 PM"
src="https://github.com/user-attachments/assets/27a21bdf-86b9-4203-893b-89523e698138">

This emits a tree view visualization of the timing information for each
Server Component provided in the RSC payload.

The unique thing about this visualization is that the end time of each
Server Component spans the end of the last child. Now what is
conceptually a blocking child is kind of undefined in RSC. E.g. if
you're not using a Promise on the client, or if it is wrapped in
Suspense, is it really blocking the parent?

Here I reconstruct parent-child relationship by which chunks reference
other chunks. A child can belong to more than one parent like when we
dedupe the result of a Server Component.

Then I wait until the whole RSC payload has streamed in, and then I
traverse the tree collecting the end time from children as I go and emit
the `performance.measure()` calls on the way up.

There's more work for this visualization in follow ups but this is the
basics. For example, since the Server Component time span includes async
work it's possible for siblings to execute their span in parallel (Foo
and Bar in the screenshot are parallel siblings). To deal with this we
need to spawn parallel work into separate tracks. Each one can be deep
due to large trees. This can makes this type of visualization unwieldy
when you have a lot of parallelism. Therefore I also plan another
flatter Timeline visualization in a follow up.
2024-12-12 14:03:18 -05:00
Devon Govett
ca587425fe Implement react-server-dom-parcel (#31725)
This adds a new `react-server-dom-parcel-package`, which is an RSC
integration for the Parcel bundler. It is mostly copied from the
existing webpack/turbopack integrations, with some changes to utilize
Parcel runtime APIs for loading and executing bundles/modules.

See https://github.com/parcel-bundler/parcel/pull/10043 for the Parcel
side of this, which includes the plugin needed to generate client and
server references. https://github.com/parcel-bundler/rsc-examples also
includes examples of various ways to use RSCs with Parcel.

Differences from other integrations:

* Client and server modules are all part of the same graph, and we use
Parcel's
[environments](https://parceljs.org/plugin-system/transformer/#the-environment)
to distinguish them. The server is the Parcel build entry point, and it
imports and renders server components in route handlers. When a `"use
client"` directive is seen, the environment changes and Parcel creates a
new client bundle for the page, combining all client modules together.
CSS from both client and server components are also combined
automatically.
* There is no separate manifest file that needs to be passed around by
the user. A [Runtime](https://parceljs.org/plugin-system/runtime/)
plugin injects client and server references as needed into the relevant
bundles, and registers server action ids using `react-server-dom-parcel`
automatically.
* A special `<Resources>` component is also generated by Parcel to
render the `<script>` and `<link rel="stylesheet">` elements needed for
a page, using the relevant info from the bundle graph.

Note: I've already published a 0.0.x version of this package to npm for
testing purposes but happy to add whoever needs access to it as well.

### Questions

* How to test this in the React repo. I'll have integration tests in
Parcel, but setting up all the different mocks and environments to
simulate that here seems challenging. I could try to copy how
Webpack/Turbopack do it but it's a bit different.
* Where to put TypeScript types. Right now I have some ambient types in
my [example
repo](https://github.com/parcel-bundler/rsc-examples/blob/main/types.d.ts)
but it would be nice for users not to copy and paste these. Can I
include them in the package or do they need to maintained separately in
definitelytyped? I would really prefer not to have to maintain code in
three different repos ideally.

---------

Co-authored-by: Sebastian Markbage <sebastian@calyptus.eu>
2024-12-11 22:58:51 -05:00
Sebastian Markbåge
79ddf5b574 [Flight] Track Timing Information (#31716)
Stacked on #31715.

This adds profiling data for Server Components to the RSC stream (but
doesn't yet use it for anything). This is on behind
`enableProfilerTimer` which is on for Dev and Profiling builds. However,
for now there's no Profiling build of Flight so in practice only in DEV.
It's gated on `enableComponentPerformanceTrack` which is experimental
only for now.

We first emit a timeOrigin in the beginning of the stream. This provides
us a relative time to emit timestamps against for cross environment
transfer so that we can log it in terms of absolute times. Using this as
a separate field allows the actual relative timestamps to be a bit more
compact representation and preserves floating point precision.

We emit a timestamp before emitting a Server Component which represents
the start time of the Server Component. The end time is either when the
next Server Component starts or when we finish the task.

We omit the end time for simple tasks that are outlined without Server
Components.

By encoding this as part of the debugInfo stream, this information can
be forwarded between Server to Server RSC.
2024-12-10 20:46:19 -05:00
Sebastian Markbåge
372ec00c03 Update ReactDebugInfo types to declare timing info separately (#31714)
This clarifies a few things by ensuring that there is always at least
one required field. This can be used to refine the object to one of the
specific types. However, it's probably just a matter of time until we
make this tagged unions instead. E.g. it would be nice to rename the
`name` field `ReactComponentInfo` to `type` and tag it with the React
Element symbol because then it's just the same as a React Element.

I also extract a time field. The idea is that this will advance (or
rewind) the time to the new timestamp and then anything below would be
defined as happening within that time stamp. E.g. to model the start and
end for a server component you'd do something like:

```
[
  {time: 123},
  {name: 'Component', ... },
  {time: 124},
]
```

The reason this needs to be in the `ReactDebugInfo` is so that timing
information from one environment gets transferred into the next
environment. It lets you take a Promise from one world and transfer it
into another world and its timing information is preserved without
everything else being preserved.

I've gone back and forth on if this should be part of each other Info
object like `ReactComponentInfo` but since those can be deduped and can
change formats (e.g. this should really just be a React Element) it's
better to store this separately.

The time format is relative to a `timeOrigin` which is the current
environment's `timeOrigin`. When it's serialized between environments
this needs to be considered.

Emitting these timings is not yet implemented in this PR.

---------

Co-authored-by: eps1lon <sebastian.silbermann@vercel.com>
2024-12-09 19:47:43 -05:00
Ricky
5b0ef217ef s/server action/server function (#31005)
## Overview

Changes the error message to say "Server Functions" instead of "Server
Actions" since this error can fire in cases like:

```
<button onClick={serverFunction} />
```

Which is calling a server function, not a server action.
2024-12-02 10:02:31 -05:00
Jan Kassens
e1378902bb [string-refs] cleanup string ref code (#31443) 2024-11-06 14:00:10 -05:00
Jan Kassens
07aa494432 Remove enableRefAsProp feature flag (#30346)
The flag is fully rolled out.
2024-11-04 14:30:58 -05:00
Sebastian Markbåge
b7e2157922 [Flight] Handle errors during JSON stringify of console values (#31391)
When we serialize debug info we should never error even though we don't
currently support everything being serialized. Since it's non-essential
dev information.

We already handle errors in the replacer but not when errors happen in
the JSON algorithm itself - such as cyclic errors.

We should ideally support cyclic objects but regardless we should
gracefully handle the errors.
2024-10-31 16:47:51 -04:00
Sebastian Markbåge
1631855f43 [Flight] encodeURI filenames parsed from stack traces (#31340)
When parsing stacks from third parties they may include invalid url
characters. So we need to encode them. Since these are expected to be
urls though we use just encodeURI instead of encodeURIComponent.
2024-10-23 16:29:20 -07:00
Sebastian Markbåge
b3e0a11e8f [Flight] Allow <anonymous> stack frames to be serialized if opt-in (#31329)
Normally we filter out stack frames with missing `filename` because they
can be noisy and not ignore listed. However, it's up to the
filterStackFrame function to determine whether to do it. This lets us
match `<anonymous>` stack frames in V8 parsing (they don't have line
numbers).
2024-10-23 08:38:33 -07:00
Sebastian Markbåge
65a56d0e99 Fix timing issue with fake promise resolving sync (#31304) 2024-10-20 02:35:15 -04:00
Sebastian Markbåge
f11bd3439c Fix types (#31303) 2024-10-20 02:23:31 -04:00
Sebastian Markbåge
251b666ded [Flight] Handle bound arguments for loaded server references (#31302)
Follow up to #31300.

I forgot to pass the bound arguments to the loaded function.
2024-10-20 02:12:06 -04:00
Sebastian Markbåge
22b2b1a05a [Flight] Add serverModuleMap option for mapping ServerReferences (#31300)
Stacked on #31299.

We already have an option for resolving Client References to other
Client References when consuming an RSC payload on the server.

This lets you resolve Server References on the consuming side when the
environment where you're consuming the RSC payload also has access to
those Server References. Basically they becomes like Client References
for this consumer but for another consumer they wouldn't be.
2024-10-19 21:10:25 -04:00
Sebastian Markbåge
39a7730b13 Rename SSRManifest to ServerConsumerManifest (#31299)
This config is more generally applicable to all server-side Flight
Clients and not just SSR.
2024-10-19 20:45:20 -04:00
Sebastian Markbåge
be94b10826 [Flight] Enable sync stack traces for errors and console replay (#31270)
This was gated behind `enableOwnerStacks` since they share some code
paths but it's really part of `enableServerComponentLogs`.

This just includes the server-side regular stack on Error/replayed logs
but doesn't use console.createTask and doesn't include owner stacks.
2024-10-16 10:57:08 -04:00
Sebastian Markbåge
cd22717c27 [Flight] Also don't cut off type and key (#31209) 2024-10-13 18:57:50 +02:00
Sebastian Markbåge
566b0b0f14 [Flight] Don't limit objects that are children of special types (#31160)
We can't make a special getter to mark the boundary of deep
serialization (which can be used for lazy loading in the future) when
the parent object is a special object that we parse with
getOutlinedModel. Such as Map/Set and JSX.

This marks the objects that are direct children of those as not possible
to limit.

I don't love this solution since ideally it would maybe be more local to
the serialization of a specific object.

It also means that very deep trees of only Map/Set never get cut off.
Maybe we should instead override the `get()` and enumeration methods on
these instead somehow.

It's important to have it be a getter though because that's the
mechanism that lets us lazy-load more depth in the future.
2024-10-10 07:36:37 -04:00
Josh Story
f5b8d9378b [Flight] Serialize top-level Date (#31163)
renderModelDesctructive can sometimes be called direclty on Date values.
When this happens we don't first call toJSON on the Date value so we
need to explicitly handle the case where where the rendered value is a
Date instance as well. This change updates renderModelDesctructive to
account for sometimes receiving Date instances directly.
2024-10-09 20:29:48 -07:00
Sebastian Markbåge
99c056abb0 [Flight] Allow aborting encodeReply (#31106)
Allow aborting encoding arguments to a Server Action if a Promise
doesn't resolve. That way at least part of the arguments can be used on
the receiving side. This leaves it unresolved in the stream rather than
encoding an error.

This should error on the receiving side when the stream closes but it
doesn't right now in the Edge/Browser versions because closing happens
immediately before we've had a chance to call `.then()` so the Chunks
are still in pending state. This is an existing bug also in
FlightClient.
2024-10-01 14:28:51 -04:00
Sebastian Markbåge
654e387d7e [Flight] Serialize Server Components Props in DEV (#31105)
This allows us to show props in React DevTools when inspecting a Server
Component.

I currently drastically limit the object depth that's serialized since
this is very implicit and you can have heavy objects on the server.

We previously was using the general outlineModel to outline
ReactComponentInfo but we weren't consistently using it everywhere which
could cause some bugs with the parsing when it got deduped on the
client. It also lead to the weird feature detect of `isReactComponent`.
It also meant that this serialization was using the plain serialization
instead of `renderConsoleValue` which means we couldn't safely serialize
arbitrary debug info that isn't serializable there.

So the main change here is to call `outlineComponentInfo` and have that
always write every "Server Component" instance as outlined and in a way
that lets its props be serialized using `renderConsoleValue`.

<img width="1150" alt="Screenshot 2024-10-01 at 1 25 05 AM"
src="https://github.com/user-attachments/assets/f6e7811d-51a3-46b9-bbe0-1b8276849ed4">
2024-10-01 01:39:20 -04:00
Sebastian Markbåge
326832a56d [Flight] Serialize Error Values (#31104)
The idea is that the RSC protocol is a superset of Structured Clone.
#25687 One exception that we left out was serializing Error objects as
values. We serialize "throws" or "rejections" as Error (regardless of
their type) but not Error values.

This fixes that by serializing `Error` objects. We don't include digest
in this case since we don't call `onError` and it's not really expected
that you'd log it on the server with some way to look it up.

In general this is not super useful outside throws. Especially since we
hide their values in prod. However, there is one case where it is quite
useful. When you replay console logs in DEV you might often log an Error
object within the scope of a Server Component. E.g. the default RSC
error handling just console.error and error object.

Before this would just be an empty object due to our lax console log
serialization:
<img width="1355" alt="Screenshot 2024-09-30 at 2 24 03 PM"
src="https://github.com/user-attachments/assets/694b3fd3-f95f-4863-9321-bcea3f5c5db4">
After:
<img width="1348" alt="Screenshot 2024-09-30 at 2 36 48 PM"
src="https://github.com/user-attachments/assets/834b129d-220d-43a2-a2f4-2eb06921747d">

TODO for a follow up: Flight Reply direction. This direction doesn't
actually serialize thrown errors because they always reject the
serialization.
2024-09-30 15:45:13 -04:00
Hendrik Liebau
04bd67a490 Resolve references to deduped owner objects (#30549)
This is a follow-up from #30528 to not only handle props (the critical
change), but also the owner ~and stack~ of a referenced element.

~Handling stacks here is rather academic because the Flight Server
currently does not deduplicate owner stacks. And if they are really
identical, we should probably just dedupe the whole element.~ EDIT:
Removed from the PR.

Handling owner objects on the other hand is an actual requirement as
reported in https://github.com/vercel/next.js/issues/69545. This problem
only affects the stable release channel, as the absence of owner stacks
allows for the specific kind of shared owner deduping as demonstrated in
the unit test.
2024-09-24 02:34:53 -04:00
Sebastian Markbåge
dff50825c6 [Flight] Track owner/stack where the Flight Client reads as the root (#30933)
This means that the owner of a Component rendered on the remote server
becomes the Component on this server.

Ideally we'd support this for the Client side too. In particular Fiber
but currently ReactComponentInfo's owner is typed as only supporting
other ReactComponentInfo and it's a bigger lift to support that.
2024-09-12 17:19:34 -04:00
Sebastian Markbåge
bac33d1f82 [Flight] Unwrap lazy before reading the value (#30938)
This is important if the lazy is at the root of the chunk. I don't have
a unit test for it but @gnoff has a repro.

It also shouldn't unwrap the last value since that's the one we're
referencing.

This was already done correctly by @unstubbable in waitForReference so
this just aligns with that.
2024-09-10 19:42:19 -04:00
Sebastian Markbåge
6066b8e8e6 [Flight] Reset currentOwnerInDEV (#30929)
Missed this bit.
2024-09-09 22:07:35 -04:00
Sebastian Markbåge
49825c0ffc [Flight] Add react-stack-bottom-frame to console replaying (#30926)
Any time we're creating a stack trace we should have a
react-stack-bottom-frame so we know what to filter out.

This is the same thing we already do for createFakeJSXCallStackInDEV but
we should do that when replaying logs too.
2024-09-09 19:52:05 -04:00
Sebastian Markbåge
2283d7204c [Flight] Inject Client Into DevTools (#30910)
Stacked on #30906.

Injects the Flight Client into the DevTools hook if it `supportsFlight`.
This only injects in DEV. We could inject it in prod too but so far the
only feature this exposes is only available in DEV anyway. I also only
call `injectIntoDevTools` in the browser builds since we don't really
support DevTools on the server anyway.

The main purpose of this for now is so that DevTools can track the
Server Component owner of replayed logs. This lets us add owner stacks
where `console.createTask` is not natively supported (like Firefox). It
also lets us associate the log with the Server Component in the
Component tree #30905.
2024-09-09 15:11:57 -04:00
Sam Zhou
e210d08180 [flow] Upgrade Flow to 0.245.2 (#30919)
## Summary

This PR bumps Flow all the way to the latest 0.245.2. 

Most of the suppressions comes from Flow v0.239.0's change to include
undefined in the return of `Array.pop`.

I also enabled `react.custom_jsx_typing=true` and added custom jsx
typing to match the old behavior that `React.createElement` is
effectively any typed. This is necessary since various builtin
components like `React.Fragment` is actually symbol in the React repo
instead of `React.AbstractComponent<...>`. It can be made more accurate
by customizing the `React$CustomJSXFactory` type, but I will leave it to
the React team to decide.

## How did you test this change?

`yarn flow` for all the renderers
2024-09-09 08:41:44 -07:00
Sebastian Markbåge
1228a28398 Remove turbopack unbundled/register/loader (#30756)
The unbundled form is just a way to show case a prototype for how an
unbundled version of RSC can work. It's not really intended for every
bundler combination to provide such a configuration.

There's no configuration of Turbopack that supports this mode atm and
possibly never will be since it's more of an integrated server/client
experience.

This removes the unbundled form and node register/loaders from the
turbopack build.
2024-08-21 09:58:31 -04:00
Josh Story
a960b92cb9 [Flight] model halting as never delivered chunks (#30740)
stacked on: #30731

We've refined the model of halting a prerender. Now when you abort
during a prerender we simply omit the rows that would complete the
flight render. This is analagous to prerendering in Fizz where you must
resume the prerender to actually result in errors propagating in the
postponed holes. We don't have a resume yet for flight and it's not
entirely clear how that will work however the key insight here is that
deciding whether the never resolving rows are an error or not should
really be done on the consuming side rather than in the producer.

This PR also reintroduces the logs for the abort error/postpone when
prerendering which will give you some indication that something wasn't
finished when the prerender was aborted.
2024-08-19 19:34:20 -07:00
Sebastian Markbåge
0fa9476b9b [Flight] Revert Emit Infinite Promise as a Halted Row (#30746) (#30748)
This reverts commit 52c9c43735.

Just kidding. We realized we probably don't want to do the halted row
thing after all.
2024-08-19 16:34:38 -04:00
Sebastian Markbåge
52c9c43735 [Flight] Emit Infinite Promise as a Halted Row (#30746)
Stacked on #30731.

When logging a Promise we emit it as an infinite promise instead of
blocking the replay on it.

This models that as a halted row instead. No need for this special case.

I unflag the receiving side since now it's used to replace a feature
that's already unflagged so it's used.
2024-08-19 15:02:41 -04:00
Sebastian Markbåge
591adfa40d [Flight] Rename Chunk constructor to ReactPromise (#30747)
When printing these in DevTools they show up as the name of the
constructor so then you pass a Promise to the client it logs as "Chunk"
which is confusing.

Ideally we'd probably just name this Promise but 1) there's a slight
difference in the .then method atm 2) it's a bit tricky to name a
variable and get it from the global in the same scope. Closure compiler
doesn't let us just name a function because it removes it and just uses
the variable name.
2024-08-19 14:51:22 -04:00
Josh Story
9d082b5500 [Flight] model halted references explicitly (#30731)
using infinitely suspending promises isn't right because this will parse
as a promise which is only appropriate if the value we're halting at is
a promise. Instead we need to have a special marker type that says this
reference will never resolve. Additionally flight client needs to not
error any halted references when the stream closes because they will
otherwise appear as an error

addresses:
https://github.com/facebook/react/pull/30705#discussion_r1720479974
2024-08-19 11:24:41 -07:00
Sebastian Markbåge
6ebfd5b082 [Flight] Source Map Server Actions to their Server Location (#30741)
This uses a similar technique to what we use to generate fake stack
frames for server components. This generates an eval:ed wrapper function
around the Server Reference proxy we create on the client. This wrapper
function gets the original `name` of the action on the server and I also
add a source map if `findSourceMapURL` is defined that points back to
the source of the server function.

For `"use server"` on the server, there's no new API. It just uses the
callsite of `registerServerReference()` on the Server. We can infer the
function name from the actual function on the server and we already have
the `findSourceMapURL` on the client receiving it.

For `"use server"` imported from the client, there's two new options
added to `createServerReference()` (in addition to the optional
[`encodeFormAction`](#27563)). These are only used in DEV mode. The
[`findSourceMapURL`](#29708) option is the same one added in #29708. We
need to pass this these references aren't created in the context of any
specific request but globally. The other weird thing about this case is
that this is actually a case where the compiled environment is the
client so any source maps are the same as for the client layer, so the
environment name here is just `"Client"`.

```diff
  createServerReference(
    id: string,
    callServer: CallServerCallback,
    encodeFormAction?: EncodeFormActionCallback,
+   findSourceMapURL?: FindSourceMapURLCallback, // DEV-only
+   functionName?: string, // DEV-only
  )
```

The key is that we use the location of the
`registerServerReference()`/`createServerReference()` call as the
location of the function. A compiler can either emit those at the same
locations as the original functions or use source maps to have those
segments refer to the original location of the function (or in the case
of a re-export the original location of the re-export is also a fine
approximate). The compiled output must call these directly without a
wrapper function because the wrapper adds a stack frame. I decided
against complicated and fragile dev-only options to skip n number of
frames that would just end up in prod code. The implementation just
skips one frame - our own. Otherwise it'll just point all source mapping
to the wrapper.

We don't have a `"use server"` imported from the client implementation
in the reference implementation/fixture so it's a bit tricky to test
that. In the case of CJS on the server, we just use a runtime instead of
compiler so it's tricky to source map those appropriately. We can
implement it for ESM on the server which is the main thing we're testing
in the fixture. It's easier in a real implementation where all the
compilation is just one pass. It's a little tricky since we have to
parse and append to other source maps but I'd like to do that as a
follow up. Or maybe that's just an exercise for the reader.

You can right click an action and click "Go to Definition".

<img width="1323" alt="Screenshot 2024-08-17 at 6 04 27 PM"
src="https://github.com/user-attachments/assets/94d379b3-8871-4671-a20d-cbf9cfbc2c6e">

For now they simply don't point to the right place but you can still
jump to the right file in the fixture:

<img width="1512" alt="Screenshot 2024-08-17 at 5 58 40 PM"
src="https://github.com/user-attachments/assets/1ea5d665-e25a-44ca-9515-481dd3c5c2fe">

In Firefox/Safari given that the location doesn't exist in the source
map yet, the browser refuses to open the file. Where as Chrome does
nearest (last) line.
2024-08-18 12:31:45 -04:00
Sebastian Markbåge
19bd26beb6 [Flight/DevTools] Pass the Server Component's "key" as Part of the ReactComponentInfo (#30703)
Supports showing the key in DevTools on the Server Component that the
key was applied to. We can also use this to reconcile to preserve
instance equality when they're reordered.

One thing that's a bit weird about this is that if you provide an
explicit key on a Server Component that alone doesn't have any
semantics. It's because we pass the key down and let the nearest child
inherit the key or get prefixed by the key.

So you might see the same key as a prefix on the child of the Server
Component too which might be a bit confusing. We could remove the prefix
from children but that might also be a bit confusing if they collide.

The div in this case doesn't have a key explicitly specified. It gets it
from the Server Component parent.

<img width="1107" alt="Screenshot 2024-08-14 at 10 06 36 PM"
src="https://github.com/user-attachments/assets/cfc517cc-e737-44c3-a1be-050049267ee2">

Overall keys get a bit confusing when you apply filter. Especially since
it's so common to actually apply the key on a Host Instance. So you
often don't see the key.
2024-08-15 11:04:53 -04:00
Josh Story
8b08ee08a1 [Flight] reorganize code for forked entrypoints (#30702)
This commit updates the file locations and bulid configurations for
flight in preparation for new static entrypoints. This follows a
structure similar to Fizz which has a unified build but exports methods
from different top level entrypoints. This PR doesn't actually add the
new top level entrypoints however, that will arrive in a later update.
2024-08-14 18:10:40 -07:00
Sebastian Silbermann
5c9243d153 Rename renderToMarkup to renderToHTML (#30689) 2024-08-14 19:35:16 +02:00
Sebastian Silbermann
e0a0e65412 Move react-html to react-markup (#30688) 2024-08-14 19:22:44 +02:00
Sebastian Markbåge
ba6a9e94ed [Flight] Warn for keyless fragments in an array (#30588)
Conceptually this is the same as rendering this as if it was a built-in
Server Component.
2024-08-02 20:08:08 -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
Hendrik Liebau
3208e73e82 Assign resolved outlined props to element object (and not only tuple) (#30528)
Co-authored-by: eps1lon <sebastian.silbermann@vercel.com>
2024-07-30 21:31:32 +02:00
Sebastian Markbåge
e8df0cf9f7 Switch to binding the console with badging instead of calling it directly (#30461)
This is a major nit but this avoids an extra stack frame when we're
replaying logs.

Normally the `printToConsole` frame doesn't show up because it'd be
ignore listed.

<img width="421" alt="Screenshot 2024-07-25 at 11 49 39 AM"
src="https://github.com/user-attachments/assets/81334c2f-e19e-476a-871e-c4db9dee294e">

When you expand to show ignore listed frames a ton of other frames show
up.

<img width="516" alt="Screenshot 2024-07-25 at 11 49 47 AM"
src="https://github.com/user-attachments/assets/2ab8bdfb-464c-408d-9176-ee2fabc114b6">

The annoying thing about this frame is that it's at the top of the stack
where as typically framework stuff ends up at the bottom and something
you can ignore. The user space stack comes first.

With this fix there's no longer any `printToConsole` frame.

<img width="590" alt="Screenshot 2024-07-25 at 12 09 09 PM"
src="https://github.com/user-attachments/assets/b8365d53-31f3-43df-abce-172d608d3c9c">

Am I wiling to eat the added complexity and slightly slower performance
for this nit? Definitely.
2024-07-25 12:32:16 -04:00
Sebastian Markbåge
c2d103594d Configure the requested environment and annotate tasks at boundary between environments (#30455)
This enables configuring the name of the requested environment.

When we currently use createTask, we start with a `"use server"`
annotation. This option basically configures that string.

I now also deal with the case when switching environments along the
owner path. If you go from `"Third Party"` to `"Server"` to `"Client"`,
it'll have a task named `"use third party"` at the root, then `"use
server"` and then finally `"use client"`.

We don't really have the concept of a Server Component making a request
during render to then create another Server Component. Really the inner
one should conceptually have the first one as its owner in that case. So
currently the inner one will always have a null owner. We could somehow
connect them in this server-to-server case.

We don't currently have a way to configure the `"use client"` option but
I figured maybe that could be inferred by the server environment that
the Flight Client is executed within.

Note: We did talk before about annotating each stack frame with the
environment. You can effectively do that manually when parsing
`rsc://React/{environment}/` from `captureOwnerStack`. However, we can't
do that natively. At least not without deeper integration. Because it's
the source map that's responsible for the actual function name of each
stack frame - not what we give it at runtime. So for the native stacks,
the task showing the change in environment is more practical.
2024-07-25 11:46:58 -04:00
Sebastian Markbåge
e5d22459ff [Flight] Include environment name both in the virtual URL and findSourceMapURL (#30452)
This way you can use the environment to know where to look for the
source map in case you have multiple server environments.

This becomes part of the public protocol since it's part of what you'll
parse out of the `rsc://React/` prefixed URLs inside of
`captureOwnerStack`.
2024-07-25 11:14:24 -04:00
Sebastian Markbåge
4b62400765 [Flight] Add filterStackFrame options to the RSC Server (#30447)
This lets you customize the filter, for example allowing node_modules or
filter out additional functions that you don't want to include when
sending the stack to the client.

Notably this doesn't filter out Server Components out of the parent
stack. Those are just like a view of the tree by name. Not virtual stack
frames.
2024-07-25 10:50:56 -04:00
Hendrik Liebau
76002254b7 Fix resolving of references to deduped props in lazy elements (#30441)
When a model references a deduped object of a blocked element that has
subsequently been turned into a lazy element, we need to wait for the
lazy element's chunk to resolve before resolving the reference.

Without the fix, the new test failed with the following runtime error:

```
TypeError: Cannot read properties of undefined (reading 'children')
  1003 |       let value = chunk.value;
  1004 |       for (let i = 1; i < path.length; i++) {
> 1005 |         value = value[path[i]];
       |                          ^
  1006 |       }
  1007 |       const chunkValue = map(response, value);
  1008 |       if (__DEV__ && chunk._debugInfo) {

  at getOutlinedModel (packages/react-client/src/ReactFlightClient.js:1005:26)
```

The bug was uncovered after updating React in Next.js in
https://github.com/vercel/next.js/pull/66711.
2024-07-24 19:34:41 -04:00