Commit Graph

81 Commits

Author SHA1 Message Date
Dominic Gannaway b61174fb7b Remove the deprecated React Flare event system (#19520) 2020-08-05 15:13:29 +01:00
Dominic Gannaway 4eb9b1d2b4 Refactor createEventHandle signature (#19174) 2020-07-07 13:05:06 +01:00
Andrew Clark 103ed08c46 Remove shouldDeprioritizeSubtree from host config (#19124)
No longer being used.
2020-06-12 12:57:20 -07:00
Dominic Gannaway 80c4dea0d1 Modern Event System: Add scaffolding for createEventHandle (#18898) 2020-05-12 19:01:12 +01: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
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 aa88589d0b Refine experimental Scopes API (#18778)
* Refine experimental Scopes API
2020-05-01 19:01:43 +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
Dominic Gannaway 30cee2f4c7 Modern Event System: register onMouseEnter for portals (#18720) 2020-04-23 20:57:52 +01:00
Dominic Gannaway ff431b7fc4 Remove ReactDOM.useEvent and associated types+tests (#18689) 2020-04-21 16:40:44 +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 Markbåge 5474a83e25 Disable console.logs in the second render pass of DEV mode double render (#18547)
* Disable console log during the second rerender

* Use the disabled log to avoid double yielding values in scheduler mock

* Reenable debugRenderPhaseSideEffectsForStrictMode in tests that can
2020-04-08 16:43:51 -07:00
Luna Ruan 3278d24218 Add useOpaqueIdentifier Hook (#17322)
* Add useOpaqueIdentifier Hook

We currently use unique IDs in a lot of places. Examples are:
  * `<label for="ID">`
  * `aria-labelledby`

This can cause some issues:
  1. If we server side render and then hydrate, this could cause an
     hydration ID mismatch
  2. If we server side render one part of the page and client side
     render another part of the page, the ID for one part could be
     different than the ID for another part even though they are
     supposed to be the same
  3. If we conditionally render something with an ID ,  this might also
     cause an ID mismatch because the ID will be different on other
     parts of the page

This PR creates a new hook `useUniqueId` that generates a different
unique ID based on whether the hook was called on the server or client.
If the hook is called during hydration, it generates an opaque object
that will rerender the hook so that the IDs match.

Co-authored-by: Andrew Clark <git@andrewclark.io>
2020-04-06 17:17:27 -07:00
Sebastian Markbåge 3e94bce765 Enable prefer-const lint rules (#18451)
* Enable prefer-const rule

Stylistically I don't like this but Closure Compiler takes advantage of
this information.

* Auto-fix lints

* Manually fix the remaining callsites
2020-04-01 12:35:52 -07:00
Sebastian Silbermann ba31ad40a9 feat(StrictMode): Double-invoke render for every component (#18430)
* feat(StrictMode): Double-invoke render for every component

* fix: Mark ReactTestRendererAsync as internal
2020-03-29 23:13:46 +01:00
Sebastian Markbåge c5d2fc7127 Move some files out of /shared and rename to upper case (#18363)
* Rename lower case isomorphic default exports modules to upper case named exports

We're somewhat inconsistent here between e.g. ReactLazy and memo.

Let's pick one.

This also moves the responder, fundamental, scope creators from shared
since they're isomorphic and same as the other creators.

* Move some files that are specific to the react-reconciler from shared

Individual renderers are allowed to deep require into the reconciler.

* Move files specific to react-dom from shared

react-interactions is right now dom specific (it wasn't before) so we can
type check it together with other dom stuff. Avoids the need for
a shared ReactDOMTypes to be checked by RN for example.

* Move ReactWorkTags to the reconciler

* Move createPortal to export from reconciler

Otherwise Noop can't access it since it's not allowed deep requires.
2020-03-21 15:22:01 -07:00
Dominic Gannaway c804f9aebb ReactDOM.useEvent: wire to event system to the hook (#18304) 2020-03-16 21:46:17 +00:00
Dominic Gannaway 99d271228d ReactDOM.useEvent: more scaffolding changes (#18282) 2020-03-12 09:12:06 +00:00
Sebastian Markbåge 7a1691cdff Refactor Host Config Infra (getting rid of .inline*.js) (#18240)
* Require deep for reconcilers

* Delete inline* files

* Delete react-reconciler/persistent

This no longer makes any sense because it react-reconciler takes
supportsMutation or supportsPersistence as options. It's no longer based
on feature flags.

* Fix jest mocking

* Fix Flow strategy

We now explicitly list which paths we want to be checked by a renderer.
For every other renderer config we ignore those paths.

Nothing is "any" typed. So if some transitive dependency isn't reachable
it won't be accidentally "any" that leaks.
2020-03-06 16:20:42 -08:00
Sebastian Markbåge 549e418830 Move remaining things to named exports (#18165)
* Move remaining things to named exports

The interesting case here is the noop renderers. The wrappers around the
reconciler now changed to use a local export that gets mutated.

ReactNoop and ReactNoopPersistent now have to destructure the object to
list out the names it's going to export. We should probably refactor
ReactNoop away from createReactNoop. Especially since it's also not Flow
typed.

* Switch interactions to star exports

This will have esModule compatibility flag on them. They should ideally
export default instead.
2020-02-27 17:18:55 -08:00
Sebastian Markbåge 09348798a9 Codemod to import * as React from "react"; (#18102)
* import * as React from "react";

This is the correct way to import React from an ES module since the ES
module will not have a default export. Only named exports.

* import * as ReactDOM from "react-dom"
2020-02-21 19:45:20 -08:00
Dan Abramov b979db4e72 Bump Prettier (#17811)
* Bump Prettier

* Reformat

* Use non-deprecated option
2020-01-09 13:54:11 +00:00
Dominic Gannaway 9fe1031244 [react-interactions] Rename Flare APIs to deprecated and remove from RN (#17644) 2019-12-18 10:24:46 +00:00
Dan Abramov 0b5a26a489 Rename toWarnDev -> toErrorDev, toLowPriorityWarnDev -> toWarnDev (#17605)
* Rename toWarnDev -> toErrorDev in tests

* Rename toWarnDev matcher implementation to toErrorDev

* Rename toLowPriorityWarnDev -> toWarnDev in tests and implementation
2019-12-16 12:48:16 +00:00
Dominic Gannaway a61886b16b [react-interactions] Refine custom active element blur logic (#17354) 2019-11-13 20:46:00 +00:00
Dominic Gannaway b71ab61c8f [react-interactions] Adds more experimental Scope API methods (#17042) 2019-10-08 19:32:53 +02:00
Dominic Gannaway fc80772078 [react-events] Ensure updateEventListeners updates in commit phase (#16540) 2019-08-22 23:58:16 +01:00
Sebastian Markbåge c80678c760 Add "hydrationOptions" behind the enableSuspenseCallback flag (#16434)
This gets invoked when a boundary is either hydrated or if it is deleted
because it updated or got deleted before it mounted.
2019-08-19 13:26:39 -07:00
Dominic Gannaway 5098891193 [Flare] Redesign core event system (#16163) 2019-07-23 23:46:44 +01:00
Dominic Gannaway 2c4d61e102 Adds experimental fundamental interface (#16049) 2019-07-19 22:20:28 +01:00
Dominic Gannaway 67e3f3fb6e [Flare] Revise responder event types (#16081) 2019-07-08 14:35:59 +01:00
Dominic Gannaway c64f40d718 [Flare] Remove dead event target code (#16063) 2019-07-04 13:10:55 +01:00
Sunil Pai a457e02ae3 allow nested act()s from different renderers (#16039)
* allow nested `act()`s from different renderers

There are usecases where multiple renderers need to oprate inside an act() scope
- ReactDOM.render being used inside another component tree. The parent component will be rendered using ReactTestRenderer.create for a snapshot test or something.
- a ReactDOM instance interacting with a ReactTestRenderer instance (like for the new devtools)

This PR changes the way the acting sigils operate to allow for this. It keeps 2 booleans, one attached to React, one attached to the renderer. act() changes these values, and the workloop reads them to decide what warning to trigger.

I also renamed shouldWarnUnactedUpdates to warnsIfNotActing

* s/ReactIsActing/IsSomeRendererActing and s/ReactRendererIsActing/IsThisRendererActing
2019-07-02 22:20:17 +01:00
Dominic Gannaway eb2ace1281 [Flare] Bring Flare support to React Native Fabric (#15887) 2019-06-28 01:22:32 +01:00
Dominic Gannaway 8b88ac2592 [Flare] Remove event targets including TouchHitTarget (#16011) 2019-06-27 23:58:48 +01:00
Andrew Clark 4d307de458 Prefix mock Scheduler APIs with _unstable (#15999)
For now this is only meant to be consumed via `act`.
2019-06-26 12:16:08 -07:00
Sunil Pai fce15f14d3 don't fire missing act() warnings for react-art (#15975)
* use toWarnDev for dom fixture tests

forks toWarnDev from root into fixture/dom, updates tes tests to use it

* disable act() warnings for react-art()

- For 'secondary' renderers like react-act, we don't want to fire missing act() warnings; the wrapping renderer will fire warnings anyway, and when it flushes, it flushes effects *across* renderers.

- I could have used isPrimaryRenderer as the flag, but this is marked as false for react-test-renderer, and we *do* want the warning to fire for it. Hence a new flag.

* add missing dependency `art` to fixtures/dom
2019-06-24 19:18:26 +01:00
Andrew Clark 6568a79931 [Scheduler] requestPaint (#15960)
* [Scheduler] requestPaint

Signals to Scheduler that the browser needs to paint the screen. React
will call it in the commit phase. Scheduler will yield at the end of
the current frame, even if there is no pending input.

When `isInputPending` is not available, this has no effect, because we
yield at the end of every frame regardless.

React will call `requestPaint` in the commit phase as long as there's at
least one effect. We could choose not to call it if none of the effects
are DOM mutations, but this is so rare that it doesn't seem worthwhile
to bother checking.

* Fall back gracefully if requestPaint is missing
2019-06-22 00:15:09 -07:00
Andrew Clark 862f499fac Add Batched Mode (#15502)
* Add Batched Mode

React has an unfortunate quirk where updates are sometimes synchronous
-- where React starts rendering immediately within the call stack of
`setState` — and sometimes batched, where updates are flushed at the
end of the current event. Any update that originates within the call
stack of the React event system is batched. This encompasses most
updates, since most updates originate from an event handler like
`onClick` or `onChange`. It also includes updates triggered by lifecycle
methods or effects. But there are also updates that originate outside
React's event system, like timer events, network events, and microtasks
(promise resolution handlers). These are not batched, which results in
both worse performance (multiple render passes instead of single one)
and confusing semantics.

Ideally all updates would be batched by default. Unfortunately, it's
easy for components to accidentally rely on this behavior, so changing
it could break existing apps in subtle ways.

One way to move to a batched-by-default model is to opt into Concurrent
Mode (still experimental). But Concurrent Mode introduces additional
semantic changes that apps may not be ready to adopt.

This commit introduces an additional mode called Batched Mode. Batched
Mode enables a batched-by-default model that defers all updates to the
next React event. Once it begins rendering, React will not yield to
the browser until the entire render is finished.

Batched Mode is superset of Strict Mode. It fires all the same warnings.
It also drops the forked Suspense behavior used by Legacy Mode, in favor
of the proper semantics used by Concurrent Mode.

I have not added any public APIs that expose the new mode yet. I'll do
that in subsequent commits.

* Suspense in Batched Mode

Should have same semantics as Concurrent Mode.

* Use RootTag field to configure type of root

There are three types of roots: Legacy, Batched, and Concurrent.

* flushSync should not flush batched work

Treat Sync and Batched expiration times separately. Only Sync updates
are pushed to our internal queue of synchronous callbacks.

Renamed `flushImmediateQueue` to `flushSyncCallbackQueue` for clarity.
2019-05-13 14:30:39 -07:00
Dominic Gannaway aece8119cf Refactor EventComponent logic + add onOwnershipChange callback (#15354) 2019-04-09 12:47:32 +01:00
Dominic Gannaway 4064ea9fa6 Experimental event API: Support EventComponent onUnmount responder callback (#15335) 2019-04-06 08:16:57 +01:00
Dominic Gannaway 4fbbae8afa Add full TouchHitTarget hit slop (experimental event API) to ReactDOM (#15308) 2019-04-06 07:51:21 +01:00
Dominic Gannaway 6a1e6b2f78 Experimental event API: loosen EventTarget constraints and warnings (#15292)
* Remove warning for event targets being direct children of event component

* Addressed feedback and added more test coverage + warnings
2019-04-02 19:49:28 +01:00
Dominic Gannaway b83e01cade Adds more scaffolding for experimental event API (#15112)
* Adds more scaffolding for experimental event API
2019-03-20 11:20:17 +00:00
Dominic Gannaway 0c03a47436 Adds experimental event API scaffolding (#15108)
* Adds experimental event API scaffolding
2019-03-14 17:02:42 +00:00
Andrew Clark 1e3b6192b5 Import Scheduler directly, not via host config (#14984)
* Import Scheduler directly, not via host config

We currently schedule asynchronous tasks via the host config. (The host
config is a static/build-time dependency injection system that varies
across different renderers — DOM, native, test, and so on.) Instead of
calling platform APIs like `requestIdleCallback` directly, each renderer
implements a method called `scheduleDeferredCallback`.

We've since discovered that when scheduling tasks, it's crucial that
React work is placed in the same queue as other, non-React work on the
main thread. Otherwise, you easily end up in a starvation scenario where
rendering is constantly interrupted by less important tasks. You need a
centralized coordinator that is used both by React and by other
frameworks and application code. This coordinator must also have a
consistent API across all the different host environments, for
convention's sake and so product code is portable — e.g. so the same
component can work in both React Native and React Native Web.

This turned into the Scheduler package. We will have different builds of
Scheduler for each of our target platforms. With this approach, we treat
Scheduler like a built-in platform primitive that exists wherever React
is supported.

Now that we have this consistent interface, the indirection of the host
config no longer makes sense for the purpose of scheduling tasks. In
fact, we explicitly do not want renderers to scheduled task via any
system except the Scheduler package.

So, this PR removes `scheduleDeferredCallback` and its associated
methods from the host config in favor of directly importing Scheduler.

* Missed an extraneous export
2019-03-06 14:41:45 -08:00
Andrew Clark 757a70b25d ReactNoop.yield -> Scheduler.yieldValue (#15008)
These used to be different things, but now ReactNoop.yield merely
re-exports Scheduler.yieldValue, so let's get rid of it.
2019-03-04 11:23:00 -08:00
Dan Abramov 02404d793b Avoid dynamic dispatch for scheduler calls (#14968) 2019-03-01 15:04:15 +00:00
Andrew Clark 69060e1da6 Swap expect(ReactNoop) for expect(Scheduler) (#14971)
* Swap expect(ReactNoop) for expect(Scheduler)

In the previous commits, I upgraded our custom Jest matchers for the
noop and test renderers to use Scheduler under the hood.

Now that all these matchers are using Scheduler, we can drop
support for passing ReactNoop and test roots and always pass
Scheduler directly.

* Externalize Scheduler in noop and test bundles

I also noticed we don't need to regenerator runtime in noop anymore.
2019-02-28 12:54:47 -08:00
Andrew Clark 8e25ed20bd Unify noop and test renderer assertion APIs (#14952)
* Throw in tests if work is done before emptying log

Test renderer already does this. Makes it harder to miss unexpected
behavior by forcing you to assert on every logged value.

* Convert ReactNoop tests to use jest matchers

The matchers warn if work is flushed while the log is empty. This is
the pattern we already follow for test renderer. I've used the same APIs
as test renderer, so it should be easy to switch between the two.
2019-02-25 19:01:45 -08:00