Implemented Profiler onCommit() and onPostCommit() hooks (#17910)

* Implemented Profiler onCommit() and onPostCommit() hooks
* Added enableProfilerCommitHooks feature flag for commit hooks
* Moved onCommit and onPassiveCommit behind separate feature flag
This commit is contained in:
Brian Vaughn
2020-03-05 11:02:00 -08:00
committed by GitHub
parent d35f8a5818
commit 024a764310
15 changed files with 2869 additions and 1134 deletions
+9 -7
View File
@@ -826,13 +826,8 @@ function createFiberFromProfiler(
key: null | string,
): Fiber {
if (__DEV__) {
if (
typeof pendingProps.id !== 'string' ||
typeof pendingProps.onRender !== 'function'
) {
console.error(
'Profiler must specify an "id" string and "onRender" function as props',
);
if (typeof pendingProps.id !== 'string') {
console.error('Profiler must specify an "id" as a prop');
}
}
@@ -842,6 +837,13 @@ function createFiberFromProfiler(
fiber.type = REACT_PROFILER_TYPE;
fiber.expirationTime = expirationTime;
if (enableProfilerTimer) {
fiber.stateNode = {
effectDuration: 0,
passiveEffectDuration: 0,
};
}
return fiber;
}
+12
View File
@@ -580,6 +580,12 @@ function updateProfiler(
) {
if (enableProfilerTimer) {
workInProgress.effectTag |= Update;
// Reset effect durations for the next eventual effect phase.
// These are reset during render to allow the DevTools commit hook a chance to read them,
const stateNode = workInProgress.stateNode;
stateNode.effectDuration = 0;
stateNode.passiveEffectDuration = 0;
}
const nextProps = workInProgress.pendingProps;
const nextChildren = nextProps.children;
@@ -2944,6 +2950,12 @@ function beginWork(
if (hasChildWork) {
workInProgress.effectTag |= Update;
}
// Reset effect durations for the next eventual effect phase.
// These are reset during render to allow the DevTools commit hook a chance to read them,
const stateNode = workInProgress.stateNode;
stateNode.effectDuration = 0;
stateNode.passiveEffectDuration = 0;
}
break;
case SuspenseComponent: {
+256 -19
View File
@@ -29,6 +29,7 @@ import {
deferPassiveEffectCleanupDuringUnmount,
enableSchedulerTracing,
enableProfilerTimer,
enableProfilerCommitHooks,
enableSuspenseServerRenderer,
enableDeprecatedFlareAPI,
enableFundamentalAPI,
@@ -76,7 +77,14 @@ import {startPhaseTimer, stopPhaseTimer} from './ReactDebugFiberPerf';
import {getStackByFiberInDevAndProd} from './ReactCurrentFiber';
import {logCapturedError} from './ReactFiberErrorLogger';
import {resolveDefaultProps} from './ReactFiberLazyComponent';
import {getCommitTime} from './ReactProfilerTimer';
import {
getCommitTime,
recordLayoutEffectDuration,
recordPassiveEffectDuration,
startLayoutEffectTimer,
startPassiveEffectTimer,
} from './ReactProfilerTimer';
import {ProfileMode} from './ReactTypeOfMode';
import {commitUpdateQueue} from './ReactUpdateQueue';
import {
getPublicInstance,
@@ -113,6 +121,7 @@ import {
markCommitTimeOfFallback,
enqueuePendingPassiveHookEffectMount,
enqueuePendingPassiveHookEffectUnmount,
enqueuePendingPassiveProfilerEffect,
} from './ReactFiberWorkLoop';
import {
NoEffect as NoHookEffect,
@@ -175,7 +184,20 @@ const callComponentWillUnmountWithTimer = function(current, instance) {
startPhaseTimer(current, 'componentWillUnmount');
instance.props = current.memoizedProps;
instance.state = current.memoizedState;
instance.componentWillUnmount();
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
current.mode & ProfileMode
) {
try {
startLayoutEffectTimer();
instance.componentWillUnmount();
} finally {
recordLayoutEffectDuration(current);
}
} else {
instance.componentWillUnmount();
}
stopPhaseTimer();
};
@@ -430,8 +452,31 @@ export function commitPassiveHookEffects(finishedWork: Fiber): void {
// TODO (#17945) We should call all passive destroy functions (for all fibers)
// before calling any create functions. The current approach only serializes
// these for a single fiber.
commitHookEffectListUnmount(HookPassive | HookHasEffect, finishedWork);
commitHookEffectListMount(HookPassive | HookHasEffect, finishedWork);
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
finishedWork.mode & ProfileMode
) {
try {
startPassiveEffectTimer();
commitHookEffectListUnmount(
HookPassive | HookHasEffect,
finishedWork,
);
commitHookEffectListMount(
HookPassive | HookHasEffect,
finishedWork,
);
} finally {
recordPassiveEffectDuration(finishedWork);
}
} else {
commitHookEffectListUnmount(
HookPassive | HookHasEffect,
finishedWork,
);
commitHookEffectListMount(HookPassive | HookHasEffect, finishedWork);
}
break;
}
default:
@@ -440,6 +485,61 @@ export function commitPassiveHookEffects(finishedWork: Fiber): void {
}
}
export function commitPassiveEffectDurations(
finishedRoot: FiberRoot,
finishedWork: Fiber,
): void {
if (enableProfilerTimer && enableProfilerCommitHooks) {
// Only Profilers with work in their subtree will have an Update effect scheduled.
if ((finishedWork.effectTag & Update) !== NoEffect) {
switch (finishedWork.tag) {
case Profiler: {
const {passiveEffectDuration} = finishedWork.stateNode;
const {id, onPostCommit} = finishedWork.memoizedProps;
// This value will still reflect the previous commit phase.
// It does not get reset until the start of the next commit phase.
const commitTime = getCommitTime();
if (typeof onPostCommit === 'function') {
if (enableSchedulerTracing) {
onPostCommit(
id,
finishedWork.alternate === null ? 'mount' : 'update',
passiveEffectDuration,
commitTime,
finishedRoot.memoizedInteractions,
);
} else {
onPostCommit(
id,
finishedWork.alternate === null ? 'mount' : 'update',
passiveEffectDuration,
commitTime,
);
}
}
// Bubble times to the next nearest ancestor Profiler.
// After we process that Profiler, we'll bubble further up.
let parentFiber = finishedWork.return;
while (parentFiber !== null) {
if (parentFiber.tag === Profiler) {
const parentStateNode = parentFiber.stateNode;
parentStateNode.passiveEffectDuration += passiveEffectDuration;
break;
}
parentFiber = parentFiber.return;
}
break;
}
default:
break;
}
}
}
}
function commitLifeCycles(
finishedRoot: FiberRoot,
current: Fiber | null,
@@ -455,7 +555,20 @@ function commitLifeCycles(
// This is done to prevent sibling component effects from interfering with each other,
// e.g. a destroy function in one component should never override a ref set
// by a create function in another component during the same commit.
commitHookEffectListMount(HookLayout | HookHasEffect, finishedWork);
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
finishedWork.mode & ProfileMode
) {
try {
startLayoutEffectTimer();
commitHookEffectListMount(HookLayout | HookHasEffect, finishedWork);
} finally {
recordLayoutEffectDuration(finishedWork);
}
} else {
commitHookEffectListMount(HookLayout | HookHasEffect, finishedWork);
}
if (runAllPassiveEffectDestroysBeforeCreates) {
schedulePassiveEffects(finishedWork);
@@ -497,7 +610,20 @@ function commitLifeCycles(
}
}
}
instance.componentDidMount();
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
finishedWork.mode & ProfileMode
) {
try {
startLayoutEffectTimer();
instance.componentDidMount();
} finally {
recordLayoutEffectDuration(finishedWork);
}
} else {
instance.componentDidMount();
}
stopPhaseTimer();
} else {
const prevProps =
@@ -536,11 +662,28 @@ function commitLifeCycles(
}
}
}
instance.componentDidUpdate(
prevProps,
prevState,
instance.__reactInternalSnapshotBeforeUpdate,
);
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
finishedWork.mode & ProfileMode
) {
try {
startLayoutEffectTimer();
instance.componentDidUpdate(
prevProps,
prevState,
instance.__reactInternalSnapshotBeforeUpdate,
);
} finally {
recordLayoutEffectDuration(finishedWork);
}
} else {
instance.componentDidUpdate(
prevProps,
prevState,
instance.__reactInternalSnapshotBeforeUpdate,
);
}
stopPhaseTimer();
}
}
@@ -623,7 +766,10 @@ function commitLifeCycles(
}
case Profiler: {
if (enableProfilerTimer) {
const onRender = finishedWork.memoizedProps.onRender;
const {onCommit, onRender} = finishedWork.memoizedProps;
const {effectDuration} = finishedWork.stateNode;
const commitTime = getCommitTime();
if (typeof onRender === 'function') {
if (enableSchedulerTracing) {
@@ -633,7 +779,7 @@ function commitLifeCycles(
finishedWork.actualDuration,
finishedWork.treeBaseDuration,
finishedWork.actualStartTime,
getCommitTime(),
commitTime,
finishedRoot.memoizedInteractions,
);
} else {
@@ -643,10 +789,48 @@ function commitLifeCycles(
finishedWork.actualDuration,
finishedWork.treeBaseDuration,
finishedWork.actualStartTime,
getCommitTime(),
commitTime,
);
}
}
if (enableProfilerCommitHooks) {
if (typeof onCommit === 'function') {
if (enableSchedulerTracing) {
onCommit(
finishedWork.memoizedProps.id,
current === null ? 'mount' : 'update',
effectDuration,
commitTime,
finishedRoot.memoizedInteractions,
);
} else {
onCommit(
finishedWork.memoizedProps.id,
current === null ? 'mount' : 'update',
effectDuration,
commitTime,
);
}
}
// Schedule a passive effect for this Profiler to call onPostCommit hooks.
// This effect should be scheduled even if there is no onPostCommit callback for this Profiler,
// because the effect is also where times bubble to parent Profilers.
enqueuePendingPassiveProfilerEffect(finishedWork);
// Propagate layout effect durations to the next nearest Profiler ancestor.
// Do not reset these values until the next render so DevTools has a chance to read them first.
let parentFiber = finishedWork.return;
while (parentFiber !== null) {
if (parentFiber.tag === Profiler) {
const parentStateNode = parentFiber.stateNode;
parentStateNode.effectDuration += effectDuration;
break;
}
parentFiber = parentFiber.return;
}
}
}
return;
}
@@ -797,7 +981,17 @@ function commitUnmount(
if ((tag & HookPassive) !== NoHookEffect) {
enqueuePendingPassiveHookEffectUnmount(current, effect);
} else {
safelyCallDestroy(current, destroy);
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
current.mode & ProfileMode
) {
startLayoutEffectTimer();
safelyCallDestroy(current, destroy);
recordLayoutEffectDuration(current);
} else {
safelyCallDestroy(current, destroy);
}
}
}
effect = effect.next;
@@ -822,9 +1016,23 @@ function commitUnmount(
runWithPriority(priorityLevel, () => {
let effect = firstEffect;
do {
const destroy = effect.destroy;
const {destroy, tag} = effect;
if (destroy !== undefined) {
safelyCallDestroy(current, destroy);
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
current.mode & ProfileMode
) {
if ((tag & HookPassive) !== NoHookEffect) {
safelyCallDestroy(current, destroy);
} else {
startLayoutEffectTimer();
safelyCallDestroy(current, destroy);
recordLayoutEffectDuration(current);
}
} else {
safelyCallDestroy(current, destroy);
}
}
effect = effect.next;
} while (effect !== firstEffect);
@@ -1366,7 +1574,23 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
// This prevents sibling component effects from interfering with each other,
// e.g. a destroy function in one component should never override a ref set
// by a create function in another component during the same commit.
commitHookEffectListUnmount(HookLayout | HookHasEffect, finishedWork);
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
finishedWork.mode & ProfileMode
) {
try {
startLayoutEffectTimer();
commitHookEffectListUnmount(
HookLayout | HookHasEffect,
finishedWork,
);
} finally {
recordLayoutEffectDuration(finishedWork);
}
} else {
commitHookEffectListUnmount(HookLayout | HookHasEffect, finishedWork);
}
return;
}
case Profiler: {
@@ -1409,7 +1633,20 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
// This prevents sibling component effects from interfering with each other,
// e.g. a destroy function in one component should never override a ref set
// by a create function in another component during the same commit.
commitHookEffectListUnmount(HookLayout | HookHasEffect, finishedWork);
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
finishedWork.mode & ProfileMode
) {
try {
startLayoutEffectTimer();
commitHookEffectListUnmount(HookLayout | HookHasEffect, finishedWork);
} finally {
recordLayoutEffectDuration(finishedWork);
}
} else {
commitHookEffectListUnmount(HookLayout | HookHasEffect, finishedWork);
}
return;
}
case ClassComponent: {
+79 -5
View File
@@ -24,6 +24,7 @@ import {
enableSuspenseServerRenderer,
replayFailedUnitOfWorkWithInvokeGuardedCallback,
enableProfilerTimer,
enableProfilerCommitHooks,
enableSchedulerTracing,
warnAboutUnmockedScheduler,
flushSuspenseFallbacksInTests,
@@ -139,6 +140,7 @@ import {
commitDeletion,
commitDetachRef,
commitAttachRef,
commitPassiveEffectDurations,
commitResetTextContent,
} from './ReactFiberCommitWork';
import {enqueueUpdate} from './ReactUpdateQueue';
@@ -148,6 +150,8 @@ import {createCapturedValue} from './ReactCapturedValue';
import {
recordCommitTime,
recordPassiveEffectDuration,
startPassiveEffectTimer,
startProfilerTimer,
stopProfilerTimerIfRunningAndRecordDelta,
} from './ReactProfilerTimer';
@@ -261,6 +265,7 @@ let pendingPassiveEffectsRenderPriority: ReactPriorityLevel = NoPriority;
let pendingPassiveEffectsExpirationTime: ExpirationTime = NoWork;
let pendingPassiveHookEffectsMount: Array<HookEffect | Fiber> = [];
let pendingPassiveHookEffectsUnmount: Array<HookEffect | Fiber> = [];
let pendingPassiveProfilerEffects: Array<Fiber> = [];
let rootsWithPendingDiscreteUpdates: Map<
FiberRoot,
@@ -2209,6 +2214,19 @@ export function flushPassiveEffects() {
}
}
export function enqueuePendingPassiveProfilerEffect(fiber: Fiber): void {
if (enableProfilerTimer && enableProfilerCommitHooks) {
pendingPassiveProfilerEffects.push(fiber);
if (!rootDoesHavePassiveEffects) {
rootDoesHavePassiveEffects = true;
scheduleCallback(NormalPriority, () => {
flushPassiveEffects();
return null;
});
}
}
}
export function enqueuePendingPassiveHookEffectMount(
fiber: Fiber,
effect: HookEffect,
@@ -2250,6 +2268,7 @@ function flushPassiveEffectsImpl() {
if (rootWithPendingPassiveEffects === null) {
return false;
}
const root = rootWithPendingPassiveEffects;
const expirationTime = pendingPassiveEffectsExpirationTime;
rootWithPendingPassiveEffects = null;
@@ -2282,7 +2301,17 @@ function flushPassiveEffectsImpl() {
if (typeof destroy === 'function') {
if (__DEV__) {
setCurrentDebugFiberInDEV(fiber);
invokeGuardedCallback(null, destroy, null);
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
fiber.mode & ProfileMode
) {
startPassiveEffectTimer();
invokeGuardedCallback(null, destroy, null);
recordPassiveEffectDuration(fiber);
} else {
invokeGuardedCallback(null, destroy, null);
}
if (hasCaughtError()) {
invariant(fiber !== null, 'Should be working on an effect.');
const error = clearCaughtError();
@@ -2291,7 +2320,20 @@ function flushPassiveEffectsImpl() {
resetCurrentDebugFiberInDEV();
} else {
try {
destroy();
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
fiber.mode & ProfileMode
) {
try {
startPassiveEffectTimer();
destroy();
} finally {
recordPassiveEffectDuration(fiber);
}
} else {
destroy();
}
} catch (error) {
invariant(fiber !== null, 'Should be working on an effect.');
captureCommitPhaseError(fiber, error);
@@ -2299,7 +2341,6 @@ function flushPassiveEffectsImpl() {
}
}
}
// Second pass: Create new passive effects.
let mountEffects = pendingPassiveHookEffectsMount;
pendingPassiveHookEffectsMount = [];
@@ -2308,7 +2349,17 @@ function flushPassiveEffectsImpl() {
const fiber = ((mountEffects[i + 1]: any): Fiber);
if (__DEV__) {
setCurrentDebugFiberInDEV(fiber);
invokeGuardedCallback(null, invokePassiveEffectCreate, null, effect);
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
fiber.mode & ProfileMode
) {
startPassiveEffectTimer();
invokeGuardedCallback(null, invokePassiveEffectCreate, null, effect);
recordPassiveEffectDuration(fiber);
} else {
invokeGuardedCallback(null, invokePassiveEffectCreate, null, effect);
}
if (hasCaughtError()) {
invariant(fiber !== null, 'Should be working on an effect.');
const error = clearCaughtError();
@@ -2318,7 +2369,20 @@ function flushPassiveEffectsImpl() {
} else {
try {
const create = effect.create;
effect.destroy = create();
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
fiber.mode & ProfileMode
) {
try {
startPassiveEffectTimer();
effect.destroy = create();
} finally {
recordPassiveEffectDuration(fiber);
}
} else {
effect.destroy = create();
}
} catch (error) {
invariant(fiber !== null, 'Should be working on an effect.');
captureCommitPhaseError(fiber, error);
@@ -2348,6 +2412,7 @@ function flushPassiveEffectsImpl() {
captureCommitPhaseError(effect, error);
}
}
const nextNextEffect = effect.nextEffect;
// Remove nextEffect pointer to assist GC
effect.nextEffect = null;
@@ -2355,6 +2420,15 @@ function flushPassiveEffectsImpl() {
}
}
if (enableProfilerTimer && enableProfilerCommitHooks) {
let profilerEffects = pendingPassiveProfilerEffects;
pendingPassiveProfilerEffects = [];
for (let i = 0; i < profilerEffects.length; i++) {
const fiber = ((profilerEffects[i]: any): Fiber);
commitPassiveEffectDurations(root, fiber);
}
}
if (enableSchedulerTracing) {
popInteractions(((prevInteractions: any): Set<Interaction>));
finishPendingInteractions(root, expirationTime);
+76 -1
View File
@@ -9,7 +9,11 @@
import type {Fiber} from './ReactFiber';
import {enableProfilerTimer} from 'shared/ReactFeatureFlags';
import {
enableProfilerTimer,
enableProfilerCommitHooks,
} from 'shared/ReactFeatureFlags';
import {Profiler} from 'shared/ReactWorkTags';
// Intentionally not named imports because Rollup would use dynamic dispatch for
// CommonJS interop named imports.
@@ -27,7 +31,9 @@ export type ProfilerTimer = {
};
let commitTime: number = 0;
let layoutEffectStartTime: number = -1;
let profilerStartTime: number = -1;
let passiveEffectStartTime: number = -1;
function getCommitTime(): number {
return commitTime;
@@ -77,9 +83,78 @@ function stopProfilerTimerIfRunningAndRecordDelta(
}
}
function recordLayoutEffectDuration(fiber: Fiber): void {
if (!enableProfilerTimer || !enableProfilerCommitHooks) {
return;
}
if (layoutEffectStartTime >= 0) {
const elapsedTime = now() - layoutEffectStartTime;
layoutEffectStartTime = -1;
// Store duration on the next nearest Profiler ancestor.
let parentFiber = fiber.return;
while (parentFiber !== null) {
if (parentFiber.tag === Profiler) {
const parentStateNode = parentFiber.stateNode;
parentStateNode.effectDuration += elapsedTime;
break;
}
parentFiber = parentFiber.return;
}
}
}
function recordPassiveEffectDuration(fiber: Fiber): void {
if (!enableProfilerTimer || !enableProfilerCommitHooks) {
return;
}
if (passiveEffectStartTime >= 0) {
const elapsedTime = now() - passiveEffectStartTime;
passiveEffectStartTime = -1;
// Store duration on the next nearest Profiler ancestor.
let parentFiber = fiber.return;
while (parentFiber !== null) {
if (parentFiber.tag === Profiler) {
const parentStateNode = parentFiber.stateNode;
if (parentStateNode !== null) {
// Detached fibers have their state node cleared out.
// In this case, the return pointer is also cleared out,
// so we won't be able to report the time spent in this Profiler's subtree.
parentStateNode.passiveEffectDuration += elapsedTime;
}
break;
}
parentFiber = parentFiber.return;
}
}
}
function startLayoutEffectTimer(): void {
if (!enableProfilerTimer || !enableProfilerCommitHooks) {
return;
}
layoutEffectStartTime = now();
}
function startPassiveEffectTimer(): void {
if (!enableProfilerTimer || !enableProfilerCommitHooks) {
return;
}
passiveEffectStartTime = now();
}
export {
getCommitTime,
recordCommitTime,
recordLayoutEffectDuration,
recordPassiveEffectDuration,
startLayoutEffectTimer,
startPassiveEffectTimer,
startProfilerTimer,
stopProfilerTimerIfRunning,
stopProfilerTimerIfRunningAndRecordDelta,
File diff suppressed because it is too large Load Diff
+3
View File
@@ -23,6 +23,9 @@ export const warnAboutDeprecatedLifecycles = true;
// Gather advanced timing metrics for Profiler subtrees.
export const enableProfilerTimer = __PROFILE__;
// Record durations for commit and passive effects phases.
export const enableProfilerCommitHooks = false;
// Trace which interactions trigger each commit.
export const enableSchedulerTracing = __PROFILE__;
@@ -15,6 +15,7 @@ import typeof * as ExportsType from './ReactFeatureFlags.native-fb';
// The rest of the flags are static for better dead code elimination.
export const enableUserTimingAPI = __DEV__;
export const enableProfilerTimer = __PROFILE__;
export const enableProfilerCommitHooks = false;
export const enableSchedulerTracing = __PROFILE__;
export const enableSuspenseServerRenderer = false;
export const enableSelectiveHydration = false;
@@ -17,6 +17,7 @@ export const enableUserTimingAPI = __DEV__;
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__;
export const warnAboutDeprecatedLifecycles = true;
export const enableProfilerTimer = __PROFILE__;
export const enableProfilerCommitHooks = false;
export const enableSchedulerTracing = __PROFILE__;
export const enableSuspenseServerRenderer = false;
export const enableSelectiveHydration = false;
@@ -17,6 +17,7 @@ export const enableUserTimingAPI = __DEV__;
export const warnAboutDeprecatedLifecycles = true;
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__;
export const enableProfilerTimer = __PROFILE__;
export const enableProfilerCommitHooks = false;
export const enableSchedulerTracing = __PROFILE__;
export const enableSuspenseServerRenderer = false;
export const enableSelectiveHydration = false;
@@ -17,6 +17,7 @@ export const enableUserTimingAPI = __DEV__;
export const warnAboutDeprecatedLifecycles = true;
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
export const enableProfilerTimer = __PROFILE__;
export const enableProfilerCommitHooks = false;
export const enableSchedulerTracing = __PROFILE__;
export const enableSuspenseServerRenderer = false;
export const enableSelectiveHydration = false;
@@ -17,6 +17,7 @@ export const enableUserTimingAPI = __DEV__;
export const warnAboutDeprecatedLifecycles = true;
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
export const enableProfilerTimer = __PROFILE__;
export const enableProfilerCommitHooks = false;
export const enableSchedulerTracing = __PROFILE__;
export const enableSuspenseServerRenderer = false;
export const enableSelectiveHydration = false;
@@ -17,6 +17,7 @@ export const enableUserTimingAPI = __DEV__;
export const warnAboutDeprecatedLifecycles = true;
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
export const enableProfilerTimer = __PROFILE__;
export const enableProfilerCommitHooks = false;
export const enableSchedulerTracing = __PROFILE__;
export const enableSuspenseServerRenderer = false;
export const enableSelectiveHydration = false;
@@ -17,6 +17,7 @@ export const enableUserTimingAPI = false;
export const warnAboutDeprecatedLifecycles = true;
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
export const enableProfilerTimer = false;
export const enableProfilerCommitHooks = false;
export const enableSchedulerTracing = false;
export const enableSuspenseServerRenderer = true;
export const enableSelectiveHydration = true;
@@ -35,6 +35,7 @@ export const {
export let enableUserTimingAPI = __DEV__ && !__EXPERIMENTAL__;
export const enableProfilerTimer = __PROFILE__;
export const enableProfilerCommitHooks = false;
export const enableSchedulerTracing = __PROFILE__;
export const enableSchedulerDebugging = true;