Commit Graph
15395 Commits
Author SHA1 Message Date
Mengdi Chen 992911981b [DevTools] add simple usage events for internal logging (#24888)
* [DevTools] add simple events for internal logging

* fix lint

* fix lint

* better event name

* fix flow

* better way to fix flow

* combine 'select-element'

* use same event name for selecting element by inspecting
2022-07-18 15:52:53 -04:00
Luna Ruan 6daf600609 add transistion callbacks to hydrateRoot (#24937)
This PR adds transition callbacks to hydrateRoot.
2022-07-18 10:22:47 -07:00
Andrew Clark 02206099af Use recursion to traverse during passive unmount phase (#24918)
This converts the layout phase to iterate over its effects recursively
instead of iteratively. This makes it easier to track contextual
information, like whether a fiber is inside a hidden tree.

We already made this change for several other phases, like mutation and
layout mount. See 481dece for more context.
2022-07-14 11:08:08 -04:00
Mengdi Chen d54880d424 React DevTools 4.24.7 -> 4.25.0 (#24919) 2022-07-13 15:57:50 -04:00
Luna Ruan f629495199 [Transition Tracing] Rename transitionCallbacks to unstable_transitionCallbacks (#24920)
Renaming transitionCallbacks to unstable_transitionCallbacks as per convention
2022-07-13 15:27:12 -04:00
Mengdi Chen 4bc83e6821 [DevTools] enable enableProfilerComponentTree flag for all builds (#24921) 2022-07-13 15:21:32 -04:00
Andrew Clark 7a4336c404 Use recursion to traverse during passive mount phase
This converts the layout phase to iterate over its effects
recursively instead of iteratively. This makes it easier to track 
contextual information, like whether a fiber is inside a hidden tree.

We already made this change for the mutation phase. See 481dece for
more context.
2022-07-12 16:06:53 -04:00
Andrew Clark bb1357b381 Wrap try-catch directly around each user function
(This is the same as f9e6aef, but for the passive mount phase rather than the
mutation phase.)

This moves the try-catch from around each fiber's passive mount phase to
direclty around each user function (effect function, callback, etc).

We already do this when unmounting because if one unmount function
errors, we still need to call all the others so they can clean up
their resources.

Previously we didn't bother to do this for anything but unmount,
because if a mount effect throws, we're going to delete that whole
tree anyway.

But now that we're switching from an iterative loop to a recursive one,
we don't want every call frame on the stack to have a try-catch, since
the error handling requires additional memory.

Wrapping every user function is a bit tedious, but it's better
for performance. Many of them already had try blocks around
them already.
2022-07-12 16:06:53 -04:00
Andrew Clark de3c069843 Move flag check into each switch case
The fiber tag is more specific than the effect flag, so we should always
refine the type of work first, to minimize redundant checks.
2022-07-12 16:06:53 -04:00
Luna Ruan f5916d15b6 [Transition Tracing][Code Cleanup] Delete Marker Name Change Tests (#24908)
We decided that changing the Tracing Marker name wasn't allowed and we would error, so this PR deletes all the tests that tested name change behavior
2022-07-12 12:59:58 -07:00
Luna Ruan fa20b319fc [Transition Tracing] Code Cleanup (#24880)
This PR cleans up some of the transition tracing code by:
* Looping through marker transitions only when we process the markerComplete callback (rather than in the commit phase) so we block for less time during commit.
* Renaming `PendingSuspenseBoundaries` to `pendingBoundaries`
* Cleaning up the callback functions
2022-07-12 12:48:04 -07:00
Luna Ruan 5e8c1961c0 [Transition Tracing] onMarkerProgress (#24861)
This PR adds support for `onMarkerProgress` (`onTransitionProgress(transitionName: string, markerName: string, startTime: number, currentTime: number, pending: Array<{name: null | string}>)`)

We call this callback when:
    * When **a child suspense boundary of the marker commits in a fallback state**. Only the suspense boundaries that are triggered and commit in a fallback state when the transition first occurs (and all subsequent suspense boundaries in the initial suspense boundary's subtree) are considered a part of the transition
    * **A child suspense boundary of the marker resolves**
   
When we call `onMarkerProgress`, we call the function with a `pending` array. This array contains the names of the transition's suspense boundaries that are still in a fallback state
2022-07-12 11:59:54 -07:00
Andrew Clark b641d02097 Use recursion to traverse during layout phase
This converts the layout phase to iterate over its effects
recursively instead of iteratively. This makes it easier to track 
contextual information, like whether a fiber is inside a hidden tree.

We already made this change for the mutation phase. See 481dece for
more context.
2022-07-12 13:27:22 -04:00
Andrew Clark a1b1e391e1 Wrap try-catch directly around each user function
(This is the same as f9e6aef, but for the layout phase rather than the
mutation phase.)

This moves the try-catch from around each fiber's layout phase to
direclty around each user function (effect function, callback, etc).

We already do this when unmounting because if one unmount function
errors, we still need to call all the others so they can clean up
their resources.

Previously we didn't bother to do this for anything but unmount,
because if a mount effect throws, we're going to delete that whole
tree anyway.

But now that we're switching from an iterative loop to a recursive one,
we don't want every call frame on the stack to have a try-catch, since
the error handling requires additional memory.

Wrapping every user function is a bit tedious, but it's better
for performance. Many of them already had try blocks around
them already.
2022-07-12 13:27:22 -04:00
Andrew Clark 3df7e8f5dc Move flag check into each switch case
The fiber tag is more specific than the effect flag, so we should always
refine the type of work first, to minimize redundant checks.
2022-07-12 13:27:22 -04:00
Andrew Clark b8c96b136d Move ref commit effects inside switch statement
Only certain fiber types can have refs attached to them, so this moves the
Ref effect logic out of the common path and into the corresponding branch
of the layout phase's switch statement.

The types of fibers this affects are host components and class components.
Function components are not affected because they can only have a ref via
useImperativeHandle, which has a different implementation. The experimental
Scope type attaches its refs in the mutation phase, not the layout phase.
2022-07-12 13:27:22 -04:00
Luna Ruan e225fa43ad [Transition Tracing] Don't call transition callbacks if no transition name specified (#24887)
This PR checks to see if `transition.name` is defined before adding the transition so we avoid doing unnecessary work for transitions without a transition name
2022-07-11 18:00:49 -04:00
Luna Ruan dd2d652275 [Transition Tracing] Tracing Marker Name Change in Update Warning (#24873)
We should only support Tracing Marker's name field during component mount. This PR adds a warning if the Tracing Marker's name changes during an update.
2022-07-08 12:31:44 -04:00
Luna Ruan 80208e7696 [Transition Tracing] Add onTransitionProgress Callback (#24833)
This PR adds support for `onTransitionProgress` (`onTransitionProgress(transitionName: string, startTime: number, currentTime: number, pending: Array<{name: null | string}>)`)

We call this callback when:
    * When **a child suspense boundary of the transition commits in a fallback state**. Only the suspense boundaries that are triggered and commit in a fallback state when the transition first occurs (and all subsequent suspense boundaries in the initial suspense boundary's subtree) are considered a part of the transition
    * **A child suspense boundary of the transition resolves**
   
When we call `onTransitionProgress`, we call the function with a `pending` array. This array contains the names of the transition's suspense boundaries that are still in a fallback state
2022-07-08 12:13:29 -04:00
Andrew Clark 30eb267abd Land forked reconciler changes (#24878)
This applies forked changes from the "new" reconciler to the "old" one.

Includes:

- 67de5e3 [FORKED] Hidden trees should capture Suspense
- 6ab05ee [FORKED] Track nearest Suspense handler on stack
- 051ac55 [FORKED] Add HiddenContext to track if subtree is hidden
2022-07-08 11:55:53 -04:00
Andrew Clark 5e4e2dae0b Defer setState callbacks until component is visible (#24872)
A class component `setState` callback should not fire if a component is inside a
hidden Offscreen tree. Instead, it should wait until the next time the component
is made visible.
2022-07-08 11:51:40 -04:00
Andrew Clark 95e22ff528 Delete Partial Renderer SSR implementation (#24868)
This removes the old server rendering implementation (the "Partial Renderer").
It was replaced in React 18 with a new streaming implementation (Fizz).

We hadn't removed it from the codebase yet because Facebook hadn't finished
rolling out Fizz in production; it's been behind a feature flag while we run
performance tests and migrate our internal infrastructure.

The diff to land Fizz will land imminently, and once it does, we can merge
this commit.
2022-07-07 16:57:42 -04:00
Luna Ruan c3b18571db [DevTools][Bugfix] Fix DevTools Perf Issue When Unmounting Large React Subtrees (#24863)
We've recently had multiple reports where, if React DevTools was installed, unmounting large React subtrees would take a huge performance hit (ex. from 50ms to 7 seconds). 

Digging in more, we realized for every fiber that unmounts, we called `untrackFibers`, which calls `clearTimeout` (and does some work manipulating a set, but this wasn't the bulk of the time). We ten call `recordUnmount`, which adds the timer back. Adding and removing the timer so many times was taking upwards of 50ms per timer add/remove call, which was resulting in exorbitant amounts of time spent in DevTools deleting subtrees.

It looks like we are calling `untrackFibers` so many times to avoid a race condition with Suspense children where we unmount them twice (first a "virtual" unmount when the suspense boundary is toggled from visible to invisible, and then an actual unmount when the new children are rendered) without modifying `fiberIDMap`. We can fix this race condition by using the `untrackFibersSet` as a lock and not calling `recordUnmount` if the fiber is in the set and hasn't been processed yet. This works because the only way fibers are added in the set is via `recordUnmount` anyway.

This PR also adds a test to make sure this change doesn't regress the previous behavior.

**Before**
![image](https://user-images.githubusercontent.com/2735514/177655428-774ee306-0568-49ce-987e-b5213b613265.png)

**After**
![image](https://user-images.githubusercontent.com/2735514/177655604-a217583f-787e-438e-b6f9-18953fe32444.png)
2022-07-07 10:43:25 -04:00
Luna Ruan 8e35b50608 [Transition Tracing] Refactor Code to Remove OffscreeInstance TODOs (#24855)
Refactored code to pass flow and remove TODOs introduced in #24846
2022-07-06 09:38:28 -04:00
Luna Ruan deab1263a8 [Transition Tracing] Change Transition Type Passed Pending Transitions (#24856)
This PR changes the type of the object we store in the pending transitions callbacks map. Previously, we were recreating the transition object that we initially created during `startTransition`. However, we can actually reuse the object instead (and it also gives us a stable way to identify a transition). This PR changes the implementation to reuse the transition object instead of creating a new one
2022-07-06 09:37:46 -04:00
Andrew Clark 82e9e99098 Suspending inside a hidden tree should not cause fallbacks to appear (#24699)
* [FORKED] Hidden trees should capture Suspense

If something suspends inside a hidden tree, it should not affect
anything in the visible part of the UI. This means that Offscreen acts
like a Suspense boundary whenever it's in its hidden state.

* Add previous commit to forked revisions
2022-07-05 17:51:27 -04:00
Andrew Clark c1f5884ffe Add missing null checks to OffscreenInstance code (#24846)
`stateNode` is any-typed, so when reading from `stateNode` we should always cast
it to the specific type for that type of work. I noticed a place in the commit
phase where OffscreenInstance wasn't being cast. When I added the type
assertion, it exposed some type errors where nullable values were being accessed
without first being refined.

I added the required null checks without verifying the logic of the existing
code. If the existing logic was correct, then the extra null checks won't have
any affect on the behavior, because all they do is refine from a nullable type
to a non-nullable type in places where the type was assumed to already be
non-nullable. But the result looks a bit fishy to me, so I also left behind some
TODOs to follow up and verify it's correct.
2022-07-05 11:40:44 -04:00
Luna Ruan 4cd788aef0 Revert "Revert [Transition Tracing] Refactor Transition Tracing Root Code" (#24830)
* refactor root

* old

* Add comments and push actual marker instance in pushMarkerInstance

* old

* refactor pushRootMarkerInstance

* old

* fix test
2022-06-30 13:16:08 -04:00
Andrew Clark e61fd91f5c Revert "[Transition Tracing] Refactor Transition Tracing Root Code (#24766)" (#24829)
This reverts commit 401296310f because it's
failing on main, likely due to conflict with something that landed before the
PR was merged. Need to rebase and fix.
2022-06-30 11:48:25 -04:00
Luna Ruan 401296310f [Transition Tracing] Refactor Transition Tracing Root Code (#24766)
This PR refactors the transition tracing root code by reusing the tracing marker code. Namely it:
* Refactors the tracing marker code so that it takes a tracing marker instance instead of a tracing marker fiber and rename the stack to `markerInstance` instead of `tracingMarker`
* Pushes the root code onto the stack
* Moves the instantiation of `root.incompleteTransitions` to the begin phase when we are pushing the root to the stack rather than in the commit phase
2022-06-30 08:16:32 -07:00
Andrew Clark 1859329021 Track nearest Suspense handler on stack (#24585)
* [FORKED] Add HiddenContext to track if subtree is hidden

This adds a new stack cursor for tracking whether we're rendering inside
a subtree that's currently hidden.

This corresponds to the same place where we're already tracking the
"base lanes" needed to reveal a hidden subtree — that is, when going
from hidden -> visible, the base lanes are the ones that we skipped
over when we deferred the subtree. We must includes all the base lanes
and their updates in order to avoid an inconsistency with the
surrounding content that already committed.

I consolidated the base lanes logic and the hidden logic into the same
set of push/pop calls.

This is intended to replace the InvisibleParentContext that is currently
part of SuspenseContext, but I haven't done that part yet.

* Add previous commit to forked revisions

* [FORKED] Track nearest Suspense handler on stack

Instead of traversing the return path whenever something suspends to
find the nearest Suspense boundary, we can push the Suspense boundary
onto the stack before entering its subtree. This doesn't affect the
overall algorithm that much, but because we already do all the same
logic in the begin phase, we can save some redundant work by tracking
that information on the stack instead of recomputing it every time.

* Add previous commit to forked revisions
2022-06-30 10:03:29 -04:00
Andrew Clark a7b192e0f1 Add test gate alias for Offscreen (#24749)
Offscreen is only enabled in the www and experimental channels. Instead
of listing these on every Offscreen test, I added a test gate alias
called `enableOffscreen`. Makes it easier to grep for these, and edit or
remove the channels later.
2022-06-30 09:44:54 -04:00
Andrew Clark 6b6cf8311c Land forked reconciler changes (#24817)
This applies forked changes from the "new" reconciler to the "old" one.

Includes:

- d410f0a [FORKED] Bugfix: Offscreen instance is null during setState
- 58bb117 [FORKED] Check for infinite update loops even if unmounted
- 31882b5 [FORKED] Bugfix: Revealing a hidden update
- 17691ac [FORKED] Don't update childLanes until after current render
2022-06-29 23:31:42 -04:00
Luna Ruan 4e1fcfa771 [DevTools] Resign Timeline Profiler Sidebar (#24816)
This PR:
* Redesigned the sidebar to resemble the flamegraph profiler sidebar and added title and timestamp to the sidebar
* Added ability to copy the component stack (for places where you're unable to link to source)

https://user-images.githubusercontent.com/2735514/176564897-5301d6d4-429a-4ea3-86cd-74427cff4ce6.mov
2022-06-29 17:54:06 -07:00
Luna Ruan 1974d08c93 [DevTools] Fix Bugs With Component Stacks (#24815)
This PR:
* Simplifies the code in `SidebarEventInfo` by passing it the actual clicked event rather than an index.
* Lightly refactored the `SidebarEventInfo` code so that it can be used for more than just `schedulingEvents`
* Fixes bug. Previously, whenever a state update event was clicked, we updated the `selectedCommitIndex` in the `ProfilerContext`. However, this index is used for the selected commit in the Flamegraph profiler, which caused a bug where if you would change the contents of the event sidebar, the commit sidebar in the Flamegraph profiler would change too. This PR replaces this with the actual event info instead
2022-06-29 16:00:48 -07:00
Luna Ruan cd80d3274d [DevTools] Add column number to viewSourceLineFunction (#24814)
Add column number for `viewSourceLineFunction` and renamed the function to `viewUrlSourceFunction` to match the other source function naming conventions
2022-06-29 10:38:27 -07:00
Mengdi Chen f01e119b7d [DevTools] Log page URL in internal build (#24799)
* test log

* fix attribute name

* fix lint

* tabs can be empty

* improve coding style per comments
2022-06-29 13:02:53 -04:00
Luna Ruan d1432ba93e [Transition Tracing] Fix excess calls to the transition start callback (#24806)
This PR fixes a bug where we would add a transition to the lanes map every time an update occurs. However, we didn't factor in that there might be multiple updates in a transition, which would cause the transition to be added multiple times to the transitionLanes map.

This changes the transitionLanes object from an Array of Arrays to an Array of Sets so that we only add a transition if it hasn't been added before, avoiding duplicates
2022-06-28 21:17:14 -04:00
Blake Friedman 2e1c8841e9 [DevTools] front-end for profiling event stack (#24805)
* [DevTools] front-end for profiling event stack

Adds a side-bar to the profiling tab. Users can now select an update event, and are
shown the callstack from the originating component. When a source path is available
there is now UI to jump to source.

Add FB enabled feature flag: enableProfilerComponentTree for the side-bar.

resolves #24170
2022-06-28 22:15:24 +01:00
Luna Ruan 88574c1b8b Fix enableTransitionTracing flag (#24801)
Move `enableTransitionTracing` to `dynamicFeatureFlags` so it runs when you run `yarn test`
2022-06-28 13:09:59 -04:00
Luna Ruan a4bed46969 [Transition Tracing] Add Tracing Markers (#24686)
This PR adds support for Tracing Markers as well as onTracingMarkerComplete
2022-06-27 09:46:43 -07:00
Josh Story 167853026c fix hydration warning suppression in text comparisons (#24784)
* fix hydration warning suppression in text comparisons

* lint

* lowercase test
2022-06-26 12:22:10 -07:00
Andrew Clark 652e6c5a1b [sizebot] Add link to diff view (#24790)
Updates the sizebot output so that the file names link to a diff view of
the corresponding build artifact.

Example diff view: https://react-builds.vercel.app/commits/955cad9bcc6d755b2a672f8038fe9754e0fe5108/files/oss-stable-semver/react-dom/cjs/react-dom.production.min.js?compare=c3d7a7e3d72937443ef75b7e29335c98ad0f1424

The diff view itself is rendered by a Next.js app that I built as a side
project and is hosted at https://react-builds.vercel.app. If we find
this useful enough I could move the app to a React-owned repo but since
this isn't a critical feature it might be OK to leave it separate for
now, so we don't need to commit to supporting it indefinitely.
2022-06-25 19:13:41 -04:00
Luna Ruan 955cad9bcc [DevTools] Clean Up DevTools Code (#24782)
This PR cleans up the DevTools codebase by:
* Consolidating `normalizeCodeLocInfo` into one place
* Remove unused source argument in the DevTools component stacks code
2022-06-23 15:47:47 -07:00
Luna RuanandBlake Friedman 9abe745aa7 [DevTools][Timeline Profiler] Component Stacks Backend (#24776)
This PR adds a component stack field to the `schedule-state-update` event. The algorithm is as follows:
* During profiling, whenever a state update happens collect the parents of the fiber that caused the state update and store it in a map
* After profiling finishes, post process the `schedule-state-update` event and using the parent fibers, generate the component stack by using`describeFiber`, a function that uses error throwing to get the location of the component by calling the component without props.

---

Co-authored-by: Blake Friedman <blake.friedman@gmail.com>
2022-06-23 11:19:23 -07:00
Luna Ruan cf665c4b73 [DevTools] Refactor incompleteTransitions field from Root Fiber memoized state to FiberRoot (#24765)
`incompleteTransitions` persists across renders, so it should be part of the `fiber.stateNode` (ie FiberRoot) rather than `fiber.memoizedState`
2022-06-20 17:08:54 -07:00
Mengdi Chen d6255f0ac4 [DevTool] fix build-for-devtools script (#24764) 2022-06-20 15:06:40 -04:00
Sebastian Markbåge 56389e81ff Abort Flight (#24754)
Add aborting to the Flight Server. This encodes the reason as an "error"
row that gets thrown client side. These are still exposed in prod which
is a follow up we'll still have to do to encode them as digests instead.

The error is encoded once and then referenced by each row that needs to
be updated.
2022-06-19 11:05:41 -04:00
Sebastian Markbåge 0f216ae31d Add entry points for "static" server rendering passes (#24752)
This will be used to add optimizations for static server rendering.
2022-06-18 22:34:31 -04:00
Sebastian Markbåge f796fa13ad Rename Segment to Task in Flight (#24753)
In Fizz this got split into Task and Segment. We don't have a concept of
Segment in Flight yet because we don't inline multiple segments into one
"Row". We just emit one "Row" for each Segment if something suspends.

This makes Flight non-deterministic atm but that's something we'll want to
address.

Regardless, right now, this is more like a Task than a Segment.
2022-06-18 15:02:11 -04:00