Commit Graph

6 Commits

Author SHA1 Message Date
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
e91dd70ba2
Remove disableYielding feature flag (#15654)
Obviated by Batched Mode.
2019-06-13 15:58:40 -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
Andrew Clark
71c8759ceb
Measure callback timeout relative to current time (#15479)
Fixes a bug where the timeout passed to `scheduleCallback` represented
an absolute timestamp, instead of the amount of time until that
timestamp is reached. The solution is to subtract the current time
from the expiration.

The bug wasn't caught by other tests because we use virtual times that
default to 0, and most tests don't advance time.

I also moved the `initialTimeMs` offset to the
`SchedulerWithReactIntegration` module so that we don't have to remember
to subtract the offset every time. (We should consider upstreaming this
to the Scheduler package.)
2019-04-23 16:40:55 -07:00
Andrew Clark
9055e31e5c
Replace old Fiber Scheduler with new one (#15387)
The new Fiber Scheduler has been running in Facebook for several days
without issues. Let's switch to it.
2019-04-11 19:15:34 -07:00
Andrew Clark
4d5cb64aa2
Rewrite ReactFiberScheduler for better integration with Scheduler package (#15151)
* Rewrite ReactFiberScheduler

Adds a new implementation of ReactFiberScheduler behind a feature flag.
We will maintain both implementations in parallel until the new one
is proven stable enough to replace the old one.

The main difference between the implementations is that the new one is
integrated with the Scheduler package's priority levels.

* Conditionally add fields to FiberRoot

Some fields only used by the old scheduler, and some by the new.

* Add separate build that enables new scheduler

* Re-enable skipped test

If synchronous updates are scheduled by a passive effect, that work
should be flushed synchronously, even if flushPassiveEffects is
called inside batchedUpdates.

* Passive effects have same priority as render

* Revert ability to cancel the current callback

React doesn't need this anyway because it never schedules callbacks if
it's already rendering.

* Revert change to FiberDebugPerf

Turns out this isn't neccessary.

* Fix ReactFiberScheduler dead code elimination

Should initialize to nothing, then assign the exports conditionally,
instead of initializing to the old exports and then reassigning to the
new ones.

* Don't yield before commit during sync error retry

* Call Scheduler.flushAll unconditionally in tests

Instead of wrapping in enableNewScheduler flag.
2019-04-02 15:49:07 -07:00