809 Commits

Author SHA1 Message Date
Andrew Clark 349cf5acc3 Experimental test helper: it.experimental (#17149)
Special version of Jest's `it` for experimental tests. Tests marked as
experimental will run **both** stable and experimental modes. In
experimental mode, they work the same as the normal Jest methods. In
stable mode, they are **expected to fail**. This means we can detect
when a test previously marked as experimental can be un-marked when the
feature becomes stable. It also reduces the chances that we accidentally
add experimental APIs to the stable builds before we intend.

I added corresponding methods for the focus and skip APIs:

- `fit` -> `fit.experimental`
- `it.only` -> `it.only.experimental` or `it.experimental.only`
- `xit` -> `xit.experimental`
- `it.skip` -> `it.skip.experimental` or `it.experimental.skip`

Since `it` is an alias of `test`, `test.experimental` works, too.
2019-10-19 16:08:08 -07:00
Sebastian Markbåge 68fb58029d Remove unstable_ prefix in various internal uses (#17146)
* Rename unstable_createRoot in DevTools

* Rename createSyncRoot in warning
2019-10-18 17:18:10 -07:00
Andrew Clark c47f59331e Move SuspenseList to experimental package (#17130)
Also moves `withSuspenseConfig`
2019-10-18 14:24:13 -07:00
Luna Ruan 685ed561f2 Migrate useDeferredValue and useTransition (#17058)
Migrated useDeferredValue and useTransition from Facebook's www repo into ReactFiberHooks.
2019-10-18 12:48:43 -07:00
Andrew Clark 7cec15155a Remove prefixed concurrent APIs from www build (#17108)
The downstream callers have been updated, so we can remove these.
2019-10-16 18:58:33 -07:00
Sebastian Markbåge ed5f010ae5 Client render Suspense content if there's no boundary match (#16945)
Without the enableSuspenseServerRenderer flag there will never be a boundary match. Also when it is enabled, there might not be a boundary match if something was conditionally rendered by mistake.

With this PR it will now client render the content of a Suspense boundary in that case and issue a DEV only hydration warning. This is the only sound semantics for this case.

Unfortunately, landing this will once again break #16938. It will be less bad though because at least it'll just work by client rendering the content instead of hydrating and issue a DEV only warning.

However, we must land this before enabling the enableSuspenseServerRenderer flag since it does this anyway.

I did notice that we special case fallback={undefined} due to our unfortunate semantics for that. So technically a workaround that works is actually setting the fallback to undefined on the server and during hydration. Then flip it on only after hydration. That could be a workaround if you want to be able to have a Suspense boundary work only after hydration for some reason.

It's kind of unfortunate but at least those semantics are internally consistent. So I added a test for that.
2019-10-16 16:23:12 -07:00
Andrew Clark d7feeb25ac unstable_createRoot -> createRoot in test (#17107)
Fixes test added in #17105, which was based on an earler commit than the
one that removed the `unstable_` prefix from `createRoot`.
2019-10-15 21:37:54 -07:00
Sebastian Markbåge 6ff23f2a5d Change retry priority to "Never" for dehydrated boundaries (#17105)
This changes the "default" retryTime to NoWork which schedules at Normal
pri.

Dehydrated bouundaries normally hydrate at Never priority except when they
retry where we accidentally increased them to Normal because Never was used
as the default value. This changes it so NoWork is the default.

Dehydrated boundaries however get initialized to Never as the default.

Therefore they now hydrate as Never pri unless their priority gets
increased by a forced rerender or selective hydration.

This revealed that erroring at this Never priority can cause an infinite
rerender. So I fixed that too.
2019-10-15 19:53:20 -07:00
Andrew Clark 43562455c9 Temporary patch www fork with prefixed APIs (#17103)
I'm doing this here instead of in the downstream repo so that if the
sync diff gets reverted, it doesn't revert this, too.

Once the sync has landed, and the callers are updated in www, I will
remove this.
2019-10-15 16:44:33 -07:00
Andrew Clark 30c5daf943 Remove concurrent apis from stable (#17088)
* Tests run in experimental mode by default

For local development, you usually want experiments enabled. Unless
the release channel is set with an environment variable, tests will
run with __EXPERIMENTAL__ set to `true`.

* Remove concurrent APIs from stable builds

Those who want to try concurrent mode should use the experimental
builds instead.

I've left the `unstable_` prefixed APIs in the Facebook build so we
can continue experimenting with them internally without blessing them
for widespread use.

* Turn on SSR flags in experimental build

* Remove prefixed concurrent APIs from www build

Instead we'll use the experimental builds when syncing to www.

* Remove "canary" from internal React version string
2019-10-15 15:09:19 -07:00
Krzysztof Kotowicz fdba0e5ce7 Fixed a bug with illegal invocation for Trusted Types (#17083)
* Fixed a bug with illegal invocation.

* Fixed the test.
2019-10-15 11:41:42 +01:00
Andrew Clark d364d8555f Set up experimental builds (#17071)
* Don't bother including `unstable_` in error

The method names don't get stripped out of the production bundles
because they are passed as arguments to the error decoder.

Let's just always use the unprefixed APIs in the messages.

* Set up experimental builds

The experimental builds are packaged exactly like builds in the stable
release channel: same file structure, entry points, and npm package
names. The goal is to match what will eventually be released in stable
as closely as possible, but with additional features turned on.

Versioning and Releasing
------------------------

The experimental builds will be published to the same registry and
package names as the stable ones. However, they will be versioned using
a separate scheme. Instead of semver versions, experimental releases
will receive arbitrary version strings based on their content hashes.
The motivation is to thwart attempts to use a version range to match
against future experimental releases. The only way to install or depend
on an experimental release is to refer to the specific version number.

Building
--------

I did not use the existing feature flag infra to configure the
experimental builds. The reason is because feature flags are designed
to configure a single package. They're not designed to generate multiple
forks of the same package; for each set of feature flags, you must
create a separate package configuration.

Instead, I've added a new build dimension called the **release
channel**. By default, builds use the **stable** channel. There's
also an **experimental** release channel. We have the option to add more
in the future.

There are now two dimensions per artifact: build type (production,
development, or profiling), and release channel (stable or
experimental). These are separate dimensions because they are
combinatorial: there are stable and experimental production builds,
stable and experimental developmenet builds, and so on.

You can add something to an experimental build by gating on
`__EXPERIMENTAL__`, similar to how we use `__DEV__`. Anything inside
these branches will be excluded from the stable builds.
This gives us a low effort way to add experimental behavior in any
package without setting up feature flags or configuring a new package.
2019-10-14 10:46:42 -07:00
Dominic Gannaway b71ab61c8f [react-interactions] Adds more experimental Scope API methods (#17042) 2019-10-08 19:32:53 +02:00
Andrew Clark 71d012ecd0 Remove dormant createBatch experiment (#17035)
* Remove dormant createBatch experiment

In a hybrid React app with multiple roots, `createBatch` is used to
coordinate an update to a root with its imperative container.

We've pivoted away from multi-root, hybrid React apps for now to focus
on single root apps.

This PR removes the API from the codebase. It's possible we'll add back
some version of this feature in the future.

* Remove unused export
2019-10-07 14:15:15 -07:00
Luna Ruan 4bc52ef0df Revert "update hideOrUnhideAllChildren to hide portals that aren't wrapped in a host component (#16992)" (#17011)
This reverts commit de2edc268d.
2019-10-03 17:22:22 -07:00
Sebastian Markbåge 3a2b5f148d [Selective Hydration] ReactDOM.unstable_scheduleHydration(domNode) (#17004)
Adds an API to explicitly prioritize hydrating the path to a particular DOM node without relying on events to do it.

The API uses the current scheduler priority to schedule it. For the same priority, the last one wins. This allows a similar effect as continuous events. This is useful for example to hydrate based on scroll position, or prioritize components that will upgrade to client-rendered-only content.

I considered having an API that explicitly overrides the current target(s). However that makes it difficult to coordinate across components in an app.

This just hydrates one target at a time but if it is blocked on I/O we could consider increasing priority of later targets too.
2019-10-03 14:48:28 -07:00
Dominic Gannaway 26ba38ae4b [EnterLeaveEventPlugin] Fix bug when dealing with unhandled DOM nodes (#17006) 2019-10-03 23:35:09 +02:00
Andrew Clark d256f88ac6 Update local version numbers for 16.10.2 release 2019-10-03 14:14:10 -07:00
Dominic Gannaway 4c5698400f [react-interactions] Remove context.setTimeout & context.clearTimeout (#17000) 2019-10-03 13:37:37 +02:00
Luna Ruan de2edc268d update hideOrUnhideAllChildren to hide portals that aren't wrapped in a host component (#16992)
Currently, when a node suspends, if its subtree contains a portal, the portal is not hidden. This hides portals in the subtree when it's not wrapped in a host component .
2019-10-02 15:30:55 -07:00
Sebastian Markbåge bb680a0905 [Selective Hydration] Prioritize the last continuous target (#16937)
* Prioritize the last continuous target

This ensures that the current focus target is always hydrated first.

Slightly higher than the usual Never expiration time used for hydration.
The priority increases with each new queued item so that the last always
wins.

* Don't export the moving target

It's not useful for comparison purposes anyway.
2019-10-02 14:52:23 -07:00
Nicolas Gallagher ab1a4f249e Move eventSystemFlags to last argument in event plugin extractors (#16978)
Fix for necolas/react-native-web#1443
2019-10-02 10:31:15 -07:00
Rango Yuan b34f042e5b Fix mouseenter handlers fired twice (#16928) 2019-10-01 14:03:14 +02:00
Andrew Clark 2a264a9dbe Update local version numbers for 16.10.1 release 2019-09-28 21:41:42 -07:00
Sebastian Markbåge d8a76ad580 Allow Suspense Mismatch on the Client to Silently Proceed (#16943)
* Regression test: Suspense + hydration + legacy

* Allow Suspense Mismatch on the Client to Silently Proceed

This fixes but isn't actually the semantics that we want this case to have.
2019-09-28 10:43:53 -07:00
Sebastian Markbåge 9d637844e9 Remove enableUserBlockingEvents flag (#16882)
Seems like this worked out. We can clean up the flag now.
2019-09-27 19:46:56 -07:00
Sebastian Markbåge fe31cc710e [Selective Hydration] Increase priority for non-synchronous discrete events and retries (#16935)
* Increase retryTime for increased priority dehydrated boundaries

* Increaese the priority to user blocking for every next discrete boundary
2019-09-27 17:27:17 -07:00
Andrew Clark 93f5f11b79 Update local version numbers for 16.10 release 2019-09-27 13:31:35 -07:00
Luna Ruan c8dc7a926e expose isHydrating (#16909)
expose isHydrating for FB
2019-09-26 14:47:01 -07:00
Sebastian Markbåge 3694a3b5e9 Selective Hydration (#16880)
* Add Feature Flag for Selective Hydration

* Enable Synchronous Hydration of Discrete Events

* Resolve cyclic dependency
2019-09-25 15:26:27 -07:00
Dominic Gannaway d6d83d7060 [react-interactions] Add Portal propagation configuration (#16889) 2019-09-25 16:56:51 +02:00
Jessica Franco 18d2e0c03e Warning system refactoring (part 1) (#16799)
* Rename lowPriorityWarning to lowPriorityWarningWithoutStack

This maintains parity with the other warning-like functions.

* Duplicate the toWarnDev tests to test toLowPriorityWarnDev

* Make a lowPriorityWarning version of warning.js

* Extract both variants in print-warning

Avoids parsing lowPriorityWarning.js itself as the way it forwards the
call to lowPriorityWarningWithoutStack is not analyzable.
2019-09-24 13:45:38 +01:00
Sebastian Markbåge 0a527707cd Event Replaying (#16725)
* Add Event Replaying Infra

* Wire up Roots and Suspense boundaries, to retry events, after they commit

* Replay discrete events in order in a separate scheduler callback

* Add continuous events

These events only replay their last target if the target is not yet
hydrated. That way we don't have to wait for a previously hovered
boundary before invoking the current target.

* Enable tests from before

These tests were written with replaying in mind and now we can properly
enable them.

* Unify replaying and dispatching

* Mark system flags as a replay and pass to legacy events

That way we can check if this is a replay and therefore needs a special
case. One such special case is "mouseover" where we check the
relatedTarget.

* Eagerly listen to all replayable events

To minimize breakages in a minor, I only do this for the new root APIs
since replaying only matters there anyway. Only if hydrating.

For Flare, I have to attach all active listeners since the current
system has one DOM listener for each. In a follow up I plan on optimizing
that by only attaching one if there's at least one active listener
which would allow us to start with only passive and then upgrade.

* Desperate attempt to save bytese

* Add test for mouseover replaying

We need to check if the "relatedTarget" is mounted due to how the old
event system dispatches from the "out" event.

* Fix for nested boundaries and suspense in root container

This is a follow up to #16673 which didn't have a test because it wasn't
observable yet. This shows that it had a bug.

* Rename RESPONDER_EVENT_SYSTEM to PLUGIN_EVENT_SYSTEM
2019-09-23 11:21:10 -07:00
Dominic Gannaway 924a305780 [react-ui] Remove event object warnings (#16822) 2019-09-19 12:46:17 +02:00
halvves a5df18a9e5 prevent firefox marking required textareas invalid (#16578)
* prevent firefox marking required textareas invalid

Bug was caused by an IE10/IE11 bugfix dealing with the placeholder attribute and textContent. Solved by avoiding the IE bugfix when textContent was empty.

Closes #16402

* more explicit conditional check for textContent

re: @philipp-spiess code review

* clarify textarea test fixture's expected result

better describe the behavior we are testing for
re: @philipp-spiess code review
2019-09-18 14:38:02 -07:00
Dan Abramov 8e0c574122 Follow-up to initial Trusted Types support (#16795)
* Follow-up to initial Trusted Types support

* Fast-path both strings and numbers

* Move shared objects out of every test
2019-09-17 16:06:26 +01:00
Dominic Gannaway 494300b366 [react-ui] Move experimental event+a11y work to react-ui package (#16794) 2019-09-16 20:05:50 +02:00
Emanuel Tesař b8d079b413 Add trusted types to react on client side (#16157)
* Add trusted types to react on client side

* Implement changes according to review

* Remove support for trusted URLs, change TrustedTypes to trustedTypes

* Add support for deprecated trusted URLs

* Apply PR suggesstions

* Warn only once, remove forgotten check, put it behind a flag

* Move comment

* Fix PR comments

* Fix html toString concatenation

* Fix forgotten else branch

* Fix PR comments
2019-09-16 13:43:22 +01:00
Dominic Gannaway b4b8a349a3 [react-interactions] Add experimental FocusGrid API (#16766) 2019-09-13 12:29:39 +02:00
Dominic Gannaway 4b0b556dcf [react-interactions] Refactor TabFocusController (#16768) 2019-09-12 22:28:07 +02:00
Dominic Gannaway 35a202d0e7 [react-events] Ensure we restore currentInstance + currentTimers (#16758) 2019-09-12 12:44:05 +02:00
Dominic Gannaway 3717c25a7e [react-interactions] More Tab Focus control handling (#16751) 2019-09-11 22:35:33 +02:00
Dominic Gannaway ae724be7be [react-interactions] Add TabFocusContainer and TabbableScope UI components (#16732) 2019-09-11 12:46:41 +02:00
Sebastian Markbåge b0a8a3e041 Mark root as already hydrated after committing (#16739)
* Mark root as already hydrated after committing

* Remove current/child check for hydration and rely on the root flag instead
2019-09-10 20:02:02 -07:00
Dominic Gannaway fd3e8cb0ae [react-events] Remove stopPropagation (Press) + use document for delegation (#16730) 2019-09-10 20:31:24 +02:00
Heaven 9444c876d5 Remove wrong copy-paste code in test (#16695) 2019-09-09 11:34:08 +01:00
Sebastian Markbåge e11bf42cea Check for Suspense boundary in a root Container (#16673)
If we find a Container that might mean that we're on a node that is inside
a Suspense boundary that is directly inside the Container root.

Imagine the div is a Container and the span is a dehydrated instance:

```
<div>
  <!--$-->
  <span />
  <!--/$-->
</div>
```

There's no way to tests this yet since I'm not actually utilizing
the return value yet.

The solution is to just use the same path to check for a Suspense boundary
as if we find a parent instance.
2019-09-05 16:06:05 -07:00
Nicolas Gallagher ff006451ad [react-events] Fix isTargetWithinNode type (#16671)
isTargetWithinNode passes the childTarget to getClosestInstanceFromNode which
does not account for a null value of 'node'.
2019-09-05 11:36:31 -07:00
Sebastian Markbåge 8d7c733f1f [Partial Hydration] Don't invoke listeners on parent of dehydrated event target (#16591)
* Don't invoke listeners on parent of dehydrated event target

* Move Suspense boundary check to getClosestInstanceFromNode

Now getClosestInstanceFromNode can return either a host component,
host text component or suspense component when the suspense
component is dehydrated.

We then use that to ignore events on a suspense component.

* Attach the HostRoot fiber to the DOM container

This lets us detect if an event happens on this root's subtree before it
has rendered something.

* Add todo

The approach of checking isFiberMounted answers if we might be in an
in-progress hydration but it doesn't answer which root or boundary
might be in-progress so we don't know what to wait for.

This needs some refactoring.

* Refactor isFiberMountedImpl to getNearestMountedFiber

We'll need the nearest boundary for event replaying so this prepares for
that.

This surfaced an issue that we attach Hydrating tag on the root but normally
this (and Placement) is attached on the child. This surfaced an issue
that this can lead to both Placement and Hydrating effects which is not
supported so we need to ensure that we only ever use one or the other.

* Add todo for bug I spotted

* Cache tags

* Check the ContainerInstanceKey before the InstanceKey

The container is inside the instance, so we must find it before the
instance, since otherwise we'll miss it.
2019-09-05 08:51:31 -07:00
Nicolas Gallagher 9ce8711d5a [react-events] Tap responder (#16628)
This is a partial replacement for the 'Press' responder:

1. `useTap` is scoped to pointers (no keyboard support). Our current thinking is
that "responders" should be limited to working with pointers, and that they can
be combined with 'useKeyboard' in user-space. For example, we might create a
'usePress' hook in user-space that combines 'useTap' with 'useKeyboard' to react
to both pointers and keyboard interactions.

2. `useTap` cancels the gesture once the pointer moves over an element that is
not within the responder target's subtree. This differs from `usePress` (and
React Native), where the gesture remains active after the pointer exits the
target's subtree and is restarted once the pointer reenters. One of the
drawbacks with the `usePress` behavior is that it requires repeatedly measuring
DOM elements (which can cause jank) to perform hit region tests. `useTap` avoids
doing this and relies on `document.elementFromPoint` only to support the
TouchEvent fallbacks.

3. `useTap` calls `onTapUpdate` when the active gesture's state changes,
`onTapEnd` when the gesture successfully completes. and `onTapCancel` when it
fails. There is no `onTap` callback. `usePress` did not explicitly report back
when the gesture failed, and product developers were confused about the
difference between `onPress` and `onPressEnd`.

4. `useTap` explicitly separates the PointerEvent implementation from the
MouseEvent/TouchEvent fallback.

5. `useTap` has better unit test coverage . All pointer types and the fallback
environment are tested. The shape of the gesture state object is also defined
and tested.
2019-09-04 17:09:33 -07:00