This code is being compiled incorrectly by something in the Facebook
build pipeline. I'm removing it temporarily to unblock the sync while
we investigate.
Currently this is getting marked as Never which is the normal continuation
for a dehydrated boundary, but if it is client-rendered it has a higher
priority. That causes us to drop the interaction tracing for that render.
This colocates the marking where we actually set the expiration time.
**Problem**
The existing responders listen to pointer events by default and add fallback events if PointerEvent is not supported. However, this complicates the responders and makes it easy to create a problematic unit test environment. jsdom doesn't support PointerEvent, which means that the responders end up listening to pointer events *and* fallback events in unit tests. This isn't a direct problem in production environments, because no browser will fire pointer events if they aren't supported. But in the unit test environment, we often dispatch event sequences taken from browsers that support pointer events. This means that what we're often testing is actually a (complex) scenario that cannot even occur in production: a responder that is listening to and receives both pointer events and fallback events. Not only does this risk making responders more complicated to implement but it could also hide bugs in implementations.
**Response**
Implement the responders so that they're only listening to *either* pointer events *or* fallback events, never both. This should make the default pointer events implementations significantly simpler and easier to test, as well as free to rely on the complete PointerEvents API. In the future it should also make DCE easier for target environments that are known to support PointerEvents, as we can use build tools with an equivalent of the runtime check. The fallback events (touch and mouse) need to coexist and be resilient to browser emulated events. Our unit tests should express a suite of high-level interactions that can be run in environments with and without PointerEvents support.
These were discovered by @SimenB in https://github.com/facebook/react/pull/16332. We weren't making actual assertions on some values. This PR makes the assertions, and fixes the tests.
In a previous version of act(), we used a dummy dom element to flush effects. This doesn't need to exist anymore, and this PR removes it. The warning doesn't need to be there either (React will fire a wrong renderer act warning if needed).
When React detects a deprectated/unsafe lifecycle method, the warning points to a page with more details on the why/what of the warning. However, the actual link (https://fb.me/react-async-component-lifecycle-hooks) uses the phrase "lifecycle-hooks" which is confusing since it doesn't have anything to do with hooks. This PR changes the link to something less confusing - https://fb.me/react-unsafe-component-lifecycles.
Upgraded from Babel 6 to Babel 7.
The only significant change seems to be the way `@babel/plugin-transform-classes` handles classes differently from `babel-plugin-transform-es2015-classes`. In regular mode, the former injects a `_createClass` function that increases the bundle size, and in the latter it removes the safeguard checks. However, this is okay because we don't all classes in new features, and we want to deprecate class usage in the future in the react repo.
Co-authored-by: Luna Ruan <luna@fb.com>
Co-authored-by: Abdul Rauf <abdulraufmujahid@gmail.com>
Co-authored-by: Maksim Markelov <maks-markel@mail.ru>
* [Scheduler] Store Tasks on a Min Binary Heap
Switches Scheduler's priority queue implementation (for both tasks and
timers) to an array-based min binary heap.
This replaces the naive linked-list implementation that was left over
from the queue we once used to schedule React roots. A list was arguably
fine when it was only used for roots, since the total number of roots is
usually small, and is only 1 in the common case of a single-page app.
Since Scheduler is now used for many types of JavaScript tasks (e.g.
including timers), the total number of tasks can be much larger.
Binary heaps are the standard way to implement priority queues.
Insertion is O(1) in the average case (append to the end) and O(log n)
in the worst. Deletion is O(log n). Peek is O(1).
* Sophie nits
We might reenter a hydration state, when attempting to hydrate a boundary.
We need to ensure that we reset it to not hydrating once we exit it.
Otherwise the next sibling will still be in hydration mode.
This happens in this case: `<!--$!--><!--$!-->...<!--/$--><!--/$-->...`
getNextHydratableInstanceAfterSuspenseInstance didn't take
SUSPENSE_FALLBACK_START_DATA or SUSPENSE_PENDING_START_DATA into account
so if a boundary was in one of those states, it wouldn't be considered to
push the stack of boundaries. As a result the first end comment was
considered the end but it really should've been the second end comment.
The next comment then would've been considered something that can be
skipped. However, since the logic in there considered all comments as
"hydratable", it was considered a hydratable node. Since it was considered
a node that didn't actually correspond to anything in the React tree it got
deleted.
The HTML is now `<!--$!--><!--$!-->...<!--/$-->...` and the trailing
content is now hydrated since it did match something.
Next, since this was client rendered, we're going to delete the suspended
boundary by calling clearSuspenseBoundary and then inserting new content.
However, clearSuspenseBoundary *is* aware of SUSPENSE_FALLBACK_START_DATA
and assumes that there must be another `<!--/$-->` after the first one.
As a result it deleted the trailing content from the DOM since it should
be part of the boundary. However, those DOM nodes were already hydrated in
the React tree. So we end up in an inconsistent state.
When we then try to insert the new content we throw as a result.
I think we would have recovered correctly if clearSuspenseBoundary and
getNextHydratableInstanceAfterSuspenseInstance had the *same* bug but
because they were inconsistent we ended up in a bad place.
We have behaviour divergence for act() between prod and dev (specifically, act() + concurrent mode does not flush fallbacks in prod. This doesn't affect anyone in OSS yet)
We also don't have a good story for writing tests in prod (and what from what I gather, nobody really writes tests in prod mode).
We could have wiped out act() in prod builds, except that _we_ ourselves use act() for our tests when we run them in prod mode.
This PR is a compromise to all of this. We will log a warning if you try to use act() in prod mode, and we silence it in our test suites.
When React schedules a rendering task, it passes a `timeout` option
based on its expiration time. This is intended to avoid starvation
by other React updates. However, it also affects the relative priority
of React tasks and other Scheduler tasks at the same level, like
data processing.
This adds a feature flag to disable passing a `timeout` option to
Scheduler. React tasks will always append themselves to the end of
the queue, without jumping ahead of already scheduled tasks.
This does not affect the order in which React updates within a single
root are processed, but it could affect updates across multiple roots.
This also doesn't remove the expiration from Scheduler. It only means
that React tasks are not given special treatment.
Previously, the suspense priority warning was fired even if the Root wasn't suspended. Changed the warning to fire only when the root is suspended.
Also refactored the suspense priority warning so it's easier to read.
The clean-up function of a passive effect (`useEffect`) usually fires
in a post-commit task, after the browser has painted. However, there is
an exception when the component (or its parent) is deleted from the
tree. In that case, we fire the clean-up function during the
synchronous commit phase, the same phase we use for layout effects.
This is a concession to implementation complexity. Calling it in the
passive effect phase would require either traversing the children of the
deleted fiber again, or including unmount effects as part of the fiber
effect list.
Because the functions are called during the sync phase in this case,
the Scheduler priority is Immediate (the one used for layout) instead
of Normal. We may want to reconsider this trade off later.
If there are adjacent updates we bail out of rendering the suspense list
at all but we may still complete the node. We need to reset the render
state in that case.
I restructured so that this is in the same code path so we don't forget it
in the future.
* Add a feature flag to disable legacy context
* Address review
- invariant -> warning
- Make this.context and context argument actually undefined
* Increase test coverage for lifecycles
* Also disable it on the server is flag is on
* Make this.context {} when disabled, but function context is undefined
* Move checks inside