Commit Graph

906 Commits

Author SHA1 Message Date
Andrew Clark
f9bf828701 Add `unstable_isNewReconciler export to FB builds (#18974)
Should check this at runtime instead of the GK
2020-05-21 10:03:59 -07:00
Dominic Gannaway
4a3f779d67 Remove event pooling in the modern system (#18969) 2020-05-21 13:54:05 +01:00
Andrew Clark
64f50c667a Remove disableHiddenPropDeprioritization flag (#18964)
This is rolled out to 100% public, so we can remove it.
2020-05-20 15:29:34 -07:00
Andrew Clark
0fb747f368 Add LegacyHidden to server renderer (#18919)
* Add LegacyHidden to server renderer

When the tree is hidden, the server renderer renders nothing. The
contents will be completely client rendered.

When the tree is visible it acts like a fragment.

The future streaming server renderer may want to pre-render these trees
and send them down in chunks, as with Suspense boundaries.

* Force client render, even at Offscreen pri
2020-05-14 11:28:11 -07:00
Andrew Clark
b4a1a4980c Disable <div hidden /> API in old fork, too (#18917)
The motivation for doing this is to make it impossible for additional
uses of pre-rendering to sneak into www without going through the
LegacyHidden abstraction. Since this feature was already disabled in
the new fork, this brings the two closer to parity.

The LegacyHidden abstraction itself still needs to opt into
pre-rendering somehow, so rather than totally disabling the feature, I
updated the `hidden` prop check to be obnoxiously specific. Before, you
could set it to any truthy value; now, you must set it to the string
"unstable-do-not-use-legacy-hidden".

The node will still be hidden in the DOM, since any truthy value will
cause the browser to apply a style of `display: none`.

I will have to update the LegacyHidden component in www to use the
obnoxious string prop. This doesn't block merge, though, since the
behavior is gated by a dynamic flag. I will update the component before
I enable the flag.
2020-05-13 20:01:10 -07:00
Dominic Gannaway
61f2a560e0 Add experimental ReactDOM.createEventHandle (#18756) 2020-05-12 20:24:25 +01:00
Dominic Gannaway
80c4dea0d1 Modern Event System: Add scaffolding for createEventHandle (#18898) 2020-05-12 19:01:12 +01:00
Andrew Clark
8b9c4d1688 Expose LegacyHidden type and disable <div hidden /> API in new fork (#18891)
* Expose LegacyHidden type

I will use this internally at Facebook to migrate away from
<div hidden />. The end goal is to migrate to the Offscreen type, but
that has different semantics. This is an incremental step.

* Disable <div hidden /> API in new fork

Migrates to the unstable_LegacyHidden type instead. The old fork does
not support the new component type, so I updated the tests to use an
indirection that picks the correct API. I will remove this once the
LegacyHidden (and/or Offscreen) type has landed in both implementations.

* Add gated warning for `<div hidden />` API

Only exists so we can detect callers in www and migrate them to the new
API. Should not visible to anyone outside React Core team.
2020-05-11 20:02:08 -07:00
Dominic Gannaway
e16703e6c7 Modern Event System: revise ancestor logic (#18886) 2020-05-11 22:09:52 +01:00
Sebastian Markbåge
539527b642 Don't cut off effects at end of list if hydrating (#18872) 2020-05-08 21:26:51 -07:00
Luna Ruan
df14b5bcc1 add new IDs for each each server renderer instance and prefixes to distinguish between each server render (#18576)
There is a worry that `useOpaqueIdentifier` might run out of unique IDs if running for long enough. This PR moves the unique ID counter so it's generated per server renderer object instead. For people who render different subtrees, this PR adds a prefix option to `renderToString`, `renderToStaticMarkup`, `renderToNodeStream`, and `renderToStaticNodeStream` so identifiers can be differentiated for each individual subtree.
2020-05-07 20:46:27 -07:00
Sebastian Markbåge
edf6eac8a1 Don't cut off the tail of a SuspenseList if hydrating (#18854) 2020-05-06 23:51:46 -07:00
Sebastian Markbåge
55f5cdee01 Disable setState before mount in legacy mode (#18851)
We kind of "support" this pattern in legacy mode. It's only deprecated in
Concurrent Mode.
2020-05-06 20:30:59 -07:00
Andrew Clark
47ebc90b08 Put render phase update change behind a flag (#18850)
In the new reconciler, I made a change to how render phase updates
work. (By render phase updates, I mean when a component updates
another component during its render phase. Or when a class component
updates itself during the render phase. It does not include when
a hook updates its own component during the render phase. Those have
their own semantics. So really I mean anything triggers the "`setState`
in render" warning.)

The old behavior is to give the update the same "thread" (expiration
time) as whatever is currently rendering. So if you call `setState` on a
component that happens later in the same render, it will flush during
that render. Ideally, we want to remove the special case and treat them
as if they came from an interleaved event.

Regardless, this pattern is not officially supported. This behavior is
only a fallback. The flag only exists until we can roll out the
`setState` warnning, since existing code might accidentally rely on the
current behavior.
2020-05-06 19:19:14 -07:00
Dominic Gannaway
6778c53c16 Modern Event System: fix bug in EnterLeave (#18849) 2020-05-07 00:13:13 +01:00
Sebastian Markbåge
96f3b7d1c3 Warn if calling setState outside of render but before commit (#18838)
* Don't attempt to render the children of a dehydrated Suspense boundary

The DehydratedFragment tag doesn't exist so doing so throws.

This can happen if we schedule childExpirationTime on the boundary and
bail out.

* Warn if scheduling work on a component before it is committed
2020-05-06 09:45:35 -07:00
Dominic Gannaway
823dc581fe Modern Event System: fix EnterLeave plugin logic (#18830) 2020-05-05 22:10:07 +01:00
Brian Vaughn
3cde22a84e Experimental test selector API (#18607)
Adds several new experimental APIs to aid with automated testing.

Each of the methods below accepts an array of "selectors" that identifies a path (or paths) through a React tree. There are four basic selector types:

* Component: Matches Fibers with the specified React component type
* Role: Matches Host Instances matching the (explicit or implicit) accessibility role.
* Test name: Matches Host Instances with a data-testname attribute.
* Text: Matches Host Instances that directly contain the specified text.
* There is also a special lookahead selector type that enables further matching within a path (without actually including the path in the result). This selector type was inspired by the :has() CSS pseudo-class. It enables e.g. matching a <section> that contained a specific header text, then finding a like button within that <section>.

API
* findAllNodes(): Finds all Host Instances (e.g. HTMLElement) within a host subtree that match the specified selector criteria.
* getFindAllNodesFailureDescription(): Returns an error string describing the matched and unmatched portions of the selector query.
* findBoundingRects(): For all React components within a host subtree that match the specified selector criteria, return a set of bounding boxes that covers the bounds of the nearest (shallowed) Host Instances within those trees.
* observeVisibleRects(): For all React components within a host subtree that match the specified selector criteria, observe if it’s bounding rect is visible in the viewport and is not occluded.
* focusWithin(): For all React components within a host subtree that match the specified selector criteria, set focus within the first focusable Host Instance (as if you started before this component in the tree and moved focus forwards one step).
2020-05-05 10:37:46 -07:00
Dominic Gannaway
e028ce2ab7 Modern Event System: ensure target ancestors are only host nodes (#18827) 2020-05-05 13:10:05 +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
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
Dominic Gannaway
aa88589d0b Refine experimental Scopes API (#18778)
* Refine experimental Scopes API
2020-05-01 19:01:43 +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
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
Alex Taylor
e71f5df9c3 Consistent useCallback implementation in ReactDOMServer (#18783) 2020-04-29 16:22:10 -07: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
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
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
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
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
Nick Reiley
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
Sebastian Markbåge
940f48b999 Avoid passing custom stacks to console.error (#18685)
* Detect double stacks in the new format in tests

* Remove unnecessary uses of getStackByFiberInDevAndProd

These all execute in the right execution context already.

* Set the debug fiber around the cases that don't have an execution context

* Remove stack detection in our console log overrides

We never pass custom stacks as part of the args anymore.

* Bonus: Don't append getStackAddendum to invariants

We print component stacks for every error anyway so this is just duplicate
information.
2020-04-21 09:22:46 -07:00
Dominic Gannaway
ff431b7fc4 Remove ReactDOM.useEvent and associated types+tests (#18689) 2020-04-21 16:40:44 +01:00
Dominic Gannaway
7b3934b34f Revert "Pressable click fix (#18625)" (#18688)
This reverts commit 5f7b175b35.
2020-04-21 11:08:30 +01:00
Naman Goel
5f7b175b35 Pressable click fix (#18625)
* Update press-legacy to use native click events

* update tests for pressable change

* fix formatting issue

* Address comments. Bring back some tests, remove others. Cleanup

* Fix flow and lint errors

* formatting fix missed by yarn lint
2020-04-20 23:13:17 +01:00
Dominic Gannaway
4f59a149b8 Modern event system: fix selectionchange bug (#18680) 2020-04-20 19:54:12 +01:00
Dominic Gannaway
a152827ef6 Refine the heuristics around beforeblur/afterblur (#18668)
* Refine the heuristics around beforeblur/afterblur
2020-04-20 19:32:22 +01:00
Sebastian Silbermann
ffb6c6c07b fix: skip dangerouslySetInnerHtml hydration warning if it's undefined (#18676)
* test: Add failing case for dangerouslySetInnerHtml=undefined

* fix: skip dangerouslySetInnerHtml warning if it's undefined

* test: add similar test that should trigger the warning

* chore: Remove redundant nullish check

* Poke yarn_test_www_variant which timed out

* test: Add smaller test for innerHTML=string to innerHTML=undefined
2020-04-20 18:46:55 +01:00
Dominic Gannaway
1078029af6 Revert "Revert focus event PRs (#18655)" (#18671)
This reverts commit 58c895e59c.
2020-04-20 16:00:33 +01:00
Nicolas Gallagher
96203240d3 ReactDOM: remove unstable-native-dependencies bundle (#18483)
This is only used by react-native-web and will be replaced by a user-space
implementation. See: https://github.com/necolas/react-native-web/issues/1568
2020-04-18 15:40:13 -07:00
Dominic Gannaway
58c895e59c Revert focus event PRs (#18655)
* Revert "Further cleanup to before/after blur (#18649)"

This reverts commit e2ccbf0358.

* Revert "Unify Flare FocusWithin responder with useFocusWithin (#18636)"

This reverts commit f24a9e7098.
2020-04-17 16:27:19 +01:00
Dominic Gannaway
e2ccbf0358 Further cleanup to before/after blur (#18649) 2020-04-17 11:52:29 +01:00
Dominic Gannaway
32bb44c80a Clean up modern plugins to remove dead code (#18639) 2020-04-16 20:10:23 +01:00
Dominic Gannaway
f24a9e7098 Unify Flare FocusWithin responder with useFocusWithin (#18636) 2020-04-16 19:35:41 +01:00
Dominic Gannaway
b1a083183c Revert legacy plugin modules (#18638) 2020-04-16 18:46:24 +01:00
Dominic Gannaway
31977d1bb3 Create copy of Legacy event plugins for Modern system (#18637) 2020-04-16 16:09:05 +01:00