Skip to content

Commit 1990ecf

Browse files
committed
Always yield to native macro tasks when a virtual task completes
1 parent c80b336 commit 1990ecf

File tree

5 files changed

+52
-9
lines changed

5 files changed

+52
-9
lines changed

packages/scheduler/src/SchedulerFeatureFlags.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@ export const frameYieldMs = 5;
1414
export const userBlockingPriorityTimeout = 250;
1515
export const normalPriorityTimeout = 5000;
1616
export const lowPriorityTimeout = 10000;
17+
18+
export const enableAlwaysYieldScheduler = __EXPERIMENTAL__;

packages/scheduler/src/__tests__/Scheduler-test.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,9 @@ describe('SchedulerBrowser', () => {
199199
runtime.assertLog([
200200
'Message Event',
201201
'Task',
202-
'Yield at 0ms',
202+
gate(flags => flags.enableAlwaysYieldScheduler)
203+
? gate(flags => (flags.www ? 'Yield at 10ms' : 'Yield at 5ms'))
204+
: 'Yield at 0ms',
203205
'Post Message',
204206
]);
205207

@@ -216,7 +218,13 @@ describe('SchedulerBrowser', () => {
216218
});
217219
runtime.assertLog(['Post Message']);
218220
runtime.fireMessageEvent();
219-
runtime.assertLog(['Message Event', 'A', 'B']);
221+
if (gate(flags => flags.enableAlwaysYieldScheduler)) {
222+
runtime.assertLog(['Message Event', 'A', 'Post Message']);
223+
runtime.fireMessageEvent();
224+
runtime.assertLog(['Message Event', 'B']);
225+
} else {
226+
runtime.assertLog(['Message Event', 'A', 'B']);
227+
}
220228
});
221229

222230
it('multiple tasks with a yield in between', () => {
@@ -263,6 +271,10 @@ describe('SchedulerBrowser', () => {
263271
runtime.assertLog(['Message Event', 'Oops!', 'Post Message']);
264272

265273
runtime.fireMessageEvent();
274+
if (gate(flags => flags.enableAlwaysYieldScheduler)) {
275+
runtime.assertLog(['Message Event', 'Post Message']);
276+
runtime.fireMessageEvent();
277+
}
266278
runtime.assertLog(['Message Event', 'Yay']);
267279
});
268280

packages/scheduler/src/__tests__/SchedulerSetImmediate-test.js

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,13 @@ describe('SchedulerDOMSetImmediate', () => {
188188
});
189189
runtime.assertLog(['Set Immediate']);
190190
runtime.fireSetImmediate();
191-
runtime.assertLog(['setImmediate Callback', 'A', 'B']);
191+
if (gate(flags => flags.enableAlwaysYieldScheduler)) {
192+
runtime.assertLog(['setImmediate Callback', 'A', 'Set Immediate']);
193+
runtime.fireSetImmediate();
194+
runtime.assertLog(['setImmediate Callback', 'B']);
195+
} else {
196+
runtime.assertLog(['setImmediate Callback', 'A', 'B']);
197+
}
192198
});
193199

194200
it('multiple tasks at different priority', () => {
@@ -200,7 +206,13 @@ describe('SchedulerDOMSetImmediate', () => {
200206
});
201207
runtime.assertLog(['Set Immediate']);
202208
runtime.fireSetImmediate();
203-
runtime.assertLog(['setImmediate Callback', 'B', 'A']);
209+
if (gate(flags => flags.enableAlwaysYieldScheduler)) {
210+
runtime.assertLog(['setImmediate Callback', 'B', 'Set Immediate']);
211+
runtime.fireSetImmediate();
212+
runtime.assertLog(['setImmediate Callback', 'A']);
213+
} else {
214+
runtime.assertLog(['setImmediate Callback', 'B', 'A']);
215+
}
204216
});
205217

206218
it('multiple tasks with a yield in between', () => {
@@ -246,7 +258,13 @@ describe('SchedulerDOMSetImmediate', () => {
246258
runtime.assertLog(['setImmediate Callback', 'Oops!', 'Set Immediate']);
247259

248260
runtime.fireSetImmediate();
249-
runtime.assertLog(['setImmediate Callback', 'Yay']);
261+
if (gate(flags => flags.enableAlwaysYieldScheduler)) {
262+
runtime.assertLog(['setImmediate Callback', 'Set Immediate']);
263+
runtime.fireSetImmediate();
264+
runtime.assertLog(['setImmediate Callback', 'Yay']);
265+
} else {
266+
runtime.assertLog(['setImmediate Callback', 'Yay']);
267+
}
250268
});
251269

252270
it('schedule new task after queue has emptied', () => {

packages/scheduler/src/forks/Scheduler.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
userBlockingPriorityTimeout,
1919
lowPriorityTimeout,
2020
normalPriorityTimeout,
21+
enableAlwaysYieldScheduler,
2122
} from '../SchedulerFeatureFlags';
2223

2324
import {push, pop, peek} from '../SchedulerMinHeap';
@@ -195,9 +196,11 @@ function workLoop(initialTime: number) {
195196
currentTask !== null &&
196197
!(enableSchedulerDebugging && isSchedulerPaused)
197198
) {
198-
if (currentTask.expirationTime > currentTime && shouldYieldToHost()) {
199-
// This currentTask hasn't expired, and we've reached the deadline.
200-
break;
199+
if (!enableAlwaysYieldScheduler) {
200+
if (currentTask.expirationTime > currentTime && shouldYieldToHost()) {
201+
// This currentTask hasn't expired, and we've reached the deadline.
202+
break;
203+
}
201204
}
202205
// $FlowFixMe[incompatible-use] found when upgrading Flow
203206
const callback = currentTask.callback;
@@ -241,6 +244,12 @@ function workLoop(initialTime: number) {
241244
pop(taskQueue);
242245
}
243246
currentTask = peek(taskQueue);
247+
if (enableAlwaysYieldScheduler) {
248+
if (currentTask === null || currentTask.expirationTime > currentTime) {
249+
// This currentTask hasn't expired we yield to the browser task.
250+
break;
251+
}
252+
}
244253
}
245254
// Return whether there's additional work
246255
if (currentTask !== null) {
@@ -458,7 +467,7 @@ let frameInterval = frameYieldMs;
458467
let startTime = -1;
459468

460469
function shouldYieldToHost(): boolean {
461-
if (needsPaint) {
470+
if (!enableAlwaysYieldScheduler && needsPaint) {
462471
// Yield now.
463472
return true;
464473
}

packages/scheduler/src/forks/SchedulerFeatureFlags.www.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@ export const {
1919
export const frameYieldMs = 10;
2020
export const enableSchedulerDebugging = true;
2121
export const enableProfiling = __DEV__;
22+
23+
export const enableAlwaysYieldScheduler = false;

0 commit comments

Comments
 (0)