Commit Graph

493 Commits

Author SHA1 Message Date
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
Sebastian Markbåge
3d2ab01a55 [Flight] Extract special cases for Server Component return value position (#31713)
This is just moving some code into a helper.

We have a bunch of special cases for the return value slot of a Server
Component that's different from just rendering that inside an object.
This was getting a little tricky to reason about inline with the rest of
rendering.
2024-12-09 17:20:46 -05:00
Sebastian Markbåge
1c9b138714 Don't serialize chunk ids for Hint and Console rows (#31671)
Hints and Console logs are side-effects and don't belong to any
particular value. They're `void`. Therefore they don't need a row ID.

In the current parsing scheme it's ok to omit the id. It just becomes
`0` which is the initial value which is then unused for these row types.

So it looks like:

```
:HP[...]
:W[...]
0:{...}
```

We could patch the parsing to encode the tag in the ID so it's more like
the ID is the target of the side-effect.

```
H:P[...]
W:[...]
0:{...}
```

Or move the tagging to the beginning like it used to be.

But this seems simple enough for now.
2024-12-04 19:53:20 -05:00
Sebastian Markbåge
92c0f5f85f Track separate SuspendedOnAction flag by rethrowing a separate SuspenseActionException sentinel (#31554)
This lets us track separately if something was suspended on an Action
using useActionState rather than suspended on Data.

This approach feels quite bloated and it seems like we'd eventually
might want to read more information about the Promise that suspended and
the context it suspended in. As a more general reason for suspending.

The way useActionState works in combination with the prewarming is quite
unfortunate because 1) it renders blocking to update the isPending flag
whether you use it or not 2) it prewarms and suspends the useActionState
3) then it does another third render to get back into the useActionState
position again.
2024-11-15 17:52:24 -05:00
lauren
b15135b9f5 [ez] Update useMemoCache return type (#31539)
Use `mixed` instead of `any`
2024-11-14 12:10:51 -05:00
Jan Kassens
e1378902bb [string-refs] cleanup string ref code (#31443) 2024-11-06 14:00:10 -05:00
Sebastian Markbåge
156eab2f7b Fork the "empty" prepareStackTrace case for Server builds (#31427)
We don't actually want the source mapped version of `.stack` from errors
because that would cause us to not be able to associate it with a source
map in the UIs that need it. The strategy in browsers is more correct
where the display is responsible for source maps.

That's why we disable any custom `prepareStackTrace` like the ones added
by `source-map`. We reset it to `undefined`.

However, when running node with `--enable-source-maps` the default for
`prepareStackTrace` which is a V8 feature (but may exist elsewhere too
like Bun) is a source mapped version of the stack. In those environments
we need to reset it to a default implementation that doesn't apply
source maps.

We already did this in Flight using the `ReactFlightStackConfigV8.js`
config. However, we need this more generally in the
`shared/ReactComponentStackFrame` implementation.

We could always set it to the default implementation instead of
`undefined` but that's unnecessary code in browser builds and it might
lead to slightly different results. For safety and code size, this PR
does it with a fork instead.

All builds specific to `node` or `edge` (or `markup` which is a server
feature) gets the default implementation where as everything else (e.g.
browsers) get `undefined` since it's expected that this is not source
mapped. We don't have to do anything about the equivalent in React
DevTools since React DevTools doesn't run on the server.
2024-11-05 15:05:04 -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
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
Sam Zhou
45804af18d [flow] Eliminate usage of more than 1-arg React.AbstractComponent in React codebase (#31314)
<!--
  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

In order to adopt react 19's ref-as-prop model, Flow needs to eliminate
all the places where they are treated differently.
`React.AbstractComponent` is the worst example of this, and we need to
eliminate it.

This PR eliminates them from the react repo, and only keeps the one that
has 1 argument of props.

## How did you test this change?

yarn flow
2024-10-21 16:17:41 -07: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
70fb136391 Fix limit without owner stacks (#31179)
Move out of gate.
2024-10-10 14:52:33 -04:00
Josh Story
38af456a49 [Flight] don't emit chunks for rejected thenables after abort (#31169)
When aborting we emit chunks for each pending task. However there was a
bug where a thenable could also reject before we could flush and we end
up with an extra chunk throwing off the pendingChunks bookeeping. When a
task is retried we skip it if is is not in PENDING status because we
understand it was completed some other way. We need to replciate this
for the reject pathway on serialized thenables since aborting if
effectively completing all pending tasks and not something we need to
continue to do once the thenable rejects later.
2024-10-10 06:47:32 -07: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
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
Josh Story
67fee58b1f [Fizz] Start initial work immediately (#31079)
In a recent update we make Flight start working immediately rather than
waitin for a new task. This commit updates fizz to have similar
mechanics. We start the render in the currently running task but we do
so in a microtask to avoid reentrancy. This aligns Fizz with Flight.

ref: https://github.com/facebook/react/pull/30961
2024-09-26 13:51:45 -07: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
Josh Story
ae75d5a3f5 [Fizz] Include componentStack at the root when aborting (#31011)
When aborting we currently don't produce a componentStack when aborting
the shell. This is likely just an oversight and this change updates this
behavior to be consistent with what we do when there is a boundary
2024-09-20 10:00:02 -07:00
Josh Story
fc5ef50da8 [Flight] Start initial work immediately (#30961)
In a past update we made render and prerender have different work
scheduling behavior because these methods are meant to be used in
differeent environments with different performance tradeoffs in mind.
For instance to prioritize streaming we want to allow as much IO to
complete before triggering a round of work because we want to flush as
few intermediate UI states. With Prerendering there will never be any
intermediate UI states so we can more aggressively render tasks as they
complete.

One thing we've found is that even during render we should ideally kick
off work immediately. This update normalizes the intitial work for
render and prerender to start in a microtask. Choosing microtask over
sync is somewhat arbitrary but there really isn't a reason to make them
different between render/prerender so for now we'll unify them and keep
it as a microtask for now.

This change also updates pinging behavior. If the request is still in
the initial task that spawned it then pings will schedule on the
microtask queue. This allows immediately available async APIs to resolve
right away. The concern with doing this for normal pings is that it
might crowd out IO events but since this is the initial task there would
be IO to already be scheduled.
2024-09-14 09:26:01 -07:00
Josh Story
6774caa379 [Flight] properly track pendingChunks when changing environment names (#30958)
When the environment name changes for a chunk we issue a new debug chunk
which updates the environment name. This chunk was not beign included in
the pendingChunks count so the count was off when flushing
2024-09-13 15:55:42 -07: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
473522093d [Fizz] Add resumeAndPrerender to Static Rendering (#30950)
This is only in the same experimental exports as `resume`. Useful with
Postpone/Halt.

We already have `prerender()` to create a partial tree with postponed
state. We also have `resume()` to dynamically resume such a tree.

This lets you do a new prerender by resuming an already existing
postponed state. Basically creating a chain of preludes. The next
prelude would include the scripts to patch up the document.

This mostly just works since both prerender and resume are already
implemented using the same code so we just enable both at the root. I'm
sure we'll find some edge cases since this wasn't considered when it was
first written but so far I've only found an unrelated existing bug with
`keyPath` fixed here.
2024-09-12 10:51:01 -04:00
Sebastian Markbåge
1bb056363c [Fizz] Use RequestInstance constructor for resuming (#30947)
We added enough fields to need a constructor instead of inline object in
V8.

We didn't update the resumeRequest path though so it wasn't using the
constructor and had a different hidden class.
2024-09-11 11:35:01 -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
96aca5f4f3 Spawn new task if we hit stack overflow (#30419)
If we see the "Maximum call stack size exceeded" error we know we've hit
stack overflow. We can recover from this by spawning a new task and
trying again. Effectively a zero-cost trampoline in the normal case. The
new task will have a clean stack. If you have a lot of siblings at the
same depth that hits the limit you can end up hitting this once for each
sibling but within that new sibling you're unlikely to hit this again.
So it's not too expensive.

If it errors again in the retryTask pass, the other error handling takes
over which causes this to be able to still not infinitely stall. E.g.
when the component itself throws an error like this.

It's still better to increase the stack limit for performance if you
have a really deep tree but it doesn't really hurt to be able to recover
since it's zero cost when it doesn't happen.

We could do the same thing for Flight. Those trees don't tend to be as
deep but could happen.
2024-08-27 13:10:37 -04:00
Josh Story
ab24f643d0 [Fizz] use microtasks rather than tasks when scheduling work while prerendering (#30770)
Similar to https://github.com/facebook/react/pull/30768 we want to
schedule work during prerendering in microtasks both for the root task
and pings. We continue to schedule flushes as Tasks to allow as much
work to be batched up as possible.
2024-08-21 07:55:56 -07:00
Josh Story
dc32c7f35e [Flight] use microtask for scheduling during prerenders (#30768)
In https://github.com/facebook/react/pull/29491 I updated the work
scheduler for Flight to use microtasks to perform work when something
pings. This is useful but it does have some downsides in terms of our
ability to do task prioritization. Additionally the initial work is not
instantiated using a microtask which is inconsistent with how pings
work.

In this change I update the scheduling logic to use microtasks
consistently for prerenders and use regular tasks for renders both for
the initial work and pings.
2024-08-20 21:43:21 -07:00
Josh Story
85180b8cf8 [Fizz][Static] when aborting a prerender halt unfinished boundaries instead of erroring (#30732)
When we introduced prerendering for flight we modeled an abort of a
flight prerender as having unfinished rows. This is similar to how
postpone was already implemented when you postponed from "within" a
prerender using React.unstable_postpone. However when aborting with a
postponed instance every boundary would be eagerly marked for client
rendering which is more akin to prerendering and then resuming with an
aborted signal.

The insight with the flight work was that it's not so much the postpone
that describes the intended semantics but the abort combined with a
prerender. So like in flight when you abort a prerender and enableHalt
is enabled boundaries and the shell won't error for any reason. Fizz
will still call onPostpone and onError according to the abort reason but
the consuemr of the prerender should expect to resume it before trying
to use it.
2024-08-20 13:30:51 -07:00
Josh Story
92d26c8e93 [Flight] When halting omit any reference rather than refer to a shared missing chunk (#30750)
When aborting a prerender we should leave references unfulfilled, not
share a common unfullfilled reference. functionally today this doesn't
matter because we don't have resuming but the semantic is that the row
was not available when the abort happened and in a resume the row should
fill in. But by pointing each task to a common unfulfilled chunk we lose
the ability for these references to resolves to distinct values on
resume.
2024-08-20 10:22:39 -07:00
Josh Story
2505bf9b34 [Fizz] track postpones when aborting boundaries with a postpone (#30751)
When aborting with a postpone value boundaries are put into client
rendered mode even during prerenders. This doesn't follow the postpoen
semantics of the rest of fizz where during a prerender a postpone is
tracked and it will leave holes in tracked postpone state that can be
resumed. This change updates this behavior to match the postpones
semantics between aborts and imperative postpones.
2024-08-20 09:49:41 -07: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
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
Josh Story
7954db9398 [Fizz] handle throwing after abort during render (#30730)
It is possible to throw after aborting during a render and we were not
properly tracking this. We use an AbortSigil to mark whether a rendering
task needs to abort but the throw interrupts that and we end up handling
an error on the error pathway instead.

This change reworks the abort-while-rendering support to be robust to
throws after calling abort
2024-08-16 18:29:18 -07:00
Josh Story
7b41cdc093 [Flight][Static] Implement halting a prerender behind enableHalt (#30705)
enableHalt turns on a mode for flight prerenders where aborts are
treated like infinitely stalled outcomes while still completing the
prerender. For regular tasks we simply serialize the slot as a promise
that never settles. For ReadableStream, Blob, and Async Iterators we
just never advance the serialization so they remain unfinished when
consumed on the client.

When enableHalt is turned on aborts of prerenders will halt rather than
error. The abort reason is forwarded to the upstream produces of the
aforementioned async iterators, blobs, and ReadableStreams. In the
future if we expose a signal that you can consume from within a render
to cancel additional work the abort reason will also be forwarded there
2024-08-16 14:21:57 -07:00
Josh Story
fa6eab5854 [Flight] Implement prerender (#30686)
Prerendering in flight is similar to prerendering in Fizz. Instead of
receiving a result (the stream) immediately a promise is returned which
resolves to the stream when the prerender is complete. The promise will
reject if the flight render fatally errors otherwise it will resolve
when the render is completed or is aborted.
2024-08-15 14:28:28 -07: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
Josh Story
2a540194ad [Flight] do not emit error after abort (#30683)
When synchronously aborting in a non-async Function Component if you
throw after aborting the task would error rather than abort because
React never observed the AbortSignal.

Using a sigil to throw after aborting during render isn't effective b/c
the user code itself could throw so insteead we just read the request
status. This is ok b/c we don't expect any tasks to still be pending
after the currently running task finishes.

However I found one instance where that wasn't true related to
serializing thenables which I've fixed so we may find other cases. If we
do, though it's almost certainly a bug in our task bookkeeping so we
should just fix it if it comes up.

I also updated `abort` to not set the status to ABORTING unless the
status was OPEN. we don't want to ever leave CLOSED or CLOSING status
2024-08-13 20:59:45 -07:00
Josh Story
f6d1df6648 [Flight] erroring after abort should not result in unhandled rejection (#30675)
When I implemented the ability to abort synchronoulsy in flight I made
it possible for erroring async server components to cause an unhandled
rejection error. In the current implementation if you abort during the
synchronous phase of a Function Component and then throw an error in the
synchronous phase React will not attach any promise handlers because it
short circuits the thenable treatment and throws an AbortSigil instead.
This change updates the rendering logic to ignore the rejecting
component.
2024-08-13 13:42:10 -07:00
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
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
Josh Story
a7d1240c96 [Fizz] Update postpone abort semantics when prerendering (#30541)
When aborting with a postpone value in Fizz if any tasks are still
pending in the root while prerendering the prerender will fatally error.
This is different from postponing imperatively in a root task and really
the semantics should be the same. This change updates React to treat an
abort with a postpone value as a postponed root rather than a fatal
error.
2024-07-31 08:33:43 -07:00