2097 Commits

Author SHA1 Message Date
Sebastian Markbåge e30c6693e4 [Fiber] Delete isMounted internals (#31966)
The public API has been deleted a long time ago so this should be unused
unless it's used by hacks. It should be replaced with an
effect/lifecycle that manually tracks this if you need it.

The problem with this API is how the timing implemented because it
requires Placement/Hydration flags to be cleared too early. In fact,
that's why we also have a separate PlacementDEV flag that works
differently.


https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberCommitWork.js#L2157-L2165

We should be able to remove this code now.
2025-01-08 12:08:30 -05:00
Ricky e0c893f51d [assert helpers] ServerIntegration tests (#31988)
Based off: https://github.com/facebook/react/pull/31986
2025-01-06 14:13:03 -05:00
Ricky 03e4ec2d0f [assert helpers] react-dom (pt3) (#31983)
moar assert helpers

this finishes all of react-dom except the server integration tests which
are tricky to convert
2025-01-05 17:10:29 -05:00
Ricky bf883bebbc [fizz] fix empty string href double warning (#31783)
I think this is the suggested change from
https://github.com/facebook/react/pull/31765#discussion_r1884541447

But no tests fail and I'm not sure how to test it? Seems sus. 

Also seems like the `removeAttribute` here should be changed?


https://github.com/facebook/react/blob/9d9f12f2699a049777fa88914306ad4de9e2b74d/packages/react-dom-bindings/src/client/ReactDOMComponent.js#L400-L427
2025-01-03 12:53:28 -05:00
Ricky dc7578290f [assert helpers] ReactDOMFloat-test (#31901)
Splitting out ReactDOMFloat to it's own PR because it's huge.
2025-01-02 15:53:19 -05:00
Ricky 7c11aad374 [assert helpers] react-dom (pt2) (#31902)
Converts more react-dom tests
2025-01-02 15:53:06 -05:00
Ricky d8a08f8e39 [assert helpers] ReactDOMComponent-test (#31898)
Splitting out ReactDOMComponent to it's own PR because it's huge.
2025-01-02 15:28:15 -05:00
Ricky a7c898d83a [assert helpers] react-dom (pt 1) (#31897)
Converts ~half of react-dom tests
2025-01-02 15:28:06 -05:00
Ricky 26297f5383 [assert helpers] not dom or reconciler (#31862)
converts everything left outside react-dom and react-reconciler
2024-12-20 12:41:13 -05:00
David Sancho 2bd1c756c6 Ensure function arity is preserved after build (#31808)
Co-authored-by: eps1lon <sebastian.silbermann@vercel.com>
2024-12-18 14:08:56 +01:00
Sebastian Markbåge facec3ee71 [Fiber] Schedule passive effects using the regular ensureRootIsScheduled flow (#31785)
This treats workInProgressRoot work and rootWithPendingPassiveEffects
the same way. Basically as long as there's some work on the root, yield
the current task. Including passive effects. This means that passive
effects are now a continuation instead of a separate callback. This can
mean they're earlier or later than before. Later for Idle in case
there's other non-React work. Earlier for same Default if there's other
Default priority work.

This makes sense since increasing priority of the passive effects beyond
Idle doesn't really make sense for an Idle render.

However, for any given render at same priority it's more important to
complete this work than start something new.

Since we special case continuations to always yield to the browser, this
has the same effect as #31784 without implementing `requestPaint`. At
least assuming nothing else calls `requestPaint`.

<img width="587" alt="Screenshot 2024-12-14 at 5 37 37 PM"
src="https://github.com/user-attachments/assets/8641b172-8842-4191-8bf0-50cbe263a30c"
/>
2024-12-17 17:01:31 -05:00
Jack Pope 34ee3919c3 Clean up enableLazyContextPropagation (#31810)
This flag has shipped everywhere, let's clean it up.
2024-12-17 11:56:00 -05:00
Ricky e06c72fcf4 [flags] Cleanup enableCache (#31778)
This is landed everywhere
2024-12-15 12:34:08 -05:00
Ricky 2d320563f3 [flags] Delete enableDebugTracing (#31780)
This is unused, even in the one builds that uses it, and we don't plan
on landing it in this form.
2024-12-15 12:16:10 -05:00
Ricky 9e2c233139 [flags] Delete enableSuspenseAvoidThisFallbackFizz (#31779)
We're not shipping `enableSuspenseAvoidThisFallback` and the fizz flag
is already off so we can delete it.
2024-12-14 13:05:17 -05:00
Brooke 0d67cc0651 Fix commong typo in <title> multiple children error message (#31777) 2024-12-14 12:32:58 -05:00
Ricky 4996a8fa5c Remove enableFilterEmptyStringAttributesDOM (#31765)
Base off https://github.com/facebook/react/pull/31764

This has landed everywhere
2024-12-13 16:30:10 -05:00
Ricky ef63718a27 Remove enableAsyncActions (#31757)
Based on https://github.com/facebook/react/pull/31756

This is landed everywhere
2024-12-13 13:58:18 -05:00
Ricky fb12845d77 Remove disableIEWorkarounds (#31756)
Based off https://github.com/facebook/react/pull/31755

This is landed everywhere.
2024-12-13 12:26:40 -05:00
Jack Pope 17ca4b157f Fix useResourceEffect in Fizz (#31758)
We're seeing errors when testing useResourceEffect in SSR and it turns
out we're missing the noop dispatcher function on Fizz.

I tested a local build with this change and it resolved the late
mutation errors in the e2e tests.
2024-12-13 11:26:44 -05:00
Sebastian Markbåge d5e8f79cf4 [Fiber] Use hydration lanes when scheduling hydration work (#31751)
When scheduling the initial root and when using
`unstable_scheduleHydration` we should use the Hydration Lanes rather
than the raw update lane. This ensures that we're always hydrating using
a Hydration Lane or the Offscreen Lane rather than other lanes getting
some random hydration in it.

This fixes an issue where updating a root while it is still hydrating
causes it to trigger client rendering when it could just hydrate and
then apply the update on top of that.

It also fixes a potential performance issue where
`unstable_scheduleHydration` gets batched with an update that then ends
up forcing an update of a boundary that requires it to rewind to do the
hydration lane anyway. Might as well just start with the hydration
without the update applied first.

I added a kill switch (`enableHydrationLaneScheduling`) just in case but
seems very safe given that using `unstable_scheduleHydration` at all is
very rare and updating the root before the shell hydrates is extremely
rare (and used to trigger a recoverable error).
2024-12-12 23:06:07 -05:00
Andrew Clark c86542b240 Bump next prerelease version numbers (#31676)
Updates the version numbers in the prerelease (canary and experimental)
channels.

---------

Co-authored-by: Jack Pope <jackpope1@gmail.com>
2024-12-12 14:10:46 -05:00
Josh Story 16d2bbbd1f Client render dehydrated Suspense boundaries on document load (#31620)
When streaming SSR while hydrating React will wait for Suspense
boundaries to be revealed by the SSR stream before attempting to hydrate
them. The rationale here is that the Server render is likely further
ahead of whatever the client would produce so waiting to let the server
stream in the UI is preferable to retrying on the client and possibly
delaying how quickly the primary content becomes available. However If
the connection closes early (user hits stop for instance) or there is a
server error which prevents additional HTML from being delivered to the
client this can put React into a broken state where the boundary never
resolves nor errors and the hydration never retries that boundary
freezing it in it's fallback state.

Once the document has fully loaded we know there is not way any
additional Suspense boundaries can arrive. This update changes react-dom
on the client to schedule client renders for any unfinished Suspense
boundaries upon document loading.

The technique for client rendering a fallback is pretty straight
forward. When hydrating a Suspense boundary if the Document is in
'complete' readyState we interpret pending boundaries as fallback
boundaries. If the readyState is not 'complete' we register an event to
retry the boundary when the DOMContentLoaded event fires.

To test this I needed JSDOM to model readyState. We previously had a
temporary implementation of readyState for SSR streaming but I ended up
implementing this as a mock of JSDOM that implements a fake readyState
that is mutable. It starts off in 'loading' readyState and you can
advance it by mutating document.readyState. You can also reset it to
'loading'. It fires events when changing states.

This seems like the least invasive way to get closer-to-real-browser
behavior in a way that won't require remembering this subtle detail
every time you create a test that asserts Suspense resolution order.
2024-12-03 13:13:35 -08:00
Zack Tanner 63cde684f5 (chore): copy fix in <style> precedence error (#31524)
## Summary

This fixes a typo in the error that gets reported when Float errors
while hoisting a style tag that does not contain both `precedence` and
`href`. There was a typo in _conflict_ and the last part of the sentence
doesn't make sense. I assume it wasn't needed since the message already
suggests moving the style tag to the head manually.
2024-11-14 14:03:59 -08:00
Jack Pope 989af12f72 Make prerendering always non-blocking with fix (#31452)
We've previously failed to land this change due to some internal apps
seeing infinite render loops due to external store state updates during
render. It turns out that since the `renderWasConcurrent` var was moved
into the do block, the sync render triggered from the external store
check was stuck with a `RootSuspended` `exitStatus`. So this is not
unique to sibling prerendering but more generally related to how we
handle update to a sync external store during render.

We've tested this build against local repros which now render without
crashes. We will try to add a unit test to cover the scenario as well.

---------

Co-authored-by: Andrew Clark <git@andrewclark.io>
Co-authored-by: Rick Hanlon <rickhanlonii@fb.com>
2024-11-08 12:38:41 -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
Jack Pope cae764ce81 Revert "[Re-land] Make prerendering always non-blocking (#31268)" (#31355)
This reverts commit 6c4bbc7832.

It looked like the bug we found on the original land was related to
broken product code. But through landing #31268 we found additional bugs
internally. Since disabling the feature flag does not fix the bugs, we
have to revert again to unblock the sync. We can continue to debug with
our internal build.
2024-10-25 09:17:07 -07:00
Sebastian Markbåge d49123f73f Expose prerender() for SSG in stable (#31298)
When we added `renderToReadableStream` we added the `allReady` helper to
make it easier to do SSG rendering but it's kind of awkward to wire up
that way. Since we're also discouraging `renderToString` in React 19 the
cliff is kind of awkward. ([As noted by
Docusaurus.](https://github.com/facebook/react/pull/24752#issuecomment-2178309299))

The idea of the `react-dom/static` `prerender` API was that this would
be the replacement for SSG rendering. Awkwardly this entry point
actually already exists in stable but it has only `undefined` exports.

Since then we've also added other useful heuristics into the `prerender`
branch that makes this really the favored and easiest to use API for the
prerender (SSG/ISR) use case.

`prerender` is also used for Partial Prerendering but that part is still
experimental.

However, we can expose only the `prerender` API on `react-dom/static`
without it returning the `postponeState`. Instead the stream is on
`prelude`. The naming is a bit awkward if you don't consider resuming
but it's the same thing.

It's really just `renderToReadable` stream with automatic `allReady` and
better heuristics for prerendering.
2024-10-19 22:33:28 -04:00
Jack Pope 6c4bbc7832 [Re-land] Make prerendering always non-blocking (#31268)
Follows https://github.com/facebook/react/pull/31238

___

This is a partial re-land of
https://github.com/facebook/react/pull/31056. We saw breakages surface
after the original land and had to revert. Now that they've been fixed,
let's try this again. This time we'll split up the commits to give us
more control of testing and rollout internally.

Original PR: https://github.com/facebook/react/pull/31056
Original Commit:
https://github.com/facebook/react/pull/31056/commits/4c71025d8d1bd46344ad793e7ed3049d24f7395a
Revert PR: https://github.com/facebook/react/pull/31080

Commit description:

> When a synchronous update suspends, and we prerender the siblings, the
prerendering should be non-blocking so that we can immediately restart
once the data arrives.
>
> This happens automatically when there's a Suspense boundary, because
we immediately commit the boundary and then proceed to a Retry render,
which are always concurrent. When there's not a Suspense boundary, there
is no Retry, so we need to take care to switch from the synchronous work
loop to the concurrent one, to enable time slicing.

Co-authored-by: Andrew Clark <git@andrewclark.io>
2024-10-15 16:47:02 -04:00
Jack Pope d8c90fa48d Disable infinite render loop detection (#31088)
We're seeing issues with this feature internally including bugs with
sibling prerendering and errors that are difficult for developers to
action on. We'll turn off the feature for the time being until we can
improve the stability and ergonomics.

This PR does two things:
- Turn off `enableInfiniteLoopDetection` everywhere while leaving it as
a variant on www so we can do further experimentation.
- Revert https://github.com/facebook/react/pull/31061 which was a
temporary change for debugging. This brings the feature back to
baseline.
2024-10-01 11:00:57 -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
Ricky 76aee6f39d Revert "Make prerendering always non-blocking" (#31080)
Reverts facebook/react#31056
2024-09-26 16:48:57 -04:00
Andrew Clark 0f1856c49f Make prerendering always non-blocking (#31056)
When a synchronous update suspends, and we prerender the siblings, the
prerendering should be non-blocking so that we can immediately restart
once the data arrives.

This happens automatically when there's a Suspense boundary, because we
immediately commit the boundary and then proceed to a Retry render,
which are always concurrent. When there's not a Suspense boundary, there
is no Retry, so we need to take care to switch from the synchronous work
loop to the concurrent one, to enable time slicing.
2024-09-25 16:31:44 -04:00
Jack Pope f9ebd85a19 Increase nested update limit to 100 (#31061)
We're seeing the limit hit in some tests after enabling sibling
prerendering. Let's bump the limit so we can run more tests and gather
more signal on the changes. When we understand the scope of the problem
we can determine whether we need to change how the updates are counted
in prerenders and/or fix specific areas of product code.
2024-09-25 11:50:41 -04:00
ling1726 d9c4920e8b fix: restore selection should consider the window of the container (#30951)
## Summary


Fixes #30864 

Before this PR the active elemen was always taken from the global
`window`. This is incorrect if the renderer is in one window rendering
into a container element in another window. The changes in this PR adds
another code branch to use a `defaultView` of the container element if
it exists so that `restoreSelection` after a commit will actually
restore to the correct window.

## How did you test this change?

I patched these changes to the repro repo in the linked issue #39864
https://github.com/ling1726/react-child-window-focus-repro/blob/master/patches/react-dom%2B18.3.1.patch.

I followed the same repro steps in the linked issue and and could not
repro the reported problem. Attaching screen recordings below:

Before
![focus
repro](https://github.com/user-attachments/assets/81c4b4f9-08b5-4356-8251-49b909771f3f)

After

![after](https://github.com/user-attachments/assets/84883032-5558-4650-9b9a-bd4d5fd9cb13)
2024-09-13 13:29:40 -07: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
Andrew Clark d6cb4e7713 Start prerendering Suspense retries immediately (#30934)
When a component suspends and is replaced by a fallback, we should start
prerendering the fallback immediately, even before any new data is
received. During the retry, we can enter prerender mode directly if
we're sure that no new data was received since we last attempted to
render the boundary.

To do this, when completing the fallback, we leave behind a pending
retry lane on the Suspense boundary. Previously we only did this once a
promise resolved, but by assigning a lane during the complete phase, we
will know that there's speculative work to be done.

Then, upon committing the fallback, we mark the retry lane as suspended
— but only if nothing was pinged or updated in the meantime. That allows
us to immediately enter prerender mode (i.e. render without skipping any
siblings) when performing the retry.
2024-09-11 11:41:54 -04:00
Andrew Clark 66cf2cfc8a Prerender during same pass if blocked anyway (#30879)
If something suspends in the shell — i.e. we won't replace the suspended
content with a fallback — we might as well prerender the siblings during
the current render pass, instead of spawning a separate prerender pass.

This is implemented by setting the "is prerendering" flag to true
whenever we suspend in the shell. But only if we haven't already skipped
over some siblings, because if so, then we need to schedule a separate
prerender pass regardless.
2024-09-10 13:23:32 -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
Andrew Clark e10e868182 Schedule prerender after something suspends (#30800)
Adds the concept of a "prerender". These special renders are spawned
whenever something suspends (and we're not already prerendering).

The purpose is to move speculative rendering work into a separate phase
that does not block the UI from updating. For example, during a
transition, if something suspends, we should not speculatively prerender
siblings that will be replaced by a fallback in the UI until *after* the
fallback has been shown to the user.
2024-09-04 13:55:29 -04: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
Andrew Clark ee7f6757c4 Fix: Synchronous popstate transitions (#30759)
This is a refactor of the fix in #27505.

When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.

In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.

But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.

The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
2024-08-23 12:30:08 -04: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 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 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
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
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
Sebastian Markbåge 146df7c311 [Fiber] Make DevTools Config use Static Injection (#30522)
We use static dependency injection. We shouldn't use this dynamic
dependency injection we do for DevTools internals. There's also meta
programming like spreading and stuff that isn't needed.

This moves the config from `injectIntoDevTools` to the FiberConfig so it
can be statically resolved.

Closure Compiler has some trouble generating optimal code for this
anyway so ideally we'd refactor this further but at least this is better
and saves a few bytes and avoids some code paths (when minified).
2024-07-30 15:03:54 -04:00
Josh Story a451de014c [Fizz] Allow aborting during render (#30488)
Currently if you abort a Fizz render during rendering the render will
not complete correctly because there are inconsistencies with task
counting. This change updates the abort implementation to allow you to
abort from within a render itself. We already landed a similar change
for Flight in #29764
2024-07-29 13:18:15 -07:00