Commit Graph
13533 Commits
Author SHA1 Message Date
Andrew ClarkandGitHub 77cec19bd2 Replace SuspenseConfig object with an integer (#19706)
Now that the options in SuspenseConfig are no longer supported, the
only thing we use it for is to track whether an update is part of
a transition.

I've renamed `ReactCurrentBatchConfig.suspense` to
`ReactCurrentBatchConfig.transition`, and changed the type to a number.
The number is always either 0 or 1. I could have made it a boolean;
however, most likely this will eventually be either a Lane or an
incrementing identifier.

The `withSuspenseConfig` export still exists until we've removed
all the callers from www.
2020-08-28 10:52:56 -07:00
Dan AbramovandGitHub 60df75519c Enable eager listeners in open source (#19716)
* Enable eager listeners in open source

* Fix tests

* Enable in all places
2020-08-28 12:23:28 +01:00
Dan AbramovandGitHub d30285cbc9 [Flight] Support more element types and Hooks for Server and Hybrid Components (#19711)
* Shim support for more element types

* Shim commonly used Hooks that are safe

* Flow

* Oopsie
2020-08-27 20:19:13 +01:00
Andrew ClarkandGitHub 4d9ff42fcc Clean up timeoutMs-related implementation details (#19704)
* Disable busyDelayMs and busyMinDurationMs

Refer to explanation in previous commit.

* Remove unnecessary work loop variables

Since we no longer support SuspenseConfig options, we don't need to
track these values.

* Remove unnecessary Update fields
2020-08-27 09:47:58 -07:00
Andrew ClarkandGitHub ca3afc5cdc Disable timeoutMs argument (#19703)
* Remove distinction between long, short transitions

We're removing the `timeoutMs` option, so there's no longer any
distinction between "short" and "long" transitions. They're all treated
the same.

This commit doesn't remove `timeoutMs` yet, only combines the internal
priority levels.

* Disable `timeoutMs` argument

tl;dr
-----

- We're removing the `timeoutMs` argument from `useTransition`.
- Transitions will either immediately switch to a skeleton/placeholder
  view (when loading new content) or wait indefinitely until the data
  resolves (when refreshing stale content).
- This commit disables the `timeoutMS` so that the API has the desired
  semantics. It doesn't yet update the types or migrate all the test
  callers. I'll do those steps in follow-up PRs.

Motivation
----------

Currently, transitions initiated by `startTransition` / `useTransition`
accept a `timeoutMs` option. You can use this to control the maximum
amount of time that a transition is allowed to delay before we give up
and show a placeholder.

What we've discovered is that, in practice, every transition falls into
one of two categories: a **load** or a **refresh**:

- **Loading a new screen**: show the next screen as soon as possible,
  even if the data hasn't finished loading. Use a skeleton/placeholder
  UI to show progress.
- **Refreshing a screen that's already visible**: keep showing the
  current screen indefinitely, for as long as it takes to load the fresh
  data, even if the current data is stale. Use a pending state (and
  maybe a busy indicator) to show progress.

In other words, transitions should either *delay indefinitely* (for a
refresh) or they should show a placeholder *instantly* (for a load).
There's not much use for transitions that are delayed for a
small-but-noticeable amount of time.

So, the plan is to remove the `timeoutMs` option. Instead, we'll assign
an effective timeout of `0` for loads, and `Infinity` for refreshes.

The mechanism for distinguishing a load from a refresh already exists in
the current model. If a component suspends, and the nearest Suspense
boundary hasn't already mounted, we treat that as a load, because
there's nothing on the screen. However, if the nearest boundary is
mounted, we treat that as a refresh, since it's already showing content.

If you need to fix a transition to be treated as a load instead of a
refresh, or vice versa, the solution will involve rearranging the
location of your Suspense boundaries. It may also involve adding a key.

We're still working on proper documentation for these patterns. In the
meantime, please reach out to us if you run into problems that you're
unsure how to fix.

We will remove `timeoutMs` from `useDeferredValue`, too, and apply the
same load versus refresh semantics to the update that spawns the
deferred value.

Note that there are other types of delays that are not related to
transitions; for example, we will still throttle the appearance of
nested placeholders (we refer to this as the placeholder "train model"),
and we may still apply a Just Noticeable Difference heuristic (JND) in
some cases. These aren't going anywhere. (Well, the JND heuristic might
but for different reasons than those discussed above.)
2020-08-26 14:35:13 -07:00
Ben PernickandGitHub b1abeba70d Add SuspenseList to devTools (#19684)
* ensure getDisplayName is only called on functions

* add SuspenseList to Dev tools element names

* Add SuspenseList and pass tests

* Import SuspenseList directly

* run prettier

* Refactor tests to use real components

* run linter
2020-08-26 18:04:43 +01:00
RickyandGitHub 307e078b06 Add React.startTransition (#19696)
* Add React.startTransition

* Export startTransition from index.js as well
2020-08-26 11:34:17 -04:00
inottnandGitHub 712e25aada Remove unused argument from finishConcurrentRender (#19689) 2020-08-25 13:49:57 +01:00
Andrew ClarkandGitHub 61dc55487e Lint rule to forbid access of cross-fork fields (#19679)
* Lint rule to forbid access of cross-fork fields

We use a shared Fiber type for both reconciler forks (old and new). It
is a superset of all the fields used by both forks. However, there are
some fields that should only be used in the new fork, and others that
should only be used in the old fork.

Ideally we would enforce this with separate Flow types for each fork.
The problem is that the Fiber type is accessed by some packages outside
the reconciler (like React DOM), and get passed into the reconciler as
arguments. So there's no way to fork the Fiber type without also forking
the packages where they are used. FiberRoot has the same issue.

Instead, I've added a lint rule that forbids cross-fork access of
fork-specific fields. Fields that end in `_old` or `_new` are forbidden
from being used inside the new or old fork respectively. Or you can
specific custom fields using the ESLint plugin options.

I used this plugin to find and remove references to the effect list
in 36ff116.

* Mark effect list fields as old

And `subtreeTag` as new.

I didn't mark `lastEffect` because that name is also used by the
Hook type. Not super important; could rename to `lastEffect_old` but
idk if it's worth the effort.
2020-08-24 10:07:11 -07:00
d13433c2fe Attach Listeners Eagerly to Roots and Portal Containers (#19659)
* Failing test for #19608

* Attach Listeners Eagerly to Roots and Portal Containers

* Forbid createEventHandle with custom events

We can't support this without adding more complexity. It's not clear that this is even desirable, as none of our existing use cases need custom events. This API primarily exists as a deprecation strategy for Flare, so I don't think it is important to expand its support beyond what Flare replacement code currently needs. We can later revisit it with a better understanding of the eager/lazy tradeoff but for now let's remove the inconsistency.

* Reduce risk by changing condition only under the flag

Co-authored-by: koba04 <[email protected]>
2020-08-24 16:50:20 +01:00
Dominic GannawayandGitHub 503cdeb8c8 Remove usage of PossiblyWeakSet from createEventHandle (#19686) 2020-08-24 16:10:23 +01:00
Toru KobayashiandGitHub e70a4a939f Add a test for non-passive event handlers for events affected by the browsers' intervention (#19658) 2020-08-24 14:30:17 +01:00
Andrew ClarkandGitHub 36ff116931 Remove remaining references to effect list (#19673)
* Remove `firstEffect` null check

This is the last remaining place where the effect list has semantic
implications.

I've replaced it with a check of `effectTag` and `subtreeTag`, to see
if there are any effects in the whole tree. This matches the semantics
of the old check. However, I think only reason this optimization exists
is because it affects profiling. We should reconsider whether this
is necessary.

* Remove remaining references to effect list

We no longer use the effect list anywhere in our implementation. It's
been replaced by a recursive traversal in the commit phase.

This removes all references to the effect list in the new fork.
2020-08-21 20:42:32 -05:00
b3a8666a23 Tweaked landing page styles (#19665)
* Tweaked landing page styles

* Update GitHub link

Co-authored-by: E-Liang Tan <[email protected]>
2020-08-21 14:06:01 -04:00
Dan AbramovandGitHub 09b0c21e4f Fix movementX/Y polyfill with capture events (#19672)
* Fix movementX/Y polyfill with capture events

* Remove unnecesary call for better inlining
2020-08-21 16:55:41 +01:00
6h057andGitHub 20d39cbfc1 Fix DevTools crash when inspecting document.all (#19619)
* Add html_all_collection type to correct typeof document.all

* process HTMLAllCollection like HTMLElement + fix flow issue

* fix lint

* move flow fix comment

* Make it work with iframes too

* optimize how we get html_all_collection type

* use once Object.prototype.toString.call
2020-08-21 14:31:16 +01:00
Sebastian MarkbågeandGitHub f16bee08f4 Use Global Render Timeout for CPU Suspense (#19643)
* Use Retry lane for resuming CPU suspended work

* Use a global render timeout for CPU suspense heuristics

* Fix profiler test since we're now reading time more often

* Sync to new reconciler

* Test synchronously rerendering should not render more rows
2020-08-20 14:39:29 -07:00
Hemakshi SachdevandGitHub 5e48aca9a5 Fix: Unspecified error for IE11 (#19530) (#19664) 2020-08-20 21:53:23 +01:00
Brian VaughnandGitHub 921d63fe74 Visually distinguish user timing marks from React events (#19663) 2020-08-20 14:43:40 -04:00
7d0dee6981 Import React Concurrent Mode Profiler (#19634)
Co-authored-by: Brian Vaughn <[email protected]>
Co-authored-by: Kartik Choudhary <[email protected]>
2020-08-20 14:06:28 -04:00
E-Liang TanandGitHub dec4a9e37e Upgrade all @babel/* packages to fix DevTools builds on newer Node versions (#19647) 2020-08-20 11:47:16 -04:00
Dan AbramovandGitHub 7785b61a07 Fix incorrect copy-paste in test (#19657) 2020-08-20 01:47:32 +01:00
Dan AbramovandGitHub 2a5c176561 Revert "Remove onScroll bubbling flag (#19535)" (#19655)
This reverts commit 54c651dfb2.
2020-08-19 20:54:54 +01:00
Dan AbramovandGitHub babb64025f Keep onTouchStart, onTouchMove, and onWheel passive (#19654)
* Keep onTouchStart, onTouchMove, and onWheel passive

* Put it behind a feature flag on WWW
2020-08-19 18:42:33 +01:00
5d8a405ecd Add flow to SyntheticEvent (#19564)
* Add flow to SyntheticEvent

* Minimal implementation of known and unknown synthetic events

* less casting

* Update EnterLeaveEventPlugin.js

Co-authored-by: Dan Abramov <[email protected]>
2020-08-19 14:16:48 +01:00
Julien GilliandGitHub 24b8c2a66d provide profiling bundle for react-reconciler (#19559) 2020-08-19 14:11:27 +01:00
Toru KobayashiandGitHub 4a0f7acac2 refactor: remove unnecessary return statements (#19625) 2020-08-19 14:10:41 +01:00
Sam MarksandGitHub 9a83027101 fix: property list values should show whitespace (#19640) 2020-08-19 08:50:46 -04:00
Brian VaughnandGitHub 9a72ba28c4 Add missing param to safelyCallDestroy() (#19638) 2020-08-18 12:02:04 -04:00
ᴜɴвʏтᴇandGitHub 5fcd0a7b81 fix: open two same tabs on firefox (#19632)
close #19629
2020-08-18 10:17:00 -04:00
Luna RuanandGitHub 27749e0c82 change destroy to safelyCallDestroy (#19605)
We use safelyCallDestroy for commitUnmount and passive effects unmounts but we call destroy directly in commitHookEffectListUnmount (AKA layout effects unmounts because we don't use this anywhere else). This PR changes the direct destroy call to safelyCallDestroy for consistency
2020-08-17 17:32:50 -07:00
Brian VaughnandGitHub 367c24ea79 Always skip unmounted/unmounting error boundaries (#19627)
The behavior of error boundaries for passive effects that throw during cleanup was recently changed so that React ignores boundaries which are also unmounting in favor of still-mounted boundaries. This commit implements that same behavior for layout effects (useLayoutEffect, componentWillUnmount, and ref-detachment).

The new, skip-unmounting-boundaries behavior is behind a feature flag (`skipUnmountedBoundaries`).
2020-08-17 15:01:06 -04:00
Timothy YungandGitHub 2a00a30b07 Append text string to <Text> error message (#19581)
* Append text string to <Text> error message

* Truncate text in <Text> error message

* Regenerate `codes.json`
2020-08-17 10:47:49 -07:00
aa89331b44 Fix: React cannot render in ShadowRoot (#15894)
* fix: render in shadow root

* fix: flow typing

* Remove types and turn invariant into warning

Co-authored-by: Dan Abramov <[email protected]>
2020-08-17 15:47:49 +01:00
Dan Abramov b9fc7f21d2 [email protected] 2020-08-17 13:31:20 +01:00
Dan AbramovandGitHub 3d2b5d4a76 Update CHANGELOG.md 2020-08-17 13:30:16 +01:00
2bf141b574 refactor fb.me redirect link to reactjs.org/link (#19598)
* refactor fb.me url to reactjs.org/link

* Update ESLintRuleExhaustiveDeps-test.js

* Update ReactDOMServerIntegrationUntrustedURL-test.internal.js

* Update createReactClassIntegration-test.js

* Update ReactDOMServerIntegrationUntrustedURL-test.internal.js

Co-authored-by: Dan Abramov <[email protected]>
2020-08-17 13:25:50 +01:00
Toru KobayashiandGitHub ef7ec502ba fix: leak strict mode with UMD builds (#19614) 2020-08-15 14:42:49 +01:00
Brian VaughnandGitHub 7012428b49 Improve error boundary handling for unmounted subtrees (#19542)
A passive effect's cleanup function may throw after an unmount. Prior to this commit, such an error would be ignored. (React would not notify any error boundaries.) After this commit, React's behavior varies depending on which reconciler fork is being used.

For the old reconciler, React will call componentDidCatch for the nearest unmounted error boundary (if there is one). If there are no unmounted error boundaries, React will still swallow the error because the return pointer has been disconnected, so the normal error handling logic does not know how to traverse the tree to find the nearest still-mounted ancestor.

For the new reconciler, React will skip any unmounted boundaries and look for a still-mounted boundary. If one is found, it will call getDerivedStateFromError and/or componentDidCatch (depending on the type of boundary).

Tests have been added for both reconciler variants for now.
2020-08-14 16:46:46 -04:00
Brian VaughnandGitHub 34e91f0b80 Permanently removed component stacks from scheduling profiler data (#19615)
These stacks improve the profiler data but they're expensive to generate and generating them can also cause runtime errors in larger applications (although an exact repro has been hard to nail down). Removing them for now. We can revisit adding them after this profiler has been integrated into the DevTools extension and we can generate them lazily.
2020-08-14 15:21:13 -04:00
Andrew Clark 601c759449 Remove didTimeout check from work loop
No longer need this, since we have starvation protection in userspace.

This will also allow us to remove the concept from the Scheduler
package, which is nice because `postTask` doesn't currently support it.
2020-08-14 10:45:24 -04:00
Andrew Clark 8e96016805 Remove wasteful checks from shouldYield
`shouldYield` will currently return `true` if there's a higher priority
task in the Scheduler queue.

Since we yield every 5ms anyway, this doesn't really have any practical
benefit. On the contrary, the extra checks on every `shouldYield` call
are wasteful.
2020-08-14 10:45:11 -04:00
Clay TercekandGitHub 27ca06d906 fix event.relatedTarget fallback logic for firefox (#19607)
* fix event.relatedTarget fallback logic for firefox

* check if relatedTarget is undefined for fallback
2020-08-14 13:05:53 +01:00
Jordan EldredgeandGitHub 4876988c46 [eslint-plugin-react-hooks] Report constant constructions (#19590)
* [eslint-plugin-react-cooks] Report constant constructions

The dependency array passed to a React hook can be thought of as a list of cache keys. On each render, if any dependency is not `===` its previous value, the hook will be rerun. Constructing a new object/array/function/etc directly within your render function means that the value will be referentially unique on each render. If you then use that value as a hook dependency, that hook will get a "cache miss" on every render, making the dependency array useless.

This can be especially dangerous since it can cascade. If a hook such as `useMemo` is rerun on each render, not only are we bypassing the option to avoid potentially expensive work, but the value _returned_ by `useMemo` may end up being referentially unique on each render causing other downstream hooks or memoized components to become deoptimized.

* Fix/remove existing tests

* Don't give an autofix of wrapping object declarations

It may not be safe to just wrap the declaration of an object, since the object may get mutated.

Only offer this autofix for functions which are unlikely to get mutated.

Also, update the message to clarify that the entire construction of the value should get wrapped.

* Handle the long tail of nodes that will be referentially unique

* Catch let/var constant constructions on initial assignment

* Trim trailing whitespace

* Address feedback from @gaearon

* Rename "assignment" to "initialization"

* Add test for a constant construction used in multiple dependency arrays
2020-08-13 20:54:33 +01:00
Sebastian MarkbågeandGitHub ada150793d Move commit passive unmount/mount to CommitWork (#19599) 2020-08-13 09:17:33 -07:00
Brian VaughnandGitHub 7b32e7cdfc Fix emoji character displayed in Chrome extension (#19603) 2020-08-13 11:16:35 -04:00
inottnandGitHub 2affd3caf9 Remove unused argument (#19600) 2020-08-13 15:11:01 +01:00
Andrew ClarkandGitHub 9e5b400236 [Scheduler] Re-throw unhandled errors (#19595)
Because `postTask` returns a promise, errors inside a `postTask`
callback result in the promise being rejected.

If we don't catch those errors, then the browser will report an
"Unhandled promise rejection" error. This is a confusing message to see
in the console, because the fact that `postTask` is a promise-based API
is an implementation detail from the perspective of the developer.
"Promise rejection" is a red herring.

On the other hand, if we do catch those errors, then we need to report
the error to the user in some other way.

What we really want is the default error reporting behavior that a
normal, non-Promise browser event gets.

So, we'll re-throw inside `setTimeout`.
2020-08-12 20:06:43 -07:00
Pascal Fong KyeandGitHub 8fa4975389 DevTools bug fix: Proxied methods should be safely dehydrated for display 2020-08-12 12:15:53 -04:00
Andrew ClarkandGitHub c3c5f85dd5 [Scheduler] Call postTask directly (#19551)
This updates the experimental Scheduler postTask build to call postTask
directly, instead of managing our own custom queue and work loop.

We still use a deadline 5ms mechanism to implement `shouldYield`.

The main thing that postTask is currently missing is the continuation
feature — when yielding to the main thread, the yielding task is sent
to the back of the queue, instead of maintaining its position.

While this would be nice to have, even without it, postTask may be good
enough to replace our userspace implementation.

We'll run some tests to see.
2020-08-12 08:39:47 -05:00