Commit Graph
15395 Commits
Author SHA1 Message Date
Brian Vaughn 27bf6f9a83 Scheduling profiler UX changes (#21990) 2021-08-02 09:23:48 -04:00
Juan b537247678 New devtools test for named hooks verifying case when hooks are used indirectly (#21996)
## Summary
Adds a new unit test to `parseHookNames-test` which verifies that we correctly give names to hooks when they are used indirectly: 

e.g.
```
  const countState = useState(0);
  const count = countState[0];
  const setCount = countState[1];
``` 

Should produce `count` as the name.

## Test plan

```
yarn test
yarn test-build-devtools
yarn test-build-devtools parseHookNames
```
2021-07-30 17:10:46 -04:00
Andrew Clark f0d354efc6 [Fabric] Fix reparenting bug in legacy Suspense mount (#21995)
* Add reparenting invariant to React Noop

Fabric does not allow nodes to be reparented, so I added the equivalent
invariant to React Noop's so we can catch regressions.

This causes some tests to fail, which I'll fix in the next step.

* Fix: Use getOffscreenContainerProps

The type of these props is different per renderer. An oversight
from #21960. Unfortunately wasn't caught by Flow because fiber props
are `any`-typed.

* [Fabric] Fix reparenting in legacy Suspense mount

Fixes a weird case during legacy Suspense mount where the offscreen host
container of a tree that suspends during initial mount is recreated
instead of cloned, since there's no current fiber to clone from.

Fabric considers this a reparent even though the parent from the first
pass never committed.

Instead we can override the props from the first pass before the
container completes. It's a bit of a hack, but no more so than the rest
of the legacy root Suspense implementation — the hacks are designed
to make it usable by non-strict mode-compliant trees.
2021-07-30 12:47:40 -07:00
Shubham PandeyandShubham Pandey 6f3fcbd6fa Some remaining instances of master to main (#21982)
Co-authored-by: Shubham Pandey <shubham.pandey@mfine.co>
2021-07-30 08:56:55 -04:00
Andrew Clark 34308b5ada Tidy up early bailout logic at start of begin phase (#21852)
* Extract early bailout to separate function

This block is getting hard to read so I moved it to a separate function.
I'm about to refactor the logic that wraps around this path.

Ideally this early bailout path would happen before the begin phase
phase. Perhaps during reconcilation of the parent fiber's children.

* Extract state and context check to separate function

The only reason we pass `updateLanes` to some begin functions is to
check if we can perform an early bail out. But this is also available
as `current.lanes`, so we can read it from there instead.

I think the only reason we didn't do it this way originally is because
components that have two phases — error and Suspense boundaries —
use `workInProgress.lanes` to prevent a bail out, since during the
initial render there is no `current`. But we can check the `DidCapture`
flag instead, which we use elsewhere to detect the second phase.
2021-07-29 06:59:59 -07:00
Brian Vaughn d9dd96530f Added testing instructions to devtools contributing guide 2021-07-28 19:05:01 -04:00
Piotr Szulc 9f88b5355b Devtools: Display as link if value is in specified protocols (#21964) 2021-07-28 09:29:13 -04:00
Sebastian Markbåge 321087d134 [Fizz] Don't add aborted segments to the completedSegments list (#21976)
* Don't add aborted segments to the completedSegments list

* Update error message to include aborted status
2021-07-27 21:53:37 -04:00
Brian Vaughn cdccdbe171 Display warnings in tooltips for native events that render sync updates (#21975) 2021-07-27 17:22:44 -04:00
Brian Vaughn d95434082f Scheduling profiler: UX tweaks (#21971) 2021-07-27 14:34:05 -04:00
Brian Vaughn 87239321b0 Sceduling profiler: Added custom view cursors (#21970) 2021-07-27 12:23:01 -04:00
Timothy Yung 4cc8ec64c2 Separate unit tests for ReactFabricHostComponent (#21969) 2021-07-26 23:45:26 -07:00
Timothy Yung d4d7864934 Fix ReactFabricHostComponent methods if detached (#21967) 2021-07-26 21:02:06 -07:00
Brian Vaughn c21e8fccad Scheduling profiler: Improve native events UI (#21966)
Also highlight events that have synchronous updates inside of them. (We may want to relax this highlighting later to not warn about event handlers that are still fast enough.)
2021-07-26 19:30:43 -04:00
Andrew Clark 392253a774 [Fabric] Use container node to toggle the visibility of Offscreen and Suspense trees (#21960)
* Fix type of Offscreen props argument

Fixes an oversight from a previous refactor. The fiber that wraps
a Suspense component's children used to be a Fragment but now it's on
Offscreen fiber, so its props type has changed. There's a special
hydration path where I forgot to update this. This isn't observable
because we don't ever end up rendering this particular fiber (because
the Suspense boundary is in its fallback state) but we should fix it
anyway to avoid a potential regression in the future.

* Extract createOffscreenFromFiber logic

...into a new method called `createWorkInProgressOffscreenFiber`. Just
for symmetry with `updateWorkInProgressOffscreenFiber`. Doesn't change
any behavior.

* [Fabric] Use container node to hide/show tree

This changes how we hide and show the contents of Offscreen boundaries
in the React Fabric renderer (persistent mode), and also Suspense
boundaries which use the same feature.=

The way it used to work was that when a boundary is hidden, in the
complete phase, instead of calling the normal `cloneInstance` method
inside `appendAllChildren`, we would call a forked method called
`cloneHiddenInstance` for each of the nearest host nodes within the
subtree. This design was largely based on how it works in React DOM
(mutation mode), where instead of cloning the nearest host nodes, we
mutate their `style.display` property.

The motivation for doing it this way in React DOM was because there's no
built-in browser API for hiding a collection of DOM nodes without
affecting their layout.

In Fabric, however, there is no such limitation, so we can instead wrap
in an extra host node and apply a hidden style.

The immediate motivation for this change is that Fabric on Android has a
view pooling mechanism for instances that relies on the assumption that
a current Fiber that is cloned and replaced by a new Fiber will never
appear in a future commit. When this assumption is broken, it may cause
crashes. In the current implementation, that can indeed happen when a
node that was previously hidden is toggled back to visible. Although
this change sidesteps the issue, we may introduce in other features in
the future that would benefit from being able to revert back to an older
node without cloning it again, such as animations.

The way I've implemented this is to insert an additional HostComponent
fiber as the child of each OffscreenComponent. The extra fiber is not
ideal — the way I'd prefer to do it is to attach the host instance to
the OffscreenComponent. However, the native Fabric implementation
currently expects a 1:1 correspondence between HostComponents and host
instances, so I've deferred that optimization to a future PR to derisk
fixing the Fabric pooling crash. I left a TODO in the host config with a
description of the remaining steps, but this alone should be sufficient
to unblock.
2021-07-26 13:17:08 -07:00
Andrew Clark 419cc9c379 Fix: Hide new/updated nodes in already hidden tree (#21929)
When a new node is added to an already hidden Offscreen tree, we need
to schedule a visibility effect to hide it. Previously we would only
hide when the boundary initially switches from visible to hidden, which
meant that newly inserted nodes would be visible.

We need to do the same thing for nodes that are updated, because the
update might affect the DOM node's `style.display` property.

The implementation is to check the `subtreeFlags` for an Insertion or
Update effect.

This only affects Offscreen, not Suspense, because Suspense boundaries
cannot be updated while in their fallback (hidden) state.

And it only affects mutation mode, because in persistent mode we
implement hiding by cloning the host tree during the complete phase,
which already happens on every update.
2021-07-26 08:18:55 -07:00
Brian Vaughn b1811ebf01 [DevTools] Add native events to the scheduling profiler (#21947) 2021-07-26 10:36:16 -04:00
Brian Vaughn 4758e4533e React Native: Export getInspectorDataForInstance API (#21572)
This PR exports a new top-level API, getInspectorDataForInstance, for React Native (both development and production). Although this change adds a new export to the DEV bundle, it only impacts the production bundle for internal builds (not what's published to NPM).
2021-07-26 09:56:59 -04:00
Brian Vaughn c76e4dbbc1 Removed an accidental console.log from DevTools source code 2021-07-22 16:11:37 -04:00
Brian Vaughn f4161c3ec7 [DRAFT] Import scheduling profiler into DevTools Profiler (#21897) 2021-07-22 13:58:57 -04:00
Andrew Clark ae5d26154b Fix: LegacyHidden should not toggle effects (#21928)
LegacyHidden is a transitional API that we added to replace the old
`<div hidden={true} />` API that we used to use for pre-rendering. The
plan is to replace this with the Offscreen component, once it's ready.

The idea is that LegacyHidden has identical behavior to Offscreen except
that it doesn't change the behavior of effects. (Which is basically how
`<div hidden={true} />` worked — it prerendered the hidden content in
the background, but nothing else.) That way, while we're rolling this
out, we could toggle the feature behind a feature flag either for
performance testing or as a kill switch.

It looks like we accidentally enabled the effects flag for both
Offscreen _and_ LegacyHidden. I suppose it's a good thing that nobody
has complained yet, since we eventually do want to ship this
behavior everywhere?

But I do think we should remove it from LegacyHidden, and roll it out by
gating the component type in the downstream repo. That way if there's an
issue related to the use of LegacyHidden, we can disable that without
disabling the behavior for Suspense boundaries.

In retrospect, I might have implemented this as an unstable prop on
Offscreen instead of a completely separate type — though at the time,
Offscreen didn't exist. I originally added LegacyHidden to unblock the
Lanes refactor, so I could move the deprioritization logic out of the
HostComponent implementation.

Not a big deal since we're going to remove this soon. The implementation
is almost the same regardless: before disconnecting or reconnecting
the effects, check the fiber tag. The rest of the logic is the same.
2021-07-21 10:34:08 -07:00
Lucas Correia 25f09e3e4e DevTools: Parse named source AST in a worker (#21902)
Resolves #21855

Ended up using workerize in order to setup the worker once it allows easy imports (for babel's parse function) and exports.
2021-07-21 12:16:08 -04:00
Andrew Clark 9ab90de602 Clean-up: Move Offscreen logic from Suspense fiber (#21925)
Much of the visibility-toggling logic is shared between the Suspense and
Offscreen types, but there is some duplicated code that exists in both.
Specifically, when a Suspense fiber's state switches from suspended to
resolved, we schedule an effect on the parent Suspense fiber, rather
than the inner Offscreen fiber. Then in the commit phase, the Suspense
fiber is responsible for committing the visibility effect on Offscreen.

There two main reasons we implemented it this way, neither of which
apply any more:

- The inner Offscreen fiber that wraps around the Suspense children used
  to be conditionally added only when the boundary was in its fallback
  state. So when toggling back to visible, there was no inner fiber to
  handle the visibility effect. This is no longer the case — the
  primary children are always wrapped in an Offscreen fiber.
- When the Suspense fiber is in its fallback state, the inner Offscreen
  fiber does not have a complete phase, because we bail out of
  rendering that tree. In the old effects list implementation, that
  meant the Offscreen fiber did not get added to the effect list, so
  it didn't have a commit phase. In the new recursive effects
  implementation, there's no list to maintain. Marking a flag on the
  inner fiber is sufficient to schedule a commit effect.

Given that these are no relevant, I was able to remove a lot of old
code and shift more of the logic out of the Suspense implementation
and into the Offscreen implementation so that it is shared by both.
(Being able to share the implementaiton like this was in fact one of
the reasons we stopped conditionally removing the inner
Offscreen fiber.)

As a bonus, this happens to fix a TODO in the Offscreen implementation
for persistent (Fabric) mode, where newly inserted nodes inside an
already hidden tree must also be hidden. Though we'll still need to
make this work in mutation (DOM) mode, too.
2021-07-20 16:05:16 -07:00
Andrew Clark 5c6543771b Fix global reference to Promise (#21926)
Referencing Promise without a type check will throw in environments
where Promise is not defined.

We will follow up with a lint rule that restricts access to all globals
except in dedicated module indirections.
2021-07-20 15:39:57 -07:00
Deniz Susman 3f62dec84a Typo fix (#21729)
emitted instead of emmitted
2021-07-19 17:19:52 -04:00
Ricky 5579f1dc87 Update test comments with explanations (#21857) 2021-07-19 15:07:38 -04:00
Christian Schulze 9b76d2d7b3 react-devtools: set icon on macos (#21908) 2021-07-19 10:26:41 -04:00
Andrew Clark 262ff7ad2c Refactor "disappear" logic into its own traversal (#21901)
Similar to #21898, but for "disappear" logic. Previously this lived
inside `hideOrUnhideAllChildren`, the function that mutates the nearest
DOM nodes to override their `display` style.

This makes the feature work in persistent mode (Fabric); it didn't
before because `hideOrUnhideAllChildren` only runs in mutation mode.
2021-07-16 15:58:11 -07:00
Andrew Clark 34600f4fad Refactor "reappear" logic into its own traversal (#21898)
When a Suspense boundary switches to its fallback state — or similarly,
when an Offscreen boundary switches from visible to hidden — we unmount
all its layout effects. When it resolves — or when Offscreen switches
back to visible — we mount them again. This "reappearing" logic
currently happens in the same commit phase traversal where we perform
normal layout effects.

I've changed it so that the "reappear" logic happens in its own
recurisve traversal that is separate from the commit phase one.

In the next step, I will do the same for the "disappear" logic that
currently lives in the `hideOrUnhideAllChildren` function.

There are a few reasons to model it this way, related to future
Offscreen features that we have planned. For example, we intend to
provide an imperative API to "appear" and "reappear" all the effects
within an Offscreen boundary. This API would be called from outside the
commit phase, during an arbitrary event. Which means it can't rely on
the regular commit phase — it's not part of a commit. This isn't the
only motivation but it illustrates why the separation makes sense.
2021-07-16 15:05:39 -07:00
Ricky 310187264d Clean up flushSync flow types (#21887) 2021-07-16 10:37:57 -04:00
Brian Vaughn d0ec283819 DevTools 4.13.5 -> 4.14.0 2021-07-16 00:25:01 -04:00
Brian Vaughn 6840c98c32 Remove named hooks feature flag (#21894) 2021-07-16 00:14:20 -04:00
Brian Vaughn e26cb8f86d Clear named hooks Suspense and AST cache after a Fast Refresh (#21891) 2021-07-15 23:39:30 -04:00
Ricky 682bbd0e72 Cache local reference to global Promise (#21886) 2021-07-15 12:39:56 -04:00
houssemchebeb d5de45820a Fix typo (#21671) 2021-07-14 20:42:54 -04:00
Steve RubinandBrian Vaughn 232c67e911 Devtools Profiler: allow user to enter commit number (#19957)
Co-authored-by: Brian Vaughn <bvaughn@fb.com>
2021-07-14 20:37:02 -04:00
Brian Vaughn 87b3ada89d DevTools: Named hooks supports "cheap-module-source-map" (#21874)
"cheap-module-source-map" is the default source-map generation mode used in created-react-dev mode because of speed. The major trade-off is that the source maps generated don't contain column numbers, so DevTools needs to be more lenient when matching AST nodes in this mode.

In this case, it can ignore column numbers and match nodes using line numbers only– so long as only a single node matches. If more than one match is found, treat it the same as if none were found, and fall back to no name.
2021-07-14 14:37:27 -04:00
Andrew ClarkandBrian Vaughn a97b5ac078 [Bugfix] Don't hide/unhide unless visibility changes (#21875)
* Use Visibility flag to schedule a hide/show effect

Instead of the Update flag, which is also used for other side-effects,
like refs.

I originally added the Visibility flag for this purpose in #20043 but
it got reverted last winter when we were bisecting the effects refactor.

* Added failing test case

Co-authored-by: Brian Vaughn <bvaughn@fb.com>
2021-07-14 10:37:10 -07:00
Andrew Clark f0efb7b70f Add comment support to @gate pragma (#21881)
So you can more easily comment on why a test is gated.
2021-07-14 10:36:24 -07:00
Andrew Clark 81346764bb Run persistent tests in more configurations in CI (#21880)
I noticed that `enableSuspenseLayoutEffectSemantics` is not fully
implemented in persistent mode. I believe this was an oversight
because we don't have a CI job that runs tests in persistent mode and
with experimental flags enabled.

This adds additional test configurations to the CI job so we don't miss
stuff like this again. It doesn't fix the failing tests — I'll address
that separately.
2021-07-14 08:40:20 -07:00
Sebastian Silbermann 9090257e6e fix: restore execution context after RetryAfterError completed (#21766)
* test: Add failing test due to executionContext not being restored

* fix: restore execution context after RetryAfterError completed

* Poke codesandbox/ci

* Completely restore executionContext

* expect a specific error
2021-07-13 22:38:25 +01:00
Brian Vaughn 9fec3f2add DevTools: Ignore multiple sourceMappingUrls for external source maps (#21871)
Added an edge case regression test and bugfix.
2021-07-13 16:39:29 -04:00
Ricky 14bac6193a Allow components to render undefined (#21869) 2021-07-13 15:48:11 -04:00
Brian Vaughn 87b67d319f Enable scheduling profiler flag for react-dom profiling builds (#21867) 2021-07-13 13:41:19 -04:00
Brian Vaughn 64bbd7a7f1 Adjust Error stack columns numbers by 1 (#21865)
To account for differences between error stacks (1-based) and ASTs (0-based). In practice this change should not make an observable difference.
2021-07-13 13:28:01 -04:00
Ehsan HosseiniandEhsan Hosseini 464f275724 Update link to flow (#21862)
`main` branch does not exist in the `flow` project and it is `master`.

Co-authored-by: Ehsan Hosseini <53467610+dh-hosseini@users.noreply.github.com>
2021-07-13 10:55:54 -04:00
Ehsan Hosseini b03293faaa Fix link to fbjs (#21863)
`fbjs` doesn't have the `main` branch and it is `master`
2021-07-13 10:55:33 -04:00
Dan Abramov 9f5224a9c6 Restore DevTools console message (#21864) 2021-07-13 15:41:51 +01:00
Andrew Clark a4ecd85e86 act: Batch updates, even in legacy roots (#21797)
In legacy roots, if an update originates outside of `batchedUpdates`,
check if it's inside an `act` scope; if so, treat it as if it were
batched. This is only necessary in legacy roots because in concurrent
roots, updates are batched by default.

With this change, the Test Utils and Test Renderer versions of `act` are
nothing more than aliases of the isomorphic API (still not exposed, but
will likely be the recommended API that replaces the others).
2021-07-12 17:15:20 -07:00
Ricky c2c6ea1fde Capture suspense boundaries with undefined fallbacks (#21854) 2021-07-12 14:50:33 -04:00