Skip to content

Commit

Permalink
Fork ReactFiberExpirationTime
Browse files Browse the repository at this point in the history
I had thought I wouldn't fork this one because the new "lanes" module
will be pretty different, but I need it to make some
incremental changes.
  • Loading branch information
acdlite committed Apr 9, 2020
1 parent e5d06e3 commit dc630d3
Show file tree
Hide file tree
Showing 43 changed files with 214 additions and 67 deletions.
2 changes: 1 addition & 1 deletion packages/react-reconciler/src/ReactChildFiber.new.js
Expand Up @@ -12,7 +12,7 @@ import type {ReactPortal} from 'shared/ReactTypes';
import type {BlockComponent} from 'react/src/ReactBlock';
import type {LazyComponent} from 'react/src/ReactLazy';
import type {Fiber} from './ReactInternalTypes';
import type {ExpirationTime} from './ReactFiberExpirationTime';
import type {ExpirationTime} from './ReactFiberExpirationTime.new';

import getComponentName from 'shared/getComponentName';
import {Placement, Deletion} from './ReactSideEffectTags';
Expand Down
2 changes: 1 addition & 1 deletion packages/react-reconciler/src/ReactChildFiber.old.js
Expand Up @@ -12,7 +12,7 @@ import type {ReactPortal} from 'shared/ReactTypes';
import type {BlockComponent} from 'react/src/ReactBlock';
import type {LazyComponent} from 'react/src/ReactLazy';
import type {Fiber} from './ReactInternalTypes';
import type {ExpirationTime} from './ReactFiberExpirationTime';
import type {ExpirationTime} from './ReactFiberExpirationTime.old';

import getComponentName from 'shared/getComponentName';
import {Placement, Deletion} from './ReactSideEffectTags';
Expand Down
4 changes: 2 additions & 2 deletions packages/react-reconciler/src/ReactFiber.new.js
Expand Up @@ -18,7 +18,7 @@ import type {Fiber} from './ReactInternalTypes';
import type {RootTag} from './ReactRootTags';
import type {WorkTag} from './ReactWorkTags';
import type {TypeOfMode} from './ReactTypeOfMode';
import type {ExpirationTime} from './ReactFiberExpirationTime';
import type {ExpirationTime} from './ReactFiberExpirationTime.new';
import type {SuspenseInstance} from './ReactFiberHostConfig';

import invariant from 'shared/invariant';
Expand Down Expand Up @@ -63,7 +63,7 @@ import {
resolveFunctionForHotReloading,
resolveForwardRefForHotReloading,
} from './ReactFiberHotReloading.new';
import {NoWork} from './ReactFiberExpirationTime';
import {NoWork} from './ReactFiberExpirationTime.new';
import {
NoMode,
ConcurrentMode,
Expand Down
4 changes: 2 additions & 2 deletions packages/react-reconciler/src/ReactFiber.old.js
Expand Up @@ -18,7 +18,7 @@ import type {Fiber} from './ReactInternalTypes';
import type {RootTag} from './ReactRootTags';
import type {WorkTag} from './ReactWorkTags';
import type {TypeOfMode} from './ReactTypeOfMode';
import type {ExpirationTime} from './ReactFiberExpirationTime';
import type {ExpirationTime} from './ReactFiberExpirationTime.old';
import type {SuspenseInstance} from './ReactFiberHostConfig';

import invariant from 'shared/invariant';
Expand Down Expand Up @@ -63,7 +63,7 @@ import {
resolveFunctionForHotReloading,
resolveForwardRefForHotReloading,
} from './ReactFiberHotReloading.old';
import {NoWork} from './ReactFiberExpirationTime';
import {NoWork} from './ReactFiberExpirationTime.old';
import {
NoMode,
ConcurrentMode,
Expand Down
4 changes: 2 additions & 2 deletions packages/react-reconciler/src/ReactFiberBeginWork.new.js
Expand Up @@ -12,7 +12,7 @@ import type {BlockComponent} from 'react/src/ReactBlock';
import type {LazyComponent as LazyComponentType} from 'react/src/ReactLazy';
import type {Fiber} from './ReactInternalTypes';
import type {FiberRoot} from './ReactInternalTypes';
import type {ExpirationTime} from './ReactFiberExpirationTime';
import type {ExpirationTime} from './ReactFiberExpirationTime.new';
import type {
SuspenseState,
SuspenseListRenderState,
Expand Down Expand Up @@ -100,7 +100,7 @@ import {
Never,
Sync,
computeAsyncExpiration,
} from './ReactFiberExpirationTime';
} from './ReactFiberExpirationTime.new';
import {
ConcurrentMode,
NoMode,
Expand Down
4 changes: 2 additions & 2 deletions packages/react-reconciler/src/ReactFiberBeginWork.old.js
Expand Up @@ -12,7 +12,7 @@ import type {BlockComponent} from 'react/src/ReactBlock';
import type {LazyComponent as LazyComponentType} from 'react/src/ReactLazy';
import type {Fiber} from './ReactInternalTypes';
import type {FiberRoot} from './ReactInternalTypes';
import type {ExpirationTime} from './ReactFiberExpirationTime';
import type {ExpirationTime} from './ReactFiberExpirationTime.old';
import type {
SuspenseState,
SuspenseListRenderState,
Expand Down Expand Up @@ -100,7 +100,7 @@ import {
Never,
Sync,
computeAsyncExpiration,
} from './ReactFiberExpirationTime';
} from './ReactFiberExpirationTime.old';
import {
ConcurrentMode,
NoMode,
Expand Down
4 changes: 2 additions & 2 deletions packages/react-reconciler/src/ReactFiberClassComponent.new.js
Expand Up @@ -8,7 +8,7 @@
*/

import type {Fiber} from './ReactInternalTypes';
import type {ExpirationTime} from './ReactFiberExpirationTime';
import type {ExpirationTime} from './ReactFiberExpirationTime.new';
import type {UpdateQueue} from './ReactUpdateQueue.new';

import * as React from 'react';
Expand Down Expand Up @@ -40,7 +40,7 @@ import {
initializeUpdateQueue,
cloneUpdateQueue,
} from './ReactUpdateQueue.new';
import {NoWork} from './ReactFiberExpirationTime';
import {NoWork} from './ReactFiberExpirationTime.new';
import {
cacheContext,
getMaskedContext,
Expand Down
4 changes: 2 additions & 2 deletions packages/react-reconciler/src/ReactFiberClassComponent.old.js
Expand Up @@ -8,7 +8,7 @@
*/

import type {Fiber} from './ReactInternalTypes';
import type {ExpirationTime} from './ReactFiberExpirationTime';
import type {ExpirationTime} from './ReactFiberExpirationTime.old';
import type {UpdateQueue} from './ReactUpdateQueue.old';

import * as React from 'react';
Expand Down Expand Up @@ -40,7 +40,7 @@ import {
initializeUpdateQueue,
cloneUpdateQueue,
} from './ReactUpdateQueue.old';
import {NoWork} from './ReactFiberExpirationTime';
import {NoWork} from './ReactFiberExpirationTime.old';
import {
cacheContext,
getMaskedContext,
Expand Down
2 changes: 1 addition & 1 deletion packages/react-reconciler/src/ReactFiberCommitWork.new.js
Expand Up @@ -17,7 +17,7 @@ import type {
} from './ReactFiberHostConfig';
import type {Fiber} from './ReactInternalTypes';
import type {FiberRoot} from './ReactInternalTypes';
import type {ExpirationTime} from './ReactFiberExpirationTime';
import type {ExpirationTime} from './ReactFiberExpirationTime.new';
import type {SuspenseState} from './ReactFiberSuspenseComponent.new';
import type {UpdateQueue} from './ReactUpdateQueue.new';
import type {FunctionComponentUpdateQueue} from './ReactFiberHooks.new';
Expand Down
2 changes: 1 addition & 1 deletion packages/react-reconciler/src/ReactFiberCommitWork.old.js
Expand Up @@ -17,7 +17,7 @@ import type {
} from './ReactFiberHostConfig';
import type {Fiber} from './ReactInternalTypes';
import type {FiberRoot} from './ReactInternalTypes';
import type {ExpirationTime} from './ReactFiberExpirationTime';
import type {ExpirationTime} from './ReactFiberExpirationTime.old';
import type {SuspenseState} from './ReactFiberSuspenseComponent.old';
import type {UpdateQueue} from './ReactUpdateQueue.old';
import type {FunctionComponentUpdateQueue} from './ReactFiberHooks.old';
Expand Down
4 changes: 2 additions & 2 deletions packages/react-reconciler/src/ReactFiberCompleteWork.new.js
Expand Up @@ -8,7 +8,7 @@
*/

import type {Fiber} from './ReactInternalTypes';
import type {ExpirationTime} from './ReactFiberExpirationTime';
import type {ExpirationTime} from './ReactFiberExpirationTime.new';
import type {
ReactFundamentalComponentInstance,
ReactScopeInstance,
Expand Down Expand Up @@ -129,7 +129,7 @@ import {
renderHasNotSuspendedYet,
} from './ReactFiberWorkLoop.new';
import {createFundamentalStateInstance} from './ReactFiberFundamental.new';
import {Never} from './ReactFiberExpirationTime';
import {Never} from './ReactFiberExpirationTime.new';
import {resetChildFibers} from './ReactChildFiber.new';
import {updateDeprecatedEventListeners} from './ReactFiberDeprecatedEvents.new';
import {createScopeMethods} from './ReactFiberScope.new';
Expand Down
4 changes: 2 additions & 2 deletions packages/react-reconciler/src/ReactFiberCompleteWork.old.js
Expand Up @@ -8,7 +8,7 @@
*/

import type {Fiber} from './ReactInternalTypes';
import type {ExpirationTime} from './ReactFiberExpirationTime';
import type {ExpirationTime} from './ReactFiberExpirationTime.old';
import type {
ReactFundamentalComponentInstance,
ReactScopeInstance,
Expand Down Expand Up @@ -129,7 +129,7 @@ import {
renderHasNotSuspendedYet,
} from './ReactFiberWorkLoop.old';
import {createFundamentalStateInstance} from './ReactFiberFundamental.old';
import {Never} from './ReactFiberExpirationTime';
import {Never} from './ReactFiberExpirationTime.old';
import {resetChildFibers} from './ReactChildFiber.old';
import {updateDeprecatedEventListeners} from './ReactFiberDeprecatedEvents.old';
import {createScopeMethods} from './ReactFiberScope.old';
Expand Down
Expand Up @@ -19,7 +19,7 @@ import {
DEPRECATED_mountResponderInstance,
DEPRECATED_unmountResponderInstance,
} from './ReactFiberHostConfig';
import {NoWork} from './ReactFiberExpirationTime';
import {NoWork} from './ReactFiberExpirationTime.new';

import {REACT_RESPONDER_TYPE} from 'shared/ReactSymbols';

Expand Down
Expand Up @@ -19,7 +19,7 @@ import {
DEPRECATED_mountResponderInstance,
DEPRECATED_unmountResponderInstance,
} from './ReactFiberHostConfig';
import {NoWork} from './ReactFiberExpirationTime';
import {NoWork} from './ReactFiberExpirationTime.old';

import {REACT_RESPONDER_TYPE} from 'shared/ReactSymbols';

Expand Down
4 changes: 2 additions & 2 deletions packages/react-reconciler/src/ReactFiberDevToolsHook.new.js
Expand Up @@ -9,11 +9,11 @@

import {enableProfilerTimer} from 'shared/ReactFeatureFlags';
import {getCurrentTime} from './ReactFiberWorkLoop.new';
import {inferPriorityFromExpirationTime} from './ReactFiberExpirationTime';
import {inferPriorityFromExpirationTime} from './ReactFiberExpirationTime.new';

import type {Fiber} from './ReactInternalTypes';
import type {FiberRoot} from './ReactInternalTypes';
import type {ExpirationTime} from './ReactFiberExpirationTime';
import type {ExpirationTime} from './ReactFiberExpirationTime.new';
import type {ReactNodeList} from 'shared/ReactTypes';

import {DidCapture} from './ReactSideEffectTags';
Expand Down
4 changes: 2 additions & 2 deletions packages/react-reconciler/src/ReactFiberDevToolsHook.old.js
Expand Up @@ -9,11 +9,11 @@

import {enableProfilerTimer} from 'shared/ReactFeatureFlags';
import {getCurrentTime} from './ReactFiberWorkLoop.old';
import {inferPriorityFromExpirationTime} from './ReactFiberExpirationTime';
import {inferPriorityFromExpirationTime} from './ReactFiberExpirationTime.old';

import type {Fiber} from './ReactInternalTypes';
import type {FiberRoot} from './ReactInternalTypes';
import type {ExpirationTime} from './ReactFiberExpirationTime';
import type {ExpirationTime} from './ReactFiberExpirationTime.old';
import type {ReactNodeList} from 'shared/ReactTypes';

import {DidCapture} from './ReactSideEffectTags';
Expand Down
147 changes: 147 additions & 0 deletions packages/react-reconciler/src/ReactFiberExpirationTime.new.js
@@ -0,0 +1,147 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

import type {ReactPriorityLevel} from './ReactInternalTypes';

import {MAX_SIGNED_31_BIT_INT} from './MaxInts';

import {
ImmediatePriority,
UserBlockingPriority,
NormalPriority,
IdlePriority,
} from './SchedulerWithReactIntegration.new';

export type ExpirationTime = number;

export const NoWork = 0;
// TODO: Think of a better name for Never. The key difference with Idle is that
// Never work can be committed in an inconsistent state without tearing the UI.
// The main example is offscreen content, like a hidden subtree. So one possible
// name is Offscreen. However, it also includes dehydrated Suspense boundaries,
// which are inconsistent in the sense that they haven't finished yet, but
// aren't visibly inconsistent because the server rendered HTML matches what the
// hydrated tree would look like.
export const Never = 1;
// Idle is slightly higher priority than Never. It must completely finish in
// order to be consistent.
export const Idle = 2;
// Continuous Hydration is slightly higher than Idle and is used to increase
// priority of hover targets.
export const ContinuousHydration = 3;
export const Sync = MAX_SIGNED_31_BIT_INT;
export const Batched = Sync - 1;

const UNIT_SIZE = 10;
const MAGIC_NUMBER_OFFSET = Batched - 1;

// 1 unit of expiration time represents 10ms.
export function msToExpirationTime(ms: number): ExpirationTime {
// Always subtract from the offset so that we don't clash with the magic number for NoWork.
return MAGIC_NUMBER_OFFSET - ((ms / UNIT_SIZE) | 0);
}

export function expirationTimeToMs(expirationTime: ExpirationTime): number {
return (MAGIC_NUMBER_OFFSET - expirationTime) * UNIT_SIZE;
}

function ceiling(num: number, precision: number): number {
return (((num / precision) | 0) + 1) * precision;
}

function computeExpirationBucket(
currentTime,
expirationInMs,
bucketSizeMs,
): ExpirationTime {
return (
MAGIC_NUMBER_OFFSET -
ceiling(
MAGIC_NUMBER_OFFSET - currentTime + expirationInMs / UNIT_SIZE,
bucketSizeMs / UNIT_SIZE,
)
);
}

// TODO: This corresponds to Scheduler's NormalPriority, not LowPriority. Update
// the names to reflect.
export const LOW_PRIORITY_EXPIRATION = 5000;
export const LOW_PRIORITY_BATCH_SIZE = 250;

export function computeAsyncExpiration(
currentTime: ExpirationTime,
): ExpirationTime {
return computeExpirationBucket(
currentTime,
LOW_PRIORITY_EXPIRATION,
LOW_PRIORITY_BATCH_SIZE,
);
}

export function computeSuspenseExpiration(
currentTime: ExpirationTime,
timeoutMs: number,
): ExpirationTime {
// TODO: Should we warn if timeoutMs is lower than the normal pri expiration time?
return computeExpirationBucket(
currentTime,
timeoutMs,
LOW_PRIORITY_BATCH_SIZE,
);
}

// We intentionally set a higher expiration time for interactive updates in
// dev than in production.
//
// If the main thread is being blocked so long that you hit the expiration,
// it's a problem that could be solved with better scheduling.
//
// People will be more likely to notice this and fix it with the long
// expiration time in development.
//
// In production we opt for better UX at the risk of masking scheduling
// problems, by expiring fast.
export const HIGH_PRIORITY_EXPIRATION = __DEV__ ? 500 : 150;
export const HIGH_PRIORITY_BATCH_SIZE = 100;

export function computeInteractiveExpiration(currentTime: ExpirationTime) {
return computeExpirationBucket(
currentTime,
HIGH_PRIORITY_EXPIRATION,
HIGH_PRIORITY_BATCH_SIZE,
);
}

export function inferPriorityFromExpirationTime(
currentTime: ExpirationTime,
expirationTime: ExpirationTime,
): ReactPriorityLevel {
if (expirationTime === Sync) {
return ImmediatePriority;
}
if (expirationTime === Never || expirationTime === Idle) {
return IdlePriority;
}
const msUntil =
expirationTimeToMs(expirationTime) - expirationTimeToMs(currentTime);
if (msUntil <= 0) {
return ImmediatePriority;
}
if (msUntil <= HIGH_PRIORITY_EXPIRATION + HIGH_PRIORITY_BATCH_SIZE) {
return UserBlockingPriority;
}
if (msUntil <= LOW_PRIORITY_EXPIRATION + LOW_PRIORITY_BATCH_SIZE) {
return NormalPriority;
}

// TODO: Handle LowPriority

// Assume anything lower has idle priority
return IdlePriority;
}
4 changes: 2 additions & 2 deletions packages/react-reconciler/src/ReactFiberHooks.new.js
Expand Up @@ -17,7 +17,7 @@ import type {
ReactScopeMethods,
} from 'shared/ReactTypes';
import type {Fiber, Dispatcher} from './ReactInternalTypes';
import type {ExpirationTime} from './ReactFiberExpirationTime';
import type {ExpirationTime} from './ReactFiberExpirationTime.new';
import type {HookEffectTag} from './ReactHookEffectTags';
import type {SuspenseConfig} from './ReactFiberSuspenseConfig';
import type {ReactPriorityLevel} from './ReactInternalTypes';
Expand All @@ -33,7 +33,7 @@ import ReactSharedInternals from 'shared/ReactSharedInternals';
import {enableUseEventAPI} from 'shared/ReactFeatureFlags';

import {markRootExpiredAtTime} from './ReactFiberRoot.new';
import {NoWork, Sync} from './ReactFiberExpirationTime';
import {NoWork, Sync} from './ReactFiberExpirationTime.new';
import {NoMode, BlockingMode} from './ReactTypeOfMode';
import {readContext} from './ReactFiberNewContext.new';
import {createDeprecatedResponderListener} from './ReactFiberDeprecatedEvents.new';
Expand Down

0 comments on commit dc630d3

Please sign in to comment.