Add feature flag for setting update lane priority (#19401)
* Add feature flag for setting update lane priority * Remove second feature flag * Refactor feature flag locations * Add missing else
Ricky committed
Aug 6, 2020 at 12:47 UTC
32ff4286872d1a6bb8ce71730064f60ebbdd1509
7 files changed
+479
-223
packages/react-dom/src/events/ReactDOMEventListener.js
+23
-7
@@ -38,7 +38,10 @@ import {
38
import getEventTarget from './getEventTarget';
39
import {getClosestInstanceFromNode} from '../client/ReactDOMComponentTree';
40
41
-import {enableLegacyFBSupport} from 'shared/ReactFeatureFlags';
41
+import {
42
+ enableLegacyFBSupport,
43
+ decoupleUpdatePriorityFromScheduler,
44
+} from 'shared/ReactFeatureFlags';
45
import {
46
UserBlockingEvent,
47
ContinuousEvent,
@@ -147,10 +150,25 @@ function dispatchUserBlockingUpdate(
150
container,
151
nativeEvent,
152
) {
150
- // TODO: Double wrapping is necessary while we decouple Scheduler priority.
151
- const previousPriority = getCurrentUpdateLanePriority();
152
- try {
153
- setCurrentUpdateLanePriority(InputContinuousLanePriority);
153
+ if (decoupleUpdatePriorityFromScheduler) {
154
+ const previousPriority = getCurrentUpdateLanePriority();
155
+ try {
156
+ // TODO: Double wrapping is necessary while we decouple Scheduler priority.
157
+ setCurrentUpdateLanePriority(InputContinuousLanePriority);
158
+ runWithPriority(
159
+ UserBlockingPriority,
160
+ dispatchEvent.bind(
161
+ null,
162
+ domEventName,
163
+ eventSystemFlags,
164
+ container,
165
+ nativeEvent,
166
+ ),
167
+ );
168
+ } finally {
169
+ setCurrentUpdateLanePriority(previousPriority);
170
+ }
171
+ } else {
172
runWithPriority(
173
UserBlockingPriority,
174
dispatchEvent.bind(
@@ -161,8 +179,6 @@ function dispatchUserBlockingUpdate(
179
nativeEvent,
180
),
181
);
164
- } finally {
165
- setCurrentUpdateLanePriority(previousPriority);
182
}
183
}
184
packages/react-reconciler/src/ReactFiberHooks.new.js
+57
-26
@@ -26,6 +26,7 @@ import {
26
enableDebugTracing,
27
enableSchedulingProfiler,
28
enableNewReconciler,
29
+ decoupleUpdatePriorityFromScheduler,
30
} from 'shared/ReactFeatureFlags';
31
32
import {NoMode, BlockingMode, DebugTracingMode} from './ReactTypeOfMode';
@@ -1506,34 +1507,64 @@ function rerenderDeferredValue<T>(
1507
1508
function startTransition(setPending, config, callback) {
1509
const priorityLevel = getCurrentPriorityLevel();
1509
- const previousLanePriority = getCurrentUpdateLanePriority();
1510
- setCurrentUpdateLanePriority(
1511
- higherLanePriority(previousLanePriority, InputContinuousLanePriority),
1512
- );
1513
- runWithPriority(
1514
- priorityLevel < UserBlockingPriority ? UserBlockingPriority : priorityLevel,
1515
- () => {
1516
- setPending(true);
1517
- },
1518
- );
1510
+ if (decoupleUpdatePriorityFromScheduler) {
1511
+ const previousLanePriority = getCurrentUpdateLanePriority();
1512
+ setCurrentUpdateLanePriority(
1513
+ higherLanePriority(previousLanePriority, InputContinuousLanePriority),
1514
+ );
1515
1520
- // If there's no SuspenseConfig set, we'll use the DefaultLanePriority for this transition.
1521
- setCurrentUpdateLanePriority(DefaultLanePriority);
1516
+ runWithPriority(
1517
+ priorityLevel < UserBlockingPriority
1518
+ ? UserBlockingPriority
1519
+ : priorityLevel,
1520
+ () => {
1521
+ setPending(true);
1522
+ },
1523
+ );
1524
1523
- runWithPriority(
1524
- priorityLevel > NormalPriority ? NormalPriority : priorityLevel,
1525
- () => {
1526
- const previousConfig = ReactCurrentBatchConfig.suspense;
1527
- ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
1528
- try {
1529
- setPending(false);
1530
- callback();
1531
- } finally {
1532
- setCurrentUpdateLanePriority(previousLanePriority);
1533
- ReactCurrentBatchConfig.suspense = previousConfig;
1534
- }
1535
- },
1536
- );
1525
+ // If there's no SuspenseConfig set, we'll use the DefaultLanePriority for this transition.
1526
+ setCurrentUpdateLanePriority(DefaultLanePriority);
1527
+
1528
+ runWithPriority(
1529
+ priorityLevel > NormalPriority ? NormalPriority : priorityLevel,
1530
+ () => {
1531
+ const previousConfig = ReactCurrentBatchConfig.suspense;
1532
+ ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
1533
+ try {
1534
+ setPending(false);
1535
+ callback();
1536
+ } finally {
1537
+ if (decoupleUpdatePriorityFromScheduler) {
1538
+ setCurrentUpdateLanePriority(previousLanePriority);
1539
+ }
1540
+ ReactCurrentBatchConfig.suspense = previousConfig;
1541
+ }
1542
+ },
1543
+ );
1544
+ } else {
1545
+ runWithPriority(
1546
+ priorityLevel < UserBlockingPriority
1547
+ ? UserBlockingPriority
1548
+ : priorityLevel,
1549
+ () => {
1550
+ setPending(true);
1551
+ },
1552
+ );
1553
+
1554
+ runWithPriority(
1555
+ priorityLevel > NormalPriority ? NormalPriority : priorityLevel,
1556
+ () => {
1557
+ const previousConfig = ReactCurrentBatchConfig.suspense;
1558
+ ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
1559
+ try {
1560
+ setPending(false);
1561
+ callback();
1562
+ } finally {
1563
+ ReactCurrentBatchConfig.suspense = previousConfig;
1564
+ }
1565
+ },
1566
+ );
1567
+ }
1568
}
1569
1570
function mountTransition(
packages/react-reconciler/src/ReactFiberHooks.old.js
+57
-26
@@ -26,6 +26,7 @@ import {
26
enableDebugTracing,
27
enableSchedulingProfiler,
28
enableNewReconciler,
29
+ decoupleUpdatePriorityFromScheduler,
30
} from 'shared/ReactFeatureFlags';
31
32
import {NoMode, BlockingMode, DebugTracingMode} from './ReactTypeOfMode';
@@ -1505,34 +1506,64 @@ function rerenderDeferredValue<T>(
1506
1507
function startTransition(setPending, config, callback) {
1508
const priorityLevel = getCurrentPriorityLevel();
1508
- const previousLanePriority = getCurrentUpdateLanePriority();
1509
- setCurrentUpdateLanePriority(
1510
- higherLanePriority(previousLanePriority, InputContinuousLanePriority),
1511
- );
1512
- runWithPriority(
1513
- priorityLevel < UserBlockingPriority ? UserBlockingPriority : priorityLevel,
1514
- () => {
1515
- setPending(true);
1516
- },
1517
- );
1509
+ if (decoupleUpdatePriorityFromScheduler) {
1510
+ const previousLanePriority = getCurrentUpdateLanePriority();
1511
+ setCurrentUpdateLanePriority(
1512
+ higherLanePriority(previousLanePriority, InputContinuousLanePriority),
1513
+ );
1514
1519
- // If there's no SuspenseConfig set, we'll use the DefaultLanePriority for this transition.
1520
- setCurrentUpdateLanePriority(DefaultLanePriority);
1515
+ runWithPriority(
1516
+ priorityLevel < UserBlockingPriority
1517
+ ? UserBlockingPriority
1518
+ : priorityLevel,
1519
+ () => {
1520
+ setPending(true);
1521
+ },
1522
+ );
1523
1522
- runWithPriority(
1523
- priorityLevel > NormalPriority ? NormalPriority : priorityLevel,
1524
- () => {
1525
- const previousConfig = ReactCurrentBatchConfig.suspense;
1526
- ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
1527
- try {
1528
- setPending(false);
1529
- callback();
1530
- } finally {
1531
- setCurrentUpdateLanePriority(previousLanePriority);
1532
- ReactCurrentBatchConfig.suspense = previousConfig;
1533
- }
1534
- },
1535
- );
1524
+ // If there's no SuspenseConfig set, we'll use the DefaultLanePriority for this transition.
1525
+ setCurrentUpdateLanePriority(DefaultLanePriority);
1526
+
1527
+ runWithPriority(
1528
+ priorityLevel > NormalPriority ? NormalPriority : priorityLevel,
1529
+ () => {
1530
+ const previousConfig = ReactCurrentBatchConfig.suspense;
1531
+ ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
1532
+ try {
1533
+ setPending(false);
1534
+ callback();
1535
+ } finally {
1536
+ if (decoupleUpdatePriorityFromScheduler) {
1537
+ setCurrentUpdateLanePriority(previousLanePriority);
1538
+ }
1539
+ ReactCurrentBatchConfig.suspense = previousConfig;
1540
+ }
1541
+ },
1542
+ );
1543
+ } else {
1544
+ runWithPriority(
1545
+ priorityLevel < UserBlockingPriority
1546
+ ? UserBlockingPriority
1547
+ : priorityLevel,
1548
+ () => {
1549
+ setPending(true);
1550
+ },
1551
+ );
1552
+
1553
+ runWithPriority(
1554
+ priorityLevel > NormalPriority ? NormalPriority : priorityLevel,
1555
+ () => {
1556
+ const previousConfig = ReactCurrentBatchConfig.suspense;
1557
+ ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
1558
+ try {
1559
+ setPending(false);
1560
+ callback();
1561
+ } finally {
1562
+ ReactCurrentBatchConfig.suspense = previousConfig;
1563
+ }
1564
+ },
1565
+ );
1566
+ }
1567
}
1568
1569
function mountTransition(
packages/react-reconciler/src/ReactFiberWorkLoop.new.js
+112
-55
@@ -1163,13 +1163,16 @@ export function flushDiscreteUpdates() {
1163
}
1164
1165
export function deferredUpdates<A>(fn: () => A): A {
1166
- // TODO: Remove in favor of Scheduler.next
1167
- const previousLanePriority = getCurrentUpdateLanePriority();
1168
- try {
1169
- setCurrentUpdateLanePriority(DefaultLanePriority);
1166
+ if (decoupleUpdatePriorityFromScheduler) {
1167
+ const previousLanePriority = getCurrentUpdateLanePriority();
1168
+ try {
1169
+ setCurrentUpdateLanePriority(DefaultLanePriority);
1170
+ return runWithPriority(NormalSchedulerPriority, fn);
1171
+ } finally {
1172
+ setCurrentUpdateLanePriority(previousLanePriority);
1173
+ }
1174
+ } else {
1175
return runWithPriority(NormalSchedulerPriority, fn);
1171
- } finally {
1172
- setCurrentUpdateLanePriority(previousLanePriority);
1176
}
1177
}
1178
@@ -1225,20 +1228,35 @@ export function discreteUpdates<A, B, C, D, R>(
1228
): R {
1229
const prevExecutionContext = executionContext;
1230
executionContext |= DiscreteEventContext;
1228
- const previousLanePriority = getCurrentUpdateLanePriority();
1229
- try {
1230
- setCurrentUpdateLanePriority(InputDiscreteLanePriority);
1231
- // Should this
1232
- return runWithPriority(
1233
- UserBlockingSchedulerPriority,
1234
- fn.bind(null, a, b, c, d),
1235
- );
1236
- } finally {
1237
- setCurrentUpdateLanePriority(previousLanePriority);
1238
- executionContext = prevExecutionContext;
1239
- if (executionContext === NoContext) {
1240
- // Flush the immediate callbacks that were scheduled during this batch
1241
- flushSyncCallbackQueue();
1231
+
1232
+ if (decoupleUpdatePriorityFromScheduler) {
1233
+ const previousLanePriority = getCurrentUpdateLanePriority();
1234
+ try {
1235
+ setCurrentUpdateLanePriority(InputDiscreteLanePriority);
1236
+ return runWithPriority(
1237
+ UserBlockingSchedulerPriority,
1238
+ fn.bind(null, a, b, c, d),
1239
+ );
1240
+ } finally {
1241
+ setCurrentUpdateLanePriority(previousLanePriority);
1242
+ executionContext = prevExecutionContext;
1243
+ if (executionContext === NoContext) {
1244
+ // Flush the immediate callbacks that were scheduled during this batch
1245
+ flushSyncCallbackQueue();
1246
+ }
1247
+ }
1248
+ } else {
1249
+ try {
1250
+ return runWithPriority(
1251
+ UserBlockingSchedulerPriority,
1252
+ fn.bind(null, a, b, c, d),
1253
+ );
1254
+ } finally {
1255
+ executionContext = prevExecutionContext;
1256
+ if (executionContext === NoContext) {
1257
+ // Flush the immediate callbacks that were scheduled during this batch
1258
+ flushSyncCallbackQueue();
1259
+ }
1260
}
1261
}
1262
}
@@ -1271,37 +1289,67 @@ export function flushSync<A, R>(fn: A => R, a: A): R {
1289
return fn(a);
1290
}
1291
executionContext |= BatchedContext;
1274
- const previousLanePriority = getCurrentUpdateLanePriority();
1275
- try {
1276
- setCurrentUpdateLanePriority(SyncLanePriority);
1277
- if (fn) {
1278
- return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a));
1279
- } else {
1280
- return (undefined: $FlowFixMe);
1292
+
1293
+ if (decoupleUpdatePriorityFromScheduler) {
1294
+ const previousLanePriority = getCurrentUpdateLanePriority();
1295
+ try {
1296
+ setCurrentUpdateLanePriority(SyncLanePriority);
1297
+ if (fn) {
1298
+ return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a));
1299
+ } else {
1300
+ return (undefined: $FlowFixMe);
1301
+ }
1302
+ } finally {
1303
+ setCurrentUpdateLanePriority(previousLanePriority);
1304
+ executionContext = prevExecutionContext;
1305
+ // Flush the immediate callbacks that were scheduled during this batch.
1306
+ // Note that this will happen even if batchedUpdates is higher up
1307
+ // the stack.
1308
+ flushSyncCallbackQueue();
1309
+ }
1310
+ } else {
1311
+ try {
1312
+ if (fn) {
1313
+ return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a));
1314
+ } else {
1315
+ return (undefined: $FlowFixMe);
1316
+ }
1317
+ } finally {
1318
+ executionContext = prevExecutionContext;
1319
+ // Flush the immediate callbacks that were scheduled during this batch.
1320
+ // Note that this will happen even if batchedUpdates is higher up
1321
+ // the stack.
1322
+ flushSyncCallbackQueue();
1323
}
1282
- } finally {
1283
- setCurrentUpdateLanePriority(previousLanePriority);
1284
- executionContext = prevExecutionContext;
1285
- // Flush the immediate callbacks that were scheduled during this batch.
1286
- // Note that this will happen even if batchedUpdates is higher up
1287
- // the stack.
1288
- flushSyncCallbackQueue();
1324
}
1325
}
1326
1327
export function flushControlled(fn: () => mixed): void {
1328
const prevExecutionContext = executionContext;
1329
executionContext |= BatchedContext;
1295
- const previousLanePriority = getCurrentUpdateLanePriority();
1296
- try {
1297
- setCurrentUpdateLanePriority(SyncLanePriority);
1298
- runWithPriority(ImmediateSchedulerPriority, fn);
1299
- } finally {
1300
- setCurrentUpdateLanePriority(previousLanePriority);
1301
- executionContext = prevExecutionContext;
1302
- if (executionContext === NoContext) {
1303
- // Flush the immediate callbacks that were scheduled during this batch
1304
- flushSyncCallbackQueue();
1330
+ if (decoupleUpdatePriorityFromScheduler) {
1331
+ const previousLanePriority = getCurrentUpdateLanePriority();
1332
+ try {
1333
+ setCurrentUpdateLanePriority(SyncLanePriority);
1334
+ runWithPriority(ImmediateSchedulerPriority, fn);
1335
+ } finally {
1336
+ setCurrentUpdateLanePriority(previousLanePriority);
1337
+
1338
+ executionContext = prevExecutionContext;
1339
+ if (executionContext === NoContext) {
1340
+ // Flush the immediate callbacks that were scheduled during this batch
1341
+ flushSyncCallbackQueue();
1342
+ }
1343
+ }
1344
+ } else {
1345
+ try {
1346
+ runWithPriority(ImmediateSchedulerPriority, fn);
1347
+ } finally {
1348
+ executionContext = prevExecutionContext;
1349
+ if (executionContext === NoContext) {
1350
+ // Flush the immediate callbacks that were scheduled during this batch
1351
+ flushSyncCallbackQueue();
1352
+ }
1353
}
1354
}
1355
}
@@ -2122,8 +2170,11 @@ function commitRootImpl(root, renderPriorityLevel) {
2170
}
2171
2172
if (firstEffect !== null) {
2125
- const previousLanePriority = getCurrentUpdateLanePriority();
2126
- setCurrentUpdateLanePriority(SyncLanePriority);
2173
+ let previousLanePriority;
2174
+ if (decoupleUpdatePriorityFromScheduler) {
2175
+ previousLanePriority = getCurrentUpdateLanePriority();
2176
+ setCurrentUpdateLanePriority(SyncLanePriority);
2177
+ }
2178
2179
const prevExecutionContext = executionContext;
2180
executionContext |= CommitContext;
@@ -2214,8 +2265,10 @@ function commitRootImpl(root, renderPriorityLevel) {
2265
}
2266
executionContext = prevExecutionContext;
2267
2217
- // Reset the priority to the previous non-sync value.
2218
- setCurrentUpdateLanePriority(previousLanePriority);
2268
+ if (decoupleUpdatePriorityFromScheduler && previousLanePriority != null) {
2269
+ // Reset the priority to the previous non-sync value.
2270
+ setCurrentUpdateLanePriority(previousLanePriority);
2271
+ }
2272
} else {
2273
// No effects.
2274
root.current = finishedWork;
@@ -2655,14 +2708,18 @@ export function flushPassiveEffects(): boolean {
2708
? NormalSchedulerPriority
2709
: pendingPassiveEffectsRenderPriority;
2710
pendingPassiveEffectsRenderPriority = NoSchedulerPriority;
2658
- const previousLanePriority = getCurrentUpdateLanePriority();
2659
- try {
2660
- setCurrentUpdateLanePriority(
2661
- schedulerPriorityToLanePriority(priorityLevel),
2662
- );
2711
+ if (decoupleUpdatePriorityFromScheduler) {
2712
+ const previousLanePriority = getCurrentUpdateLanePriority();
2713
+ try {
2714
+ setCurrentUpdateLanePriority(
2715
+ schedulerPriorityToLanePriority(priorityLevel),
2716
+ );
2717
+ return runWithPriority(priorityLevel, flushPassiveEffectsImpl);
2718
+ } finally {
2719
+ setCurrentUpdateLanePriority(previousLanePriority);
2720
+ }
2721
+ } else {
2722
return runWithPriority(priorityLevel, flushPassiveEffectsImpl);
2664
- } finally {
2665
- setCurrentUpdateLanePriority(previousLanePriority);
2723
}
2724
}
2725
return false;
packages/react-reconciler/src/ReactFiberWorkLoop.old.js
+112
-55
@@ -1147,13 +1147,16 @@ export function flushDiscreteUpdates() {
1147
}
1148
1149
export function deferredUpdates<A>(fn: () => A): A {
1150
- // TODO: Remove in favor of Scheduler.next
1151
- const previousLanePriority = getCurrentUpdateLanePriority();
1152
- try {
1153
- setCurrentUpdateLanePriority(DefaultLanePriority);
1150
+ if (decoupleUpdatePriorityFromScheduler) {
1151
+ const previousLanePriority = getCurrentUpdateLanePriority();
1152
+ try {
1153
+ setCurrentUpdateLanePriority(DefaultLanePriority);
1154
+ return runWithPriority(NormalSchedulerPriority, fn);
1155
+ } finally {
1156
+ setCurrentUpdateLanePriority(previousLanePriority);
1157
+ }
1158
+ } else {
1159
return runWithPriority(NormalSchedulerPriority, fn);
1155
- } finally {
1156
- setCurrentUpdateLanePriority(previousLanePriority);
1160
}
1161
}
1162
@@ -1209,20 +1212,35 @@ export function discreteUpdates<A, B, C, D, R>(
1212
): R {
1213
const prevExecutionContext = executionContext;
1214
executionContext |= DiscreteEventContext;
1212
- const previousLanePriority = getCurrentUpdateLanePriority();
1213
- try {
1214
- setCurrentUpdateLanePriority(InputDiscreteLanePriority);
1215
- // Should this
1216
- return runWithPriority(
1217
- UserBlockingSchedulerPriority,
1218
- fn.bind(null, a, b, c, d),
1219
- );
1220
- } finally {
1221
- setCurrentUpdateLanePriority(previousLanePriority);
1222
- executionContext = prevExecutionContext;
1223
- if (executionContext === NoContext) {
1224
- // Flush the immediate callbacks that were scheduled during this batch
1225
- flushSyncCallbackQueue();
1215
+
1216
+ if (decoupleUpdatePriorityFromScheduler) {
1217
+ const previousLanePriority = getCurrentUpdateLanePriority();
1218
+ try {
1219
+ setCurrentUpdateLanePriority(InputDiscreteLanePriority);
1220
+ return runWithPriority(
1221
+ UserBlockingSchedulerPriority,
1222
+ fn.bind(null, a, b, c, d),
1223
+ );
1224
+ } finally {
1225
+ setCurrentUpdateLanePriority(previousLanePriority);
1226
+ executionContext = prevExecutionContext;
1227
+ if (executionContext === NoContext) {
1228
+ // Flush the immediate callbacks that were scheduled during this batch
1229
+ flushSyncCallbackQueue();
1230
+ }
1231
+ }
1232
+ } else {
1233
+ try {
1234
+ return runWithPriority(
1235
+ UserBlockingSchedulerPriority,
1236
+ fn.bind(null, a, b, c, d),
1237
+ );
1238
+ } finally {
1239
+ executionContext = prevExecutionContext;
1240
+ if (executionContext === NoContext) {
1241
+ // Flush the immediate callbacks that were scheduled during this batch
1242
+ flushSyncCallbackQueue();
1243
+ }
1244
}
1245
}
1246
}
@@ -1255,37 +1273,67 @@ export function flushSync<A, R>(fn: A => R, a: A): R {
1273
return fn(a);
1274
}
1275
executionContext |= BatchedContext;
1258
- const previousLanePriority = getCurrentUpdateLanePriority();
1259
- try {
1260
- setCurrentUpdateLanePriority(SyncLanePriority);
1261
- if (fn) {
1262
- return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a));
1263
- } else {
1264
- return (undefined: $FlowFixMe);
1276
+
1277
+ if (decoupleUpdatePriorityFromScheduler) {
1278
+ const previousLanePriority = getCurrentUpdateLanePriority();
1279
+ try {
1280
+ setCurrentUpdateLanePriority(SyncLanePriority);
1281
+ if (fn) {
1282
+ return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a));
1283
+ } else {
1284
+ return (undefined: $FlowFixMe);
1285
+ }
1286
+ } finally {
1287
+ setCurrentUpdateLanePriority(previousLanePriority);
1288
+ executionContext = prevExecutionContext;
1289
+ // Flush the immediate callbacks that were scheduled during this batch.
1290
+ // Note that this will happen even if batchedUpdates is higher up
1291
+ // the stack.
1292
+ flushSyncCallbackQueue();
1293
+ }
1294
+ } else {
1295
+ try {
1296
+ if (fn) {
1297
+ return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a));
1298
+ } else {
1299
+ return (undefined: $FlowFixMe);
1300
+ }
1301
+ } finally {
1302
+ executionContext = prevExecutionContext;
1303
+ // Flush the immediate callbacks that were scheduled during this batch.
1304
+ // Note that this will happen even if batchedUpdates is higher up
1305
+ // the stack.
1306
+ flushSyncCallbackQueue();
1307
}
1266
- } finally {
1267
- setCurrentUpdateLanePriority(previousLanePriority);
1268
- executionContext = prevExecutionContext;
1269
- // Flush the immediate callbacks that were scheduled during this batch.
1270
- // Note that this will happen even if batchedUpdates is higher up
1271
- // the stack.
1272
- flushSyncCallbackQueue();
1308
}
1309
}
1310
1311
export function flushControlled(fn: () => mixed): void {
1312
const prevExecutionContext = executionContext;
1313
executionContext |= BatchedContext;
1279
- const previousLanePriority = getCurrentUpdateLanePriority();
1280
- try {
1281
- setCurrentUpdateLanePriority(SyncLanePriority);
1282
- runWithPriority(ImmediateSchedulerPriority, fn);
1283
- } finally {
1284
- setCurrentUpdateLanePriority(previousLanePriority);
1285
- executionContext = prevExecutionContext;
1286
- if (executionContext === NoContext) {
1287
- // Flush the immediate callbacks that were scheduled during this batch
1288
- flushSyncCallbackQueue();
1314
+ if (decoupleUpdatePriorityFromScheduler) {
1315
+ const previousLanePriority = getCurrentUpdateLanePriority();
1316
+ try {
1317
+ setCurrentUpdateLanePriority(SyncLanePriority);
1318
+ runWithPriority(ImmediateSchedulerPriority, fn);
1319
+ } finally {
1320
+ setCurrentUpdateLanePriority(previousLanePriority);
1321
+
1322
+ executionContext = prevExecutionContext;
1323
+ if (executionContext === NoContext) {
1324
+ // Flush the immediate callbacks that were scheduled during this batch
1325
+ flushSyncCallbackQueue();
1326
+ }
1327
+ }
1328
+ } else {
1329
+ try {
1330
+ runWithPriority(ImmediateSchedulerPriority, fn);
1331
+ } finally {
1332
+ executionContext = prevExecutionContext;
1333
+ if (executionContext === NoContext) {
1334
+ // Flush the immediate callbacks that were scheduled during this batch
1335
+ flushSyncCallbackQueue();
1336
+ }
1337
}
1338
}
1339
}
@@ -2019,8 +2067,11 @@ function commitRootImpl(root, renderPriorityLevel) {
2067
}
2068
2069
if (firstEffect !== null) {
2022
- const previousLanePriority = getCurrentUpdateLanePriority();
2023
- setCurrentUpdateLanePriority(SyncLanePriority);
2070
+ let previousLanePriority;
2071
+ if (decoupleUpdatePriorityFromScheduler) {
2072
+ previousLanePriority = getCurrentUpdateLanePriority();
2073
+ setCurrentUpdateLanePriority(SyncLanePriority);
2074
+ }
2075
2076
const prevExecutionContext = executionContext;
2077
executionContext |= CommitContext;
@@ -2143,8 +2194,10 @@ function commitRootImpl(root, renderPriorityLevel) {
2194
}
2195
executionContext = prevExecutionContext;
2196
2146
- // Reset the priority to the previous non-sync value.
2147
- setCurrentUpdateLanePriority(previousLanePriority);
2197
+ if (decoupleUpdatePriorityFromScheduler && previousLanePriority != null) {
2198
+ // Reset the priority to the previous non-sync value.
2199
+ setCurrentUpdateLanePriority(previousLanePriority);
2200
+ }
2201
} else {
2202
// No effects.
2203
root.current = finishedWork;
@@ -2463,14 +2516,18 @@ export function flushPassiveEffects(): boolean {
2516
? NormalSchedulerPriority
2517
: pendingPassiveEffectsRenderPriority;
2518
pendingPassiveEffectsRenderPriority = NoSchedulerPriority;
2466
- const previousLanePriority = getCurrentUpdateLanePriority();
2467
- try {
2468
- setCurrentUpdateLanePriority(
2469
- schedulerPriorityToLanePriority(priorityLevel),
2470
- );
2519
+ if (decoupleUpdatePriorityFromScheduler) {
2520
+ const previousLanePriority = getCurrentUpdateLanePriority();
2521
+ try {
2522
+ setCurrentUpdateLanePriority(
2523
+ schedulerPriorityToLanePriority(priorityLevel),
2524
+ );
2525
+ return runWithPriority(priorityLevel, flushPassiveEffectsImpl);
2526
+ } finally {
2527
+ setCurrentUpdateLanePriority(previousLanePriority);
2528
+ }
2529
+ } else {
2530
return runWithPriority(priorityLevel, flushPassiveEffectsImpl);
2472
- } finally {
2473
- setCurrentUpdateLanePriority(previousLanePriority);
2531
}
2532
}
2533
return false;
packages/react-reconciler/src/SchedulerWithReactIntegration.new.js
+59
-27
@@ -13,7 +13,10 @@ import type {ReactPriorityLevel} from './ReactInternalTypes';
13
// CommonJS interop named imports.
14
import * as Scheduler from 'scheduler';
15
import {__interactionsRef} from 'scheduler/tracing';
16
-import {enableSchedulerTracing} from 'shared/ReactFeatureFlags';
16
+import {
17
+ enableSchedulerTracing,
18
+ decoupleUpdatePriorityFromScheduler,
19
+} from 'shared/ReactFeatureFlags';
20
import invariant from 'shared/invariant';
21
import {
22
SyncLanePriority,
@@ -176,34 +179,63 @@ function flushSyncCallbackQueueImpl() {
179
// Prevent re-entrancy.
180
isFlushingSyncQueue = true;
181
let i = 0;
179
- const previousLanePriority = getCurrentUpdateLanePriority();
180
- try {
181
- const isSync = true;
182
- const queue = syncQueue;
183
- setCurrentUpdateLanePriority(SyncLanePriority);
184
- runWithPriority(ImmediatePriority, () => {
185
- for (; i < queue.length; i++) {
186
- let callback = queue[i];
187
- do {
188
- callback = callback(isSync);
189
- } while (callback !== null);
182
+ if (decoupleUpdatePriorityFromScheduler) {
183
+ const previousLanePriority = getCurrentUpdateLanePriority();
184
+ try {
185
+ const isSync = true;
186
+ const queue = syncQueue;
187
+ setCurrentUpdateLanePriority(SyncLanePriority);
188
+ runWithPriority(ImmediatePriority, () => {
189
+ for (; i < queue.length; i++) {
190
+ let callback = queue[i];
191
+ do {
192
+ callback = callback(isSync);
193
+ } while (callback !== null);
194
+ }
195
+ });
196
+ syncQueue = null;
197
+ } catch (error) {
198
+ // If something throws, leave the remaining callbacks on the queue.
199
+ if (syncQueue !== null) {
200
+ syncQueue = syncQueue.slice(i + 1);
201
+ }
202
+ // Resume flushing in the next tick
203
+ Scheduler_scheduleCallback(
204
+ Scheduler_ImmediatePriority,
205
+ flushSyncCallbackQueue,
206
+ );
207
+ throw error;
208
+ } finally {
209
+ setCurrentUpdateLanePriority(previousLanePriority);
210
+ isFlushingSyncQueue = false;
211
+ }
212
+ } else {
213
+ try {
214
+ const isSync = true;
215
+ const queue = syncQueue;
216
+ runWithPriority(ImmediatePriority, () => {
217
+ for (; i < queue.length; i++) {
218
+ let callback = queue[i];
219
+ do {
220
+ callback = callback(isSync);
221
+ } while (callback !== null);
222
+ }
223
+ });
224
+ syncQueue = null;
225
+ } catch (error) {
226
+ // If something throws, leave the remaining callbacks on the queue.
227
+ if (syncQueue !== null) {
228
+ syncQueue = syncQueue.slice(i + 1);
229
}
191
- });
192
- syncQueue = null;
193
- } catch (error) {
194
- // If something throws, leave the remaining callbacks on the queue.
195
- if (syncQueue !== null) {
196
- syncQueue = syncQueue.slice(i + 1);
230
+ // Resume flushing in the next tick
231
+ Scheduler_scheduleCallback(
232
+ Scheduler_ImmediatePriority,
233
+ flushSyncCallbackQueue,
234
+ );
235
+ throw error;
236
+ } finally {
237
+ isFlushingSyncQueue = false;
238
}
198
- // Resume flushing in the next tick
199
- Scheduler_scheduleCallback(
200
- Scheduler_ImmediatePriority,
201
- flushSyncCallbackQueue,
202
- );
203
- throw error;
204
- } finally {
205
- setCurrentUpdateLanePriority(previousLanePriority);
206
- isFlushingSyncQueue = false;
239
}
240
}
241
}
packages/react-reconciler/src/SchedulerWithReactIntegration.old.js
+59
-27
@@ -13,7 +13,10 @@ import type {ReactPriorityLevel} from './ReactInternalTypes';
13
// CommonJS interop named imports.
14
import * as Scheduler from 'scheduler';
15
import {__interactionsRef} from 'scheduler/tracing';
16
-import {enableSchedulerTracing} from 'shared/ReactFeatureFlags';
16
+import {
17
+ enableSchedulerTracing,
18
+ decoupleUpdatePriorityFromScheduler,
19
+} from 'shared/ReactFeatureFlags';
20
import invariant from 'shared/invariant';
21
import {
22
SyncLanePriority,
@@ -176,34 +179,63 @@ function flushSyncCallbackQueueImpl() {
179
// Prevent re-entrancy.
180
isFlushingSyncQueue = true;
181
let i = 0;
179
- const previousLanePriority = getCurrentUpdateLanePriority();
180
- try {
181
- const isSync = true;
182
- const queue = syncQueue;
183
- setCurrentUpdateLanePriority(SyncLanePriority);
184
- runWithPriority(ImmediatePriority, () => {
185
- for (; i < queue.length; i++) {
186
- let callback = queue[i];
187
- do {
188
- callback = callback(isSync);
189
- } while (callback !== null);
182
+ if (decoupleUpdatePriorityFromScheduler) {
183
+ const previousLanePriority = getCurrentUpdateLanePriority();
184
+ try {
185
+ const isSync = true;
186
+ const queue = syncQueue;
187
+ setCurrentUpdateLanePriority(SyncLanePriority);
188
+ runWithPriority(ImmediatePriority, () => {
189
+ for (; i < queue.length; i++) {
190
+ let callback = queue[i];
191
+ do {
192
+ callback = callback(isSync);
193
+ } while (callback !== null);
194
+ }
195
+ });
196
+ syncQueue = null;
197
+ } catch (error) {
198
+ // If something throws, leave the remaining callbacks on the queue.
199
+ if (syncQueue !== null) {
200
+ syncQueue = syncQueue.slice(i + 1);
201
+ }
202
+ // Resume flushing in the next tick
203
+ Scheduler_scheduleCallback(
204
+ Scheduler_ImmediatePriority,
205
+ flushSyncCallbackQueue,
206
+ );
207
+ throw error;
208
+ } finally {
209
+ setCurrentUpdateLanePriority(previousLanePriority);
210
+ isFlushingSyncQueue = false;
211
+ }
212
+ } else {
213
+ try {
214
+ const isSync = true;
215
+ const queue = syncQueue;
216
+ runWithPriority(ImmediatePriority, () => {
217
+ for (; i < queue.length; i++) {
218
+ let callback = queue[i];
219
+ do {
220
+ callback = callback(isSync);
221
+ } while (callback !== null);
222
+ }
223
+ });
224
+ syncQueue = null;
225
+ } catch (error) {
226
+ // If something throws, leave the remaining callbacks on the queue.
227
+ if (syncQueue !== null) {
228
+ syncQueue = syncQueue.slice(i + 1);
229
}
191
- });
192
- syncQueue = null;
193
- } catch (error) {
194
- // If something throws, leave the remaining callbacks on the queue.
195
- if (syncQueue !== null) {
196
- syncQueue = syncQueue.slice(i + 1);
230
+ // Resume flushing in the next tick
231
+ Scheduler_scheduleCallback(
232
+ Scheduler_ImmediatePriority,
233
+ flushSyncCallbackQueue,
234
+ );
235
+ throw error;
236
+ } finally {
237
+ isFlushingSyncQueue = false;
238
}
198
- // Resume flushing in the next tick
199
- Scheduler_scheduleCallback(
200
- Scheduler_ImmediatePriority,
201
- flushSyncCallbackQueue,
202
- );
203
- throw error;
204
- } finally {
205
- setCurrentUpdateLanePriority(previousLanePriority);
206
- isFlushingSyncQueue = false;
239
}
240
}
241
}