Replace SuspenseConfig object with an integer (#19706)

Now that the options in SuspenseConfig are no longer supported, the
only thing we use it for is to track whether an update is part of
a transition.

I've renamed `ReactCurrentBatchConfig.suspense` to
`ReactCurrentBatchConfig.transition`, and changed the type to a number.
The number is always either 0 or 1. I could have made it a boolean;
however, most likely this will eventually be either a Lane or an
incrementing identifier.

The `withSuspenseConfig` export still exists until we've removed
all the callers from www.
This commit is contained in:
Andrew Clark
2020-08-28 12:52:56 -05:00
committed by GitHub
parent b754caaaf2
commit 92fcd46cc7
15 changed files with 80 additions and 108 deletions

View File

@@ -20,7 +20,7 @@ import type {
} from 'react-reconciler/src/ReactInternalTypes';
import type {OpaqueIDType} from 'react-reconciler/src/ReactFiberHostConfig';
import type {SuspenseConfig} from 'react-reconciler/src/ReactFiberSuspenseConfig';
import type {SuspenseConfig} from 'react-reconciler/src/ReactFiberTransition';
import {NoMode} from 'react-reconciler/src/ReactTypeOfMode';
import ErrorStackParser from 'error-stack-parser';

View File

@@ -15,7 +15,7 @@ import type {
MutableSourceSubscribeFn,
ReactContext,
} from 'shared/ReactTypes';
import type {SuspenseConfig} from 'react-reconciler/src/ReactFiberSuspenseConfig';
import type {SuspenseConfig} from 'react-reconciler/src/ReactFiberTransition';
import type PartialRenderer from './ReactPartialRenderer';
import {validateContextBounds} from './ReactPartialRendererContext';

View File

@@ -56,7 +56,6 @@ import {
requestUpdateLane,
scheduleUpdateOnFiber,
} from './ReactFiberWorkLoop.new';
import {requestCurrentSuspenseConfig} from './ReactFiberSuspenseConfig';
import {logForceUpdateScheduled, logStateUpdateScheduled} from './DebugTracing';
import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev';
@@ -196,8 +195,7 @@ const classComponentUpdater = {
enqueueSetState(inst, payload, callback) {
const fiber = getInstance(inst);
const eventTime = requestEventTime();
const suspenseConfig = requestCurrentSuspenseConfig();
const lane = requestUpdateLane(fiber, suspenseConfig);
const lane = requestUpdateLane(fiber);
const update = createUpdate(eventTime, lane);
update.payload = payload;
@@ -227,8 +225,7 @@ const classComponentUpdater = {
enqueueReplaceState(inst, payload, callback) {
const fiber = getInstance(inst);
const eventTime = requestEventTime();
const suspenseConfig = requestCurrentSuspenseConfig();
const lane = requestUpdateLane(fiber, suspenseConfig);
const lane = requestUpdateLane(fiber);
const update = createUpdate(eventTime, lane);
update.tag = ReplaceState;
@@ -260,8 +257,7 @@ const classComponentUpdater = {
enqueueForceUpdate(inst, callback) {
const fiber = getInstance(inst);
const eventTime = requestEventTime();
const suspenseConfig = requestCurrentSuspenseConfig();
const lane = requestUpdateLane(fiber, suspenseConfig);
const lane = requestUpdateLane(fiber);
const update = createUpdate(eventTime, lane);
update.tag = ForceUpdate;

View File

@@ -56,7 +56,6 @@ import {
requestUpdateLane,
scheduleUpdateOnFiber,
} from './ReactFiberWorkLoop.old';
import {requestCurrentSuspenseConfig} from './ReactFiberSuspenseConfig';
import {logForceUpdateScheduled, logStateUpdateScheduled} from './DebugTracing';
import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev';
@@ -196,8 +195,7 @@ const classComponentUpdater = {
enqueueSetState(inst, payload, callback) {
const fiber = getInstance(inst);
const eventTime = requestEventTime();
const suspenseConfig = requestCurrentSuspenseConfig();
const lane = requestUpdateLane(fiber, suspenseConfig);
const lane = requestUpdateLane(fiber);
const update = createUpdate(eventTime, lane);
update.payload = payload;
@@ -227,8 +225,7 @@ const classComponentUpdater = {
enqueueReplaceState(inst, payload, callback) {
const fiber = getInstance(inst);
const eventTime = requestEventTime();
const suspenseConfig = requestCurrentSuspenseConfig();
const lane = requestUpdateLane(fiber, suspenseConfig);
const lane = requestUpdateLane(fiber);
const update = createUpdate(eventTime, lane);
update.tag = ReplaceState;
@@ -260,8 +257,7 @@ const classComponentUpdater = {
enqueueForceUpdate(inst, callback) {
const fiber = getInstance(inst);
const eventTime = requestEventTime();
const suspenseConfig = requestCurrentSuspenseConfig();
const lane = requestUpdateLane(fiber, suspenseConfig);
const lane = requestUpdateLane(fiber);
const update = createUpdate(eventTime, lane);
update.tag = ForceUpdate;

View File

@@ -16,7 +16,7 @@ import type {
import type {Fiber, Dispatcher} from './ReactInternalTypes';
import type {Lanes, Lane} from './ReactFiberLane';
import type {HookEffectTag} from './ReactHookEffectTags';
import type {SuspenseConfig} from './ReactFiberSuspenseConfig';
import type {SuspenseConfig} from './ReactFiberTransition';
import type {ReactPriorityLevel} from './ReactInternalTypes';
import type {FiberRoot} from './ReactInternalTypes';
import type {OpaqueIDType} from './ReactFiberHostConfig';
@@ -70,7 +70,6 @@ import invariant from 'shared/invariant';
import getComponentName from 'shared/getComponentName';
import is from 'shared/objectIs';
import {markWorkInProgressReceivedUpdate} from './ReactFiberBeginWork.new';
import {requestCurrentSuspenseConfig} from './ReactFiberSuspenseConfig';
import {
UserBlockingPriority,
NormalPriority,
@@ -1003,8 +1002,7 @@ function useMutableSource<Source, Snapshot>(
if (!is(snapshot, maybeNewSnapshot)) {
setSnapshot(maybeNewSnapshot);
const suspenseConfig = requestCurrentSuspenseConfig();
const lane = requestUpdateLane(fiber, suspenseConfig);
const lane = requestUpdateLane(fiber);
markRootMutableRead(root, lane);
}
// If the source mutated between render and now,
@@ -1024,8 +1022,7 @@ function useMutableSource<Source, Snapshot>(
latestSetSnapshot(latestGetSnapshot(source._source));
// Record a pending mutable source update with the same expiration time.
const suspenseConfig = requestCurrentSuspenseConfig();
const lane = requestUpdateLane(fiber, suspenseConfig);
const lane = requestUpdateLane(fiber);
markRootMutableRead(root, lane);
} catch (error) {
@@ -1441,12 +1438,12 @@ function mountDeferredValue<T>(
): T {
const [prevValue, setValue] = mountState(value);
mountEffect(() => {
const previousConfig = ReactCurrentBatchConfig.suspense;
ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;
try {
setValue(value);
} finally {
ReactCurrentBatchConfig.suspense = previousConfig;
ReactCurrentBatchConfig.transition = prevTransition;
}
}, [value, config]);
return prevValue;
@@ -1458,12 +1455,12 @@ function updateDeferredValue<T>(
): T {
const [prevValue, setValue] = updateState(value);
updateEffect(() => {
const previousConfig = ReactCurrentBatchConfig.suspense;
ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;
try {
setValue(value);
} finally {
ReactCurrentBatchConfig.suspense = previousConfig;
ReactCurrentBatchConfig.transition = prevTransition;
}
}, [value, config]);
return prevValue;
@@ -1475,12 +1472,12 @@ function rerenderDeferredValue<T>(
): T {
const [prevValue, setValue] = rerenderState(value);
updateEffect(() => {
const previousConfig = ReactCurrentBatchConfig.suspense;
ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;
try {
setValue(value);
} finally {
ReactCurrentBatchConfig.suspense = previousConfig;
ReactCurrentBatchConfig.transition = prevTransition;
}
}, [value, config]);
return prevValue;
@@ -1509,8 +1506,8 @@ function startTransition(setPending, config, callback) {
runWithPriority(
priorityLevel > NormalPriority ? NormalPriority : priorityLevel,
() => {
const previousConfig = ReactCurrentBatchConfig.suspense;
ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;
try {
setPending(false);
callback();
@@ -1518,7 +1515,7 @@ function startTransition(setPending, config, callback) {
if (decoupleUpdatePriorityFromScheduler) {
setCurrentUpdateLanePriority(previousLanePriority);
}
ReactCurrentBatchConfig.suspense = previousConfig;
ReactCurrentBatchConfig.transition = prevTransition;
}
},
);
@@ -1535,13 +1532,13 @@ function startTransition(setPending, config, callback) {
runWithPriority(
priorityLevel > NormalPriority ? NormalPriority : priorityLevel,
() => {
const previousConfig = ReactCurrentBatchConfig.suspense;
ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;
try {
setPending(false);
callback();
} finally {
ReactCurrentBatchConfig.suspense = previousConfig;
ReactCurrentBatchConfig.transition = prevTransition;
}
},
);
@@ -1685,8 +1682,7 @@ function dispatchAction<S, A>(
}
const eventTime = requestEventTime();
const suspenseConfig = requestCurrentSuspenseConfig();
const lane = requestUpdateLane(fiber, suspenseConfig);
const lane = requestUpdateLane(fiber);
const update: Update<S, A> = {
lane,

View File

@@ -16,7 +16,7 @@ import type {
import type {Fiber, Dispatcher} from './ReactInternalTypes';
import type {Lanes, Lane} from './ReactFiberLane';
import type {HookEffectTag} from './ReactHookEffectTags';
import type {SuspenseConfig} from './ReactFiberSuspenseConfig';
import type {SuspenseConfig} from './ReactFiberTransition';
import type {ReactPriorityLevel} from './ReactInternalTypes';
import type {FiberRoot} from './ReactInternalTypes';
import type {OpaqueIDType} from './ReactFiberHostConfig';
@@ -69,7 +69,6 @@ import invariant from 'shared/invariant';
import getComponentName from 'shared/getComponentName';
import is from 'shared/objectIs';
import {markWorkInProgressReceivedUpdate} from './ReactFiberBeginWork.old';
import {requestCurrentSuspenseConfig} from './ReactFiberSuspenseConfig';
import {
UserBlockingPriority,
NormalPriority,
@@ -1002,8 +1001,7 @@ function useMutableSource<Source, Snapshot>(
if (!is(snapshot, maybeNewSnapshot)) {
setSnapshot(maybeNewSnapshot);
const suspenseConfig = requestCurrentSuspenseConfig();
const lane = requestUpdateLane(fiber, suspenseConfig);
const lane = requestUpdateLane(fiber);
markRootMutableRead(root, lane);
}
// If the source mutated between render and now,
@@ -1023,8 +1021,7 @@ function useMutableSource<Source, Snapshot>(
latestSetSnapshot(latestGetSnapshot(source._source));
// Record a pending mutable source update with the same expiration time.
const suspenseConfig = requestCurrentSuspenseConfig();
const lane = requestUpdateLane(fiber, suspenseConfig);
const lane = requestUpdateLane(fiber);
markRootMutableRead(root, lane);
} catch (error) {
@@ -1440,12 +1437,12 @@ function mountDeferredValue<T>(
): T {
const [prevValue, setValue] = mountState(value);
mountEffect(() => {
const previousConfig = ReactCurrentBatchConfig.suspense;
ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;
try {
setValue(value);
} finally {
ReactCurrentBatchConfig.suspense = previousConfig;
ReactCurrentBatchConfig.transition = prevTransition;
}
}, [value, config]);
return prevValue;
@@ -1457,12 +1454,12 @@ function updateDeferredValue<T>(
): T {
const [prevValue, setValue] = updateState(value);
updateEffect(() => {
const previousConfig = ReactCurrentBatchConfig.suspense;
ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;
try {
setValue(value);
} finally {
ReactCurrentBatchConfig.suspense = previousConfig;
ReactCurrentBatchConfig.transition = prevTransition;
}
}, [value, config]);
return prevValue;
@@ -1474,12 +1471,12 @@ function rerenderDeferredValue<T>(
): T {
const [prevValue, setValue] = rerenderState(value);
updateEffect(() => {
const previousConfig = ReactCurrentBatchConfig.suspense;
ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;
try {
setValue(value);
} finally {
ReactCurrentBatchConfig.suspense = previousConfig;
ReactCurrentBatchConfig.transition = prevTransition;
}
}, [value, config]);
return prevValue;
@@ -1508,8 +1505,8 @@ function startTransition(setPending, config, callback) {
runWithPriority(
priorityLevel > NormalPriority ? NormalPriority : priorityLevel,
() => {
const previousConfig = ReactCurrentBatchConfig.suspense;
ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;
try {
setPending(false);
callback();
@@ -1517,7 +1514,7 @@ function startTransition(setPending, config, callback) {
if (decoupleUpdatePriorityFromScheduler) {
setCurrentUpdateLanePriority(previousLanePriority);
}
ReactCurrentBatchConfig.suspense = previousConfig;
ReactCurrentBatchConfig.transition = prevTransition;
}
},
);
@@ -1534,13 +1531,13 @@ function startTransition(setPending, config, callback) {
runWithPriority(
priorityLevel > NormalPriority ? NormalPriority : priorityLevel,
() => {
const previousConfig = ReactCurrentBatchConfig.suspense;
ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;
try {
setPending(false);
callback();
} finally {
ReactCurrentBatchConfig.suspense = previousConfig;
ReactCurrentBatchConfig.transition = prevTransition;
}
},
);
@@ -1683,8 +1680,7 @@ function dispatchAction<S, A>(
}
const eventTime = requestEventTime();
const suspenseConfig = requestCurrentSuspenseConfig();
const lane = requestUpdateLane(fiber, suspenseConfig);
const lane = requestUpdateLane(fiber);
const update: Update<S, A> = {
lane,

View File

@@ -83,7 +83,6 @@ import {
getCurrentUpdateLanePriority,
setCurrentUpdateLanePriority,
} from './ReactFiberLane';
import {requestCurrentSuspenseConfig} from './ReactFiberSuspenseConfig';
import {
scheduleRefresh,
scheduleRoot,
@@ -266,8 +265,7 @@ export function updateContainer(
warnIfNotScopedWithMatchingAct(current);
}
}
const suspenseConfig = requestCurrentSuspenseConfig();
const lane = requestUpdateLane(current, suspenseConfig);
const lane = requestUpdateLane(current);
if (enableSchedulingProfiler) {
markRenderScheduled(lane);
@@ -427,7 +425,7 @@ export function attemptHydrationAtCurrentPriority(fiber: Fiber): void {
return;
}
const eventTime = requestEventTime();
const lane = requestUpdateLane(fiber, null);
const lane = requestUpdateLane(fiber);
scheduleUpdateOnFiber(fiber, lane, eventTime);
markRetryLaneIfNotHydrated(fiber, lane);
}

View File

@@ -83,7 +83,6 @@ import {
getCurrentUpdateLanePriority,
setCurrentUpdateLanePriority,
} from './ReactFiberLane';
import {requestCurrentSuspenseConfig} from './ReactFiberSuspenseConfig';
import {
scheduleRefresh,
scheduleRoot,
@@ -266,8 +265,7 @@ export function updateContainer(
warnIfNotScopedWithMatchingAct(current);
}
}
const suspenseConfig = requestCurrentSuspenseConfig();
const lane = requestUpdateLane(current, suspenseConfig);
const lane = requestUpdateLane(current);
if (enableSchedulingProfiler) {
markRenderScheduled(lane);
@@ -427,7 +425,7 @@ export function attemptHydrationAtCurrentPriority(fiber: Fiber): void {
return;
}
const eventTime = requestEventTime();
const lane = requestUpdateLane(fiber, null);
const lane = requestUpdateLane(fiber);
scheduleUpdateOnFiber(fiber, lane, eventTime);
markRetryLaneIfNotHydrated(fiber, lane);
}

View File

@@ -9,18 +9,22 @@
import ReactSharedInternals from 'shared/ReactSharedInternals';
const {ReactCurrentBatchConfig} = ReactSharedInternals;
// Deprecated
export type SuspenseConfig = {|
timeoutMs: number,
busyDelayMs?: number,
busyMinDurationMs?: number,
|};
// Deprecated
export type TimeoutConfig = {|
timeoutMs: number,
|};
export function requestCurrentSuspenseConfig(): null | SuspenseConfig {
return ReactCurrentBatchConfig.suspense;
const {ReactCurrentBatchConfig} = ReactSharedInternals;
export const NoTransition = 0;
export function requestCurrentTransition(): number {
return ReactCurrentBatchConfig.transition;
}

View File

@@ -12,7 +12,6 @@ import type {Fiber, FiberRoot} from './ReactInternalTypes';
import type {Lanes, Lane} from './ReactFiberLane';
import type {ReactPriorityLevel} from './ReactInternalTypes';
import type {Interaction} from 'scheduler/src/Tracing';
import type {SuspenseConfig} from './ReactFiberSuspenseConfig';
import type {SuspenseState} from './ReactFiberSuspenseComponent.new';
import type {StackCursor} from './ReactFiberStack.new';
import type {FunctionComponentUpdateQueue} from './ReactFiberHooks.new';
@@ -188,6 +187,7 @@ import {
schedulerPriorityToLanePriority,
lanePriorityToSchedulerPriority,
} from './ReactFiberLane';
import {requestCurrentTransition, NoTransition} from './ReactFiberTransition';
import {beginWork as originalBeginWork} from './ReactFiberBeginWork.new';
import {completeWork} from './ReactFiberCompleteWork.new';
import {unwindWork, unwindInterruptedWork} from './ReactFiberUnwindWork.new';
@@ -402,10 +402,7 @@ export function getCurrentTime() {
return now();
}
export function requestUpdateLane(
fiber: Fiber,
suspenseConfig: SuspenseConfig | null,
): Lane {
export function requestUpdateLane(fiber: Fiber): Lane {
// Special cases
const mode = fiber.mode;
if ((mode & BlockingMode) === NoMode) {
@@ -449,10 +446,8 @@ export function requestUpdateLane(
currentEventWipLanes = workInProgressRootIncludedLanes;
}
if (suspenseConfig !== null) {
// Use the size of the timeout as a heuristic to prioritize shorter
// transitions over longer ones.
// TODO: This will coerce numbers larger than 31 bits to 0.
const isTransition = requestCurrentTransition() !== NoTransition;
if (isTransition) {
if (currentEventPendingLanes !== NoLanes) {
currentEventPendingLanes =
mostRecentlyUpdatedRoot !== null

View File

@@ -12,7 +12,6 @@ import type {Fiber, FiberRoot} from './ReactInternalTypes';
import type {Lanes, Lane} from './ReactFiberLane';
import type {ReactPriorityLevel} from './ReactInternalTypes';
import type {Interaction} from 'scheduler/src/Tracing';
import type {SuspenseConfig} from './ReactFiberSuspenseConfig';
import type {SuspenseState} from './ReactFiberSuspenseComponent.old';
import type {Effect as HookEffect} from './ReactFiberHooks.old';
import type {StackCursor} from './ReactFiberStack.old';
@@ -174,6 +173,7 @@ import {
schedulerPriorityToLanePriority,
lanePriorityToSchedulerPriority,
} from './ReactFiberLane';
import {requestCurrentTransition, NoTransition} from './ReactFiberTransition';
import {beginWork as originalBeginWork} from './ReactFiberBeginWork.old';
import {completeWork} from './ReactFiberCompleteWork.old';
import {unwindWork, unwindInterruptedWork} from './ReactFiberUnwindWork.old';
@@ -390,10 +390,7 @@ export function getCurrentTime() {
return now();
}
export function requestUpdateLane(
fiber: Fiber,
suspenseConfig: SuspenseConfig | null,
): Lane {
export function requestUpdateLane(fiber: Fiber): Lane {
// Special cases
const mode = fiber.mode;
if ((mode & BlockingMode) === NoMode) {
@@ -437,10 +434,8 @@ export function requestUpdateLane(
currentEventWipLanes = workInProgressRootIncludedLanes;
}
if (suspenseConfig !== null) {
// Use the size of the timeout as a heuristic to prioritize shorter
// transitions over longer ones.
// TODO: This will coerce numbers larger than 31 bits to 0.
const isTransition = requestCurrentTransition() !== NoTransition;
if (isTransition) {
if (currentEventPendingLanes !== NoLanes) {
currentEventPendingLanes =
mostRecentlyUpdatedRoot !== null

View File

@@ -27,7 +27,7 @@ import type {RootTag} from './ReactRootTags';
import type {TimeoutHandle, NoTimeout} from './ReactFiberHostConfig';
import type {Wakeable} from 'shared/ReactTypes';
import type {Interaction} from 'scheduler/src/Tracing';
import type {SuspenseConfig, TimeoutConfig} from './ReactFiberSuspenseConfig';
import type {SuspenseConfig, TimeoutConfig} from './ReactFiberTransition';
export type ReactPriorityLevel = 99 | 98 | 97 | 96 | 95 | 90;

View File

@@ -7,17 +7,21 @@
* @flow
*/
import type {SuspenseConfig} from 'react-reconciler/src/ReactFiberSuspenseConfig';
import type {SuspenseConfig} from 'react-reconciler/src/ReactFiberTransition';
import ReactCurrentBatchConfig from './ReactCurrentBatchConfig';
// Within the scope of the callback, mark all updates as being allowed to suspend.
// This is a copy of startTransition, except if null or undefined is passed,
// then updates inside the scope are opted-out of the outer transition scope.
// TODO: Deprecated. Remove in favor of startTransition. Figure out how scopes
// should nest, and whether we need an API to opt-out nested scopes.
export function withSuspenseConfig(scope: () => void, config?: SuspenseConfig) {
const previousConfig = ReactCurrentBatchConfig.suspense;
ReactCurrentBatchConfig.suspense = config === undefined ? null : config;
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition =
config === undefined || config === null ? 0 : 1;
try {
scope();
} finally {
ReactCurrentBatchConfig.suspense = previousConfig;
ReactCurrentBatchConfig.transition = prevTransition;
}
}

View File

@@ -7,14 +7,12 @@
* @flow
*/
import type {SuspenseConfig} from 'react-reconciler/src/ReactFiberSuspenseConfig';
/**
* Keeps track of the current batch's configuration such as how long an update
* should suspend for if it needs to.
*/
const ReactCurrentBatchConfig = {
suspense: (null: null | SuspenseConfig),
transition: (0: number),
};
export default ReactCurrentBatchConfig;

View File

@@ -9,16 +9,12 @@
import ReactCurrentBatchConfig from './ReactCurrentBatchConfig';
// Default to an arbitrarily large timeout. Effectively, this is infinite. The
// eventual goal is to never timeout when refreshing already visible content.
const IndefiniteTimeoutConfig = {timeoutMs: 100000};
export function startTransition(scope: () => void) {
const previousConfig = ReactCurrentBatchConfig.suspense;
ReactCurrentBatchConfig.suspense = IndefiniteTimeoutConfig;
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;
try {
scope();
} finally {
ReactCurrentBatchConfig.suspense = previousConfig;
ReactCurrentBatchConfig.transition = prevTransition;
}
}