@samitouri / QOS-React / commits / 32ff428687

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 }