Skip to content

Commit 238402d

Browse files
rickhanloniityao1
authored andcommitted
Add frame-end scheduling (V3)
1 parent 6513469 commit 238402d

33 files changed

+625
-23
lines changed

packages/jest-react/src/internalAct.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ export function act<T>(scope: () => Thenable<T> | T): Thenable<T> {
106106
let didFlushWork;
107107
do {
108108
didFlushWork = Scheduler.unstable_flushAllWithoutAsserting();
109+
110+
// Flush scheduled rAF.
111+
if (global.flushRequestAnimationFrameQueue) {
112+
global.flushRequestAnimationFrameQueue();
113+
}
109114
} while (didFlushWork);
110115
return {
111116
then(resolve, reject) {
@@ -144,6 +149,10 @@ function flushActWork(resolve, reject) {
144149
// $FlowFixMe: Flow doesn't know about global Jest object
145150
jest.runOnlyPendingTimers();
146151
if (Scheduler.unstable_hasPendingWork()) {
152+
// Flush scheduled rAF.
153+
if (global.flushRequestAnimationFrameQueue) {
154+
global.flushRequestAnimationFrameQueue();
155+
}
147156
// Committing a fallback scheduled additional work. Continue flushing.
148157
flushActWork(resolve, reject);
149158
return;

packages/react-dom-bindings/src/client/ReactDOMHostConfig.js

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,11 @@ import {
7474
} from 'react-reconciler/src/ReactWorkTags';
7575
import {listenToAllSupportedEvents} from '../events/DOMPluginEventSystem';
7676

77-
import {DefaultEventPriority} from 'react-reconciler/src/ReactEventPriorities';
77+
import {UnknownEventPriority} from 'react-reconciler/src/ReactEventPriorities';
7878

7979
// TODO: Remove this deep import when we delete the legacy root API
8080
import {ConcurrentMode, NoMode} from 'react-reconciler/src/ReactTypeOfMode';
81+
import * as Scheduler from 'scheduler';
8182

8283
import {
8384
prepareToRenderResources,
@@ -373,7 +374,7 @@ export function createTextInstance(
373374
export function getCurrentEventPriority(): EventPriority {
374375
const currentEvent = window.event;
375376
if (currentEvent === undefined) {
376-
return DefaultEventPriority;
377+
return UnknownEventPriority;
377378
}
378379
return getEventPriority(currentEvent.type);
379380
}
@@ -393,6 +394,11 @@ const localRequestAnimationFrame =
393394
typeof requestAnimationFrame === 'function'
394395
? requestAnimationFrame
395396
: scheduleTimeout;
397+
const localCancelAnimationFrame =
398+
typeof window !== 'undefined' &&
399+
typeof window.cancelAnimationFrame === 'function'
400+
? window.cancelAnimationFrame
401+
: cancelTimeout;
396402
// -------------------
397403
// Microtasks
398404
// -------------------
@@ -408,6 +414,39 @@ export const scheduleMicrotask: any =
408414
.catch(handleErrorInNextTick)
409415
: scheduleTimeout; // TODO: Determine the best fallback here.
410416

417+
// -------------------
418+
// requestAnimationFrame
419+
// -------------------
420+
type FrameAlignedTask = {
421+
frameNode: any,
422+
callbackNode: any,
423+
};
424+
425+
// TODO: Fix these types
426+
export const supportsFrameAlignedTask = true;
427+
export function scheduleFrameAlignedTask(task: any): FrameAlignedTask {
428+
// Schedule both tasks, we'll race them and use the first to fire.
429+
const raf: any = localRequestAnimationFrame;
430+
431+
return {
432+
frameNode: raf(task),
433+
callbackNode: Scheduler.unstable_scheduleCallback(
434+
Scheduler.unstable_NormalPriority,
435+
task,
436+
),
437+
};
438+
}
439+
export function cancelFrameAlignedTask(task: any) {
440+
const caf: any = localCancelAnimationFrame;
441+
if (task.frameNode != null) {
442+
caf(task.frameNode);
443+
}
444+
445+
if (task.callbackNode != null) {
446+
Scheduler.unstable_cancelCallback(task.callbackNode);
447+
}
448+
}
449+
411450
function handleErrorInNextTick(error) {
412451
setTimeout(() => {
413452
throw error;

0 commit comments

Comments
 (0)