Commit Graph
13196 Commits
Author SHA1 Message Date
Dominic Gannaway e028ce2ab7 Modern Event System: ensure target ancestors are only host nodes (#18827) 2020-05-05 13:10:05 +01:00
Dan Abramov 4d124a4f67 [Blocks Fixture] Misc updates (#18811)
* [Blocks Fixture] Update navigation buttons immediately

* Add more profile links

* Minor refactor

* Add subroutes to Profile
2020-05-05 11:53:02 +01:00
Andrew Clark fe7163e73d Add unstable prefix to experimental APIs (#18825)
We've been shipping unprefixed experimental APIs (like `createRoot` and
`useTransition`) to the Experimental release channel, with the rationale
that because these APIs do not appear in any stable release, we're free
to change or remove them later without breaking any downstream projects.

What we didn't consider is that downstream projects might be tempted to
use feature detection:

```js
const useTransition = React.useTransition || fallbackUseTransition;
```

This pattern assumes that the version of `useTransition` that exists in
the Experimental channel today has the same API contract as the final
`useTransition` API that we'll eventually ship to stable.

To discourage feature detection, I've added an `unstable_` prefix to
all of our unstable APIs.

The Facebook builds still have the unprefixed APIs, though. We will
continue to support those; if we make any breaking changes, we'll
migrate the internal callers like we usually do. To make testing easier,
I added the `unstable_`-prefixed APIs to the www builds, too. That way
our tests can always use the prefixed ones without gating on the
release channel.
2020-05-04 22:25:41 -07:00
Sebastian Markbåge cd4a96035f Remove old CM exports (#18710) 2020-05-04 21:39:57 -07:00
Dominic Gannaway 9751935abf Modern Event System: improve dispatching queue (#18799) 2020-05-04 16:55:45 +01:00
Dan Abramov 3e13d70984 [RN] Remove debugging invariant (#18813) 2020-05-04 15:48:35 +01:00
Dan Abramov f6fcae58e9 [Blocks] Add Shell to Fixture (#18803)
* [Blocks] Add Feed page to fixture

* Add minimal routing

* Always show post with comments
2020-05-04 01:59:55 +01:00
Dan Abramov d830cd9984 [Blocks] Fix stale data on updates (#18810)
* [Blocks] Failing test for nested load

* Simplify the test

* Add a similar test that fails in PROD

* Copy .type when cloning work in progress
2020-05-04 01:43:51 +01:00
Sebastian Markbåge 64d4b84204 Rename Flight to Transport (#18808)
* Rename Flight to Transport

Flight is still the codename for the implementation details (like Fiber).

However, now the public package is react-transport-... which is only
intended to be used directly by integrators.

* Rename names
2020-05-03 11:33:48 -07:00
Andrew Clark 93e078ddf2 Initial Lanes implementation (#18796)
See PR #18796 for more information.

All of the changes I've made in this commit are behind the
`enableNewReconciler` flag. Merging this to master will not affect the
open source builds or the build that we ship to Facebook.

The only build that is affected is the `ReactDOMForked` build, which is
deployed to Facebook **behind an experimental flag (currently disabled
for all users)**. We will use this flag to gradually roll out the new
reconciler, and quickly roll it back if we find any problems.

Because we have those protections in place, what I'm aiming for with
this initial PR is the **smallest possible atomic change that lands
cleanly and doesn't rely on too many hacks**. The goal has not been to
get every single test or feature passing, and it definitely is not to
implement all the features that we intend to build on top of the new
model. When possible, I have chosen to preserve existing semantics and
defer changes to follow-up steps. (Listed in the section below.)

(I did not end up having to disable any tests, although if I had, that
should not have necessarily been a merge blocker.)

For example, even though one of the primary goals of this project is to
improve our model for parallel Suspense transitions, in this initial
implementation, I have chosen to keep the same core heuristics for
sequencing and flushing that existed in the ExpirationTimes model: low
priority updates cannot finish without also finishing high priority
ones.

Despite all these precautions, **because the scope of this refactor is
inherently large, I do expect we will find regressions.** The flip side
is that I also expect the new model to improve the stability of the
codebase and make it easier to fix bugs when they arise.
2020-05-02 17:09:31 -07:00
Moti ZilbermanandSebastian Markbage 3c7d52c3d6 Give unresolved lazy() a name in component stack (#16104)
* Give unresolved lazy() a name in component stack

* Normalize stack in tests

Co-authored-by: Sebastian Markbage <sema@fb.com>
2020-05-01 16:41:39 -07:00
Benedikt Franke 333deb707d Remove hint to post feedback about exhaustive-deps rule (#18712)
The thread is closed and locked.
2020-05-01 19:13:59 +01:00
Dominic Gannaway aa88589d0b Refine experimental Scopes API (#18778)
* Refine experimental Scopes API
2020-05-01 19:01:43 +01:00
Dan Abramov d804f99b9e eslint-plugin-react-hooks@4.0.0 2020-05-01 17:13:56 +01:00
Dan Abramov 4e93b9364c Add changelog for eslint-plugin-react-hooks (#18801) 2020-05-01 17:12:32 +01:00
Aaron PettengillandAaron Pettengill 5ac9ca72df Feature: Add support to exhaustive-deps rule for any hook ending with Effect (#18580)
* Add test cases for support exhaustive deps ending in Effect

* Apply the exhaustive deps lint rule to any hook ending with Effect

* Add another test for supporting linting useXEffect hooks

Co-authored-by: Aaron Pettengill <aaron.pettengill@echoman.com>
2020-05-01 16:57:25 +01:00
Dan Abramov eab94403d7 Build Flight runtime for WWW (revert part of earlier change) 2020-05-01 16:44:25 +01:00
Sebastian Markbåge 17dcc29cd1 Don't "schedule" discrete work if we're scheduling sync work (#18797) 2020-05-01 08:43:15 -07:00
Dan Abramov 9491f39472 react-refresh@0.8.2 2020-05-01 16:18:13 +01:00
Dan Abramov 43a1c72751 Don't build react-data for WWW 2020-05-01 16:13:11 +01:00
Dan Abramov 01914a7673 Update bundle configs to not build some packages (#18800)
* Stop building old ReactCache for FB

* Update other bundle configs
2020-05-01 16:07:36 +01:00
Sophie Alpert 21670cf4be [react-refresh/babel] Always insert registrations after var (#18794)
Previously, we transformed

```
let Foo = styled.div``;
```

to

```
let Foo = _c1 = styled.div``;
```

and then babel-plugin-styled-components would infer `_c1` as the display name. Widen the existing case that applies to function expressions to apply to any type of variable declaration.
2020-05-01 16:01:11 +01:00
Andrew Clark 914b57be27 Move legacy hidden API to new internal Fiber type (#18782)
* Unhide Suspense trees without entanglement

When a Suspense boundary is in its fallback state, you cannot switch
back to the main content without also finishing any updates inside the
tree that might have been skipped. That would be a form of tearing.

Before we fixed this in #18411, the way this bug manifested was that a
boundary was suspended by an update that originated from a child
component (as opposed to props from a parent). While the fallback was
showing, it received another update, this time at high priority. React
would render the high priority update without also including the
original update. That would cause the fallback to switch back to the
main content, since the update that caused the tree to suspend was no
longer part of the render. But then, React would immediately try to
render the original update, which would again suspend and show the
fallback, leading to a momentary flicker in the UI.

The approach added in #18411 is, when receiving a high priority update
to a Suspense tree that's in its fallback state is to bail out, keep
showing the fallback and finish the update in the rest of the tree.
After that commits, render again at the original priority. Because low
priority expiration times are inclusive of higher priority expiration
times, this ensures that all the updates are committed together.

The new approach in this commit is to turn `renderExpirationTime` into a
context-like value that lives on the stack. Then, when unhiding the
Suspense boundary, we can push a new `renderExpirationTime` that is
inclusive of both the high pri update and the original update that
suspended. Then the boundary can be unblocked in a single render pass.

An advantage of the old approach is that by deferring the work of
unhiding, there's less work to do in the high priority update.

The key advantage of the new approach is that it solves the consistency
problem without having to entangle the entire root.

* Create internal LegacyHidden type

This only exists so we can clean up the internal implementation of
`<div hidden={isHidden} />`, which is not a stable feature. The goal
is to move everything to the new Offscreen type instead. However,
Offscreen has different semantics, so before we can remove the legacy
API, we have to migrate our internal usage at Facebook. So we'll need
to maintain both temporarily.

In this initial commit, I've only added the type. It's not used
anywhere. The next step is to use it to implement `hidden`.

* Use LegacyHidden to implement old hidden API

If a host component receives a `hidden` prop, we wrap its children in
an Offscreen fiber. This is similar to what we do for Suspense children.

The LegacyHidden type happens to share the same implementation as the
new Offscreen type, for now, but using separate types allows us to fork
the behavior later when we implement our planned changes to the
Offscreen API.

There are two subtle semantic changes here. One is that the children of
the host component will have their visibility toggled using the same
mechanism we use for Offscreen and Suspense: find the nearest host node
children and give them a style of `display: none`. We didn't used to do
this in the old API, because the `hidden` DOM attribute on the parent
already hides them. So with this change, we're actually "overhiding" the
children. I considered addressing this, but I figure I'll leave it as-is
in case we want to expose the LegacyHidden component type temporarily
to ease migration of Facebook's internal callers to the Offscreen type.

The other subtle semantic change is that, because of the extra fiber
that wraps around the children, this pattern will cause the children
to lose state:

```js
return isHidden ? <div hidden={true} /> : <div />;
```

The reason is that I didn't want to wrap every single host component
in an extra fiber. So I only wrap them if a `hidden` prop exists. In
the above example, that means the children are conditionally wrapped
in an extra fiber, so they don't line up during reconciliation, so
they get remounted every time `isHidden` changes.

The fix is to rewrite to:

```js
return <div hidden={isHidden} />;
```

I don't anticipate this will be a problem at Facebook, especially since
we're only supposed to use `hidden` via a userspace wrapper component.
(And since the bad pattern isn't very React-y, anyway.)

Again, the eventual goal is to delete this completely and replace it
with Offscreen.
2020-04-30 19:37:27 -07:00
Brian Vaughn ac533fde3d Prevent stale legacy root from clearing a container (DRAFT) (#18792)
* Don't clear a container because of a stale legacy root

* Added test repro for FB error
2020-04-30 15:56:21 -07:00
Dan Abramov 5b89d353e2 Update react-refresh README 2020-04-30 15:43:21 +01:00
Dan Abramov 3a9c373521 [Blocks] Add preload to fetch (#18785) 2020-04-30 02:23:18 +01:00
Dan Abramov dd7f0deb94 [Blocks] Use native fetch (#18784)
* [Blocks] Use native fetch

* Use the prototype

* Support arrayBuffer() and blob()

* ctor

* Simplify

* Use an expando

* Keep a map of formats

* Unused

* Remove unnecessary second property read

* Keep it simple

* Store the original thenable
2020-04-30 01:24:04 +01:00
Alex Taylor e71f5df9c3 Consistent useCallback implementation in ReactDOMServer (#18783) 2020-04-29 16:22:10 -07:00
Dan Abramov 515326753b [Blocks] Initial implementation of cache and data/fetch (#18774)
* Rename ReactCache -> ReactCacheOld

We still use it in some tests so I'm going to leave it for now. I'll start making the new one in parallel in the react package.

* Add react/unstable-cache entry point

* Add react-data entry point

* Initial implementation of cache and data/fetch

* Address review
2020-04-29 19:14:15 +01:00
Dan Abramov 53d68b33ff [Blocks] Add Client Fixture (#18773)
* [Blocks] Add Client Fixture

* Add more TODOs
2020-04-29 02:23:09 +01:00
Dominic Gannaway 88d0be6da5 Refactor ElementListenerMap (#18766) 2020-04-28 21:53:51 +01:00
Brian Vaughn ea2af878cc Root API should clear non-empty roots before mounting (#18730)
* Root API should clear non-empty roots before mounting

Legacy render-into-subtree API removes children from a container before rendering into it. The root API did not do this previously, but just left the children around in the document.

This commit adds a new FiberRoot flag to clear a container's contents before mounting. This is done during the commit phase, to avoid multiple, observable mutations.
2020-04-28 13:07:42 -07:00
Nick Reiley d2ef120089 Allow Node 14.x (#18755) 2020-04-28 15:57:45 +01:00
Sebastian Markbåge 53ce0c3452 Allow flushSync to noop in life cycles but with a warning (#18759) 2020-04-27 20:07:39 -07:00
Andrew Clark f342a2399f SuspenseList: Reschedule at same priority (#18738)
SuspenseList progressively renders items even if the list is CPU bound,
i.e. it isn't waiting for missing data. It does this by showing a
fallback for the remaining items, committing the items in that have
already finished, then starting a new render to continue working on
the rest.

When it schedules that subsequent render, it uses a slightly lower
priority than the current render: `renderExpirationTime - 1`.

This commit changes it to reschedule at `renderExpirationTime` instead.

I don't know what the original motivation was for bumping the expiration
time slightly lower. The comment says that the priorities of the two
renders are the same (which makes sense to me) so I imagine it was
motivated by some implementation detail. I don't think it's necessary
anymore, though perhaps it was when it was originally written. If it is
still necessary, we should write a test case that illustrates why.
2020-04-25 20:27:35 -07:00
Andrew Clark cb70753993 Move hide/unhide logic to Offscreen component
The Offscreen component is not a public type, yet, but once it is, it
will share the same hide/unhide logic as Suspense children.
2020-04-25 00:10:09 -07:00
Andrew Clark cb48f974c9 Wrap primary tree in Offscreen fiber type
Still just acts like a fragment. Next step is to move the hide/unhide
logic to the Offscreen implementation.
2020-04-25 00:10:09 -07:00
Luna Ruan ed01fdacce Add Offscreen component type
Doesn't do anything special in this initial commit. Just acts like a
fragment.
2020-04-25 00:10:09 -07:00
Andrew Clark 1df756ba2c Always wrap Suspense children in fragment (#18711)
Changes the internal fiber structure of the Suspense component. When a
Suspense boundary can't finish rendering and switches to a fallback, we
wrap the "primary" tree in a Fragment fiber and hide all its DOM nodes.
Then we mount the fallback tree into a separate Fragment fiber. Both
trees will render into the same parent DOM node (since React fragments
aren't part of the host tree), but the wrappers ensure that the children
in each tree are reconciled separately.

The old implementation would try to be clever and only add the fragment
wrapper when the fallback was in place, to save memory. This "worked"
but was prone to regressions, since this is the only such place in the
codebase where we wrap existing nodes in a new node. (In other words,
it's a form of reparenting, which we don't implement elsewhere).

Since the original implementation, we've also added lots of additional
requirements to the Suspense component that have led to an explosion in
complexity, like limited support in Legacy Mode (with very different
semantics) and progressive hydration.

We're planning to add even more features to the Suspense boundary, so
we're going to sacrifice a bit more memory for a simpler implementation
that is less prone to regressions.

This ended up removing a lot of weird hacks and edge cases, but there
are still plenty left over. Most of the remaining complexity is related
to Legacy mode. That's the next thing we should aim to drop support for.

Because this is a risky change, I've only changed this in the new
reconciler. It blocks some other features, but as of now we're not
planning to implement those in the old reconciler. If that changes, this
should cherry-pick to the other implementation without much effort.
2020-04-25 00:09:19 -07:00
Andrew Clark db6513914f Make ExpirationTime an opaque type (#18732)
* Add LanePriority type

React's internal scheduler has more priority levels than the external
Scheduler package. Let's use React as the source of truth for tracking
the priority of updates so we have more control. We'll still fall back
to Scheduler in the default case. In the future, we should consider
removing `runWithPriority` from Scheduler and replacing the valid use
cases with React-specific APIs.

This commit adds a new type, called a LanePriority to disambiguate from
the Scheduler one.

("Lane" refers to another type that I'm planning. It roughly translates
to "thread." Each lane will have a priority associated with it.)

I'm not actually using the lane anywhere, yet. Only setting stuff up.

* Remove expiration times train model

In the old reconciler, expiration times are computed by applying an
offset to the current system time. This has the effect of increasing
the priority of updates as time progresses. Because we also use
expiration times as a kind of "thread" identifier, it turns out this
is quite limiting because we can only flush work sequentially along
the timeline.

The new model will use a bitmask to represent parallel threads that
can be worked on in any combination and in any order.

In this commit, expiration times and the linear timeline are still in
place, but they are no longer based on a timestamp. Effectively, they
are constants based on their priority level.

* Stop using ExpirationTime to represent timestamps

Follow up to the previous commit. This converts the remaining places
where we were using the ExpirationTime type to represent a timestamp,
like Suspense timeouts.

* Fork Dependencies and PendingInteractionMap types

These contain expiration times

* Make ExpirationTime an opaque type

ExpirationTime is currently just an alias for the `number` type, for a
few reasons. One is that it predates Flow's opaque type feature. Another
is that making it opaque means we have to move all our comparisons and
number math to the ExpirationTime module, and use utility functions
everywhere else.

However, this is actually what we want in the new system, because the
Lanes type that will replace ExpirationTime is a bitmask with a
particular layout, and performing operations on it will involve more
than just number comparisions and artihmetic. I don't want this logic to
spread ad hoc around the whole codebase.

The utility functions get inlined by Closure so it doesn't matter
performance-wise.

I automated most of the changes with JSCodeshift, with only a few manual
tweaks to stuff like imports. My goal was to port the logic exactly to
prevent subtle mistakes, without trying to simplify anything in the
process. I'll likely need to audit many of these sites again when I
replace them with the new type, though, especially the ones
in ReactFiberRoot.

I added the codemods I used to the `scripts` directory. I won't merge
these to master. I'll remove them in a subsequent commit. I'm only
committing them here so they show up in the PR for future reference.

I had a lot of trouble getting Flow to pass. Somehow it was not
inferring the correct type of the constants exported from the
ExpirationTime module, despite being annotated correctly.

I tried converting them them to constructor functions — `NoWork`
becomes `NoWork()` — and that made it work. I used that to unblock me,
and fixed all the other type errors. Once there were no more type
errors, I tried converting the constructors back to constants. Started
getting errors again.

Then I added a type constraint everywhere a constant was referenced.
That fixed it. I also figured out that you only have to add a constraint
when the constant is passed to another function, even if the function is
annotated. So this indicates to me that it's probably a Flow bug. I'll
file an issue with Flow.

* Delete temporary codemods used in previous commit

I only added these to the previous commit so that I can easily run it
again when rebasing. When the stack is squashed, it will be as if they
never existed.
2020-04-24 23:26:04 -07:00
Chang Yan 4b02b66111 [ESLint] Extend isHook to recognize those under PascalCase's namespace (#18722)
* Extend Namespace to PascalCase

* Add valid case for jest.useFakeTimer

* format

* format :(

* fix nits
2020-04-24 02:50:52 +01:00
Dominic Gannaway 30cee2f4c7 Modern Event System: register onMouseEnter for portals (#18720) 2020-04-23 20:57:52 +01:00
Dominic Gannaway 4e3545fd6f ReactDOMEventListener: clean up module (#18713) 2020-04-23 20:19:28 +01:00
Sebastian Markbåge b58dec979a Remove unnecessary stack (#18707) 2020-04-23 09:44:37 -07:00
Sebastian Markbåge a2fb84bebd Disable prepareStackTrace while we're generating stacks (#18708)
This could be used to do custom formatting of the stack trace in a way
that isn't compatible with how we use it. So we disable it while we use
it.

In theory we could call this ourselves with the result of our stack.
It would be a lot of extra production code though. My personal opinion
is that this should always be done server side instead of on the client.

We could expose a custom parser that converts it and passes it through
prepareStackTrace as structured data. That way it's external and doesn't
have to be built-in to React.
2020-04-23 09:16:58 -07:00
Brian Vaughn b9fc3d8d59 DevTools temporarily disable prepareStackTrace before creating custom component stacks (#18717) 2020-04-23 09:02:42 -07:00
Sebastian Markbåge b0cb137bcb Don't dedupe using the stack (#18693)
We currently use the stack to dedupe warnings in a couple of places.
This is a very heavy weight way of computing that a warning doesn't need
to be fired.

This uses parent component name as a heuristic for deduping. It's not
perfect but as soon as you fix one you'll uncover the next. It might be a
little annoying but having many logs is also annoying.

We now have no special cases for stacks. The only thing that uses stacks in
dev is the console.error and dev tools. This means that we could
externalize this completely to an console.error patching module and drop
it from being built-in to react.

The only prod/dev behavior is the one we pass to error boundaries or the
error we throw if you don't have an error boundary.
2020-04-22 19:02:11 -07:00
Sebastian Markbåge 571f5ad2d6 Temporarily Remove DebugTracing from the New Reconciler (#18697)
* Remove priority field from tracing

* Remove DebugTracing mode from new reconciler (temporarily)

* Run DebugTracing tests in the *other* variant so it's no on for new reconciler
2020-04-21 20:14:40 -07:00
Sebastian Markbåge 2325375f4f Nit: add suffix _TIMEOUT consistently in scheduler (#18696) 2020-04-21 19:44:42 -07:00
Nick ReileyandBrian Vaughn e5cc1462b3 Fix mistyped script arbitrary code execution vulnerability (#18660)
* add test to trustedTypes-test.internal.js

* fix mistyped script arbitrary code execution

* Removed redundant .toLowerCase() call

Co-authored-by: Brian Vaughn <brian.david.vaughn@gmail.com>
2020-04-21 12:10:25 -07:00