Merge branch '165-add-flow-types-for-fiber' of https://github.com/sompylasar/react-devtools-experimental into sompylasar-165-add-flow-types-for-fiber

This commit is contained in:
Brian Vaughn
2019-05-03 07:48:21 -07:00
3 changed files with 145 additions and 39 deletions
+1
View File
@@ -27,6 +27,7 @@ shells/dev/build/*
[options]
server.max_workers=4
esproposal.class_instance_fields=enable
esproposal.optional_chaining=enable
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue
suppress_comment=\\(.\\|\n\\)*\\$FlowIgnore
+82 -37
View File
@@ -249,7 +249,7 @@ export function attach(
if (__DEBUG__) {
const displayName = getDisplayNameForFiber(fiber) || 'null';
const parentDisplayName =
(parentFiber !== null && getDisplayNameForFiber(parentFiber)) || 'null';
(parentFiber != null && getDisplayNameForFiber(parentFiber)) || 'null';
// NOTE: calling getFiberID or getPrimaryFiber is unsafe here
// because it will put them in the map. For now, we'll omit them.
// TODO: better debugging story for this.
@@ -634,7 +634,6 @@ export function attach(
}
}
// eslint-disable-next-line no-unused-vars
function haveProfilerTimesChanged(
prevFiber: Fiber,
nextFiber: Fiber
@@ -776,7 +775,7 @@ export function attach(
const isProfilingSupported = fiber.hasOwnProperty('treeBaseDuration');
if (isProfilingSupported) {
idToRootMap.set(id, currentRootID);
idToTreeBaseDurationMap.set(id, fiber.treeBaseDuration);
idToTreeBaseDurationMap.set(id, fiber.treeBaseDuration || 0);
}
const hasOwnerMetadata = fiber.hasOwnProperty('_debugOwner');
@@ -795,7 +794,9 @@ export function attach(
const ownerID =
_debugOwner != null ? getFiberID(getPrimaryFiber(_debugOwner)) : 0;
const parentID = getFiberID(getPrimaryFiber(parentFiber));
const parentID = parentFiber
? getFiberID(getPrimaryFiber(parentFiber))
: 0;
let displayNameStringID = getStringID(displayName);
let keyStringID = getStringID(key);
@@ -811,14 +812,14 @@ export function attach(
if (isProfiling) {
// Tree base duration updates are included in the operations typed array.
// So we have to convert them from milliseconds to microseconds so we can send them as ints.
const treeBaseDuration = Math.floor(fiber.treeBaseDuration * 1000);
const treeBaseDuration = Math.floor((fiber.treeBaseDuration || 0) * 1000);
pushOperation(TREE_OPERATION_UPDATE_TREE_BASE_DURATION);
pushOperation(id);
pushOperation(treeBaseDuration);
const { actualDuration } = fiber;
if (actualDuration > 0) {
if (actualDuration != null && actualDuration > 0) {
// If profiling is active, store durations for elements that were rendered during the commit.
const metadata = ((currentCommitProfilingMetadata: any): CommitProfilingData);
metadata.actualDurations.push(id, actualDuration);
@@ -912,8 +913,12 @@ export function attach(
// get the fallback child from the inner fragment and mount
// it as if it was our own child. Updates handle this too.
const primaryChildFragment = fiber.child;
const fallbackChildFragment = primaryChildFragment.sibling;
const fallbackChild = fallbackChildFragment.child;
const fallbackChildFragment = primaryChildFragment
? primaryChildFragment.sibling
: null;
const fallbackChild = fallbackChildFragment
? fallbackChildFragment.child
: null;
if (fallbackChild !== null) {
mountFiberRecursively(
fallbackChild,
@@ -956,9 +961,11 @@ export function attach(
if (isTimedOutSuspense) {
// If it's showing fallback tree, let's traverse it instead.
const primaryChildFragment = fiber.child;
const fallbackChildFragment = primaryChildFragment.sibling;
const fallbackChildFragment = primaryChildFragment
? primaryChildFragment.sibling
: null;
// Skip over to the real Fiber child.
child = fallbackChildFragment.child;
child = fallbackChildFragment ? fallbackChildFragment.child : null;
}
while (child !== null) {
@@ -976,20 +983,27 @@ export function attach(
const id = getFiberID(getPrimaryFiber(fiber));
const { actualDuration, treeBaseDuration } = fiber;
idToTreeBaseDurationMap.set(id, fiber.treeBaseDuration);
idToTreeBaseDurationMap.set(id, fiber.treeBaseDuration || 0);
if (isProfiling) {
if (treeBaseDuration !== fiber.alternate.treeBaseDuration) {
const { alternate } = fiber;
if (
treeBaseDuration !==
(alternate ? alternate.treeBaseDuration : undefined)
) {
// Tree base duration updates are included in the operations typed array.
// So we have to convert them from milliseconds to microseconds so we can send them as ints.
const treeBaseDuration = Math.floor(fiber.treeBaseDuration * 1000);
const treeBaseDuration = Math.floor(
(fiber.treeBaseDuration || 0) * 1000
);
pushOperation(TREE_OPERATION_UPDATE_TREE_BASE_DURATION);
pushOperation(getFiberID(getPrimaryFiber(fiber)));
pushOperation(treeBaseDuration);
}
if (haveProfilerTimesChanged(fiber.alternate, fiber)) {
if (actualDuration > 0) {
if (alternate ? haveProfilerTimesChanged(alternate, fiber) : true) {
if (actualDuration != null && actualDuration > 0) {
// If profiling is active, store durations for elements that were rendered during the commit.
const metadata = ((currentCommitProfilingMetadata: any): CommitProfilingData);
metadata.actualDurations.push(id, actualDuration);
@@ -1071,11 +1085,19 @@ export function attach(
if (prevDidTimeout && nextDidTimeOut) {
// Fallback -> Fallback:
// 1. Reconcile fallback set.
const nextFallbackChildSet = nextFiber.child.sibling;
const nextFiberChild = nextFiber.child;
const nextFallbackChildSet = nextFiberChild
? nextFiberChild.sibling
: null;
// Note: We can't use nextFiber.child.sibling.alternate
// because the set is special and alternate may not exist.
const prevFallbackChildSet = prevFiber.child.sibling;
const prevFiberChild = prevFiber.child;
const prevFallbackChildSet = prevFiberChild
? prevFiberChild.sibling
: null;
if (
nextFallbackChildSet != null &&
prevFallbackChildSet != null &&
updateFiberRecursively(
nextFallbackChildSet,
prevFallbackChildSet,
@@ -1101,9 +1123,14 @@ export function attach(
// We need to manually walk the previous tree and record unmounts.
unmountFiberChildrenRecursively(prevFiber);
// 2. Mount fallback set
const nextFallbackChildSet = nextFiber.child.sibling;
mountFiberRecursively(nextFallbackChildSet, nextFiber, true);
shouldResetChildren = true;
const nextFiberChild = nextFiber.child;
const nextFallbackChildSet = nextFiberChild
? nextFiberChild.sibling
: null;
if (nextFallbackChildSet != null) {
mountFiberRecursively(nextFallbackChildSet, nextFiber, true);
shouldResetChildren = true;
}
} else {
// Common case: Primary -> Primary.
// This is the same codepath as for non-Suspense fibers.
@@ -1172,9 +1199,12 @@ export function attach(
let nextChildSet = nextFiber.child;
if (nextDidTimeOut) {
// Special case: timed-out Suspense renders the fallback set.
nextChildSet = nextFiber.child.sibling;
const nextFiberChild = nextFiber.child;
nextChildSet = nextFiberChild ? nextFiberChild.sibling : null;
}
if (nextChildSet != null) {
recordResetChildren(nextFiber, nextChildSet);
}
recordResetChildren(nextFiber, nextChildSet);
// We've handled the child order change for this Fiber.
// Since it's included, there's no need to invalidate parent child order.
return false;
@@ -1357,7 +1387,7 @@ export function attach(
function findNativeByFiberID(id: number) {
try {
let fiber = findCurrentFiberUsingSlowPath(idToFiberMap.get(id));
let fiber = findCurrentFiberUsingSlowPathById(id);
if (fiber === null) {
return null;
}
@@ -1367,9 +1397,10 @@ export function attach(
if (isTimedOutSuspense) {
// A timed-out Suspense's findDOMNode is useless.
// Try our best to find the fallback directly.
const maybeFallbackFiber =
(fiber.child && fiber.child.sibling) || fiber;
fiber = maybeFallbackFiber;
const maybeFallbackFiber = fiber.child && fiber.child.sibling;
if (maybeFallbackFiber != null) {
fiber = maybeFallbackFiber;
}
}
const hostFibers = findAllCurrentHostFibers(fiber);
return hostFibers.map(hostFiber => hostFiber.stateNode).filter(Boolean);
@@ -1647,6 +1678,11 @@ export function attach(
// Find the currently mounted version of this fiber (so we don't show the wrong props and state).
fiber = findCurrentFiberUsingSlowPath(fiber);
if (fiber == null) {
console.warn(`Could not find Fiber with id "${id}"`);
return null;
}
const {
_debugOwner,
_debugSource,
@@ -1655,7 +1691,7 @@ export function attach(
memoizedState,
tag,
type,
} = ((fiber: any): Fiber);
} = fiber;
const usesHooks =
(tag === FunctionComponent ||
@@ -1729,7 +1765,7 @@ export function attach(
displayName: getDisplayNameForFiber(owner) || 'Unknown',
id: getFiberID(getPrimaryFiber(owner)),
});
owner = owner._debugOwner;
owner = owner._debugOwner || null;
}
}
@@ -1826,13 +1862,21 @@ export function attach(
}
}
function findCurrentFiberUsingSlowPathById(id: number): Fiber | null {
const fiber = idToFiberMap.get(id);
if (fiber) {
return findCurrentFiberUsingSlowPath(fiber);
}
return null;
}
function setInHook(
id: number,
index: number,
path: Array<string | number>,
value: any
) {
const fiber = findCurrentFiberUsingSlowPath(idToFiberMap.get(id));
const fiber = findCurrentFiberUsingSlowPathById(id);
if (fiber !== null) {
if (typeof overrideHookState === 'function') {
overrideHookState(fiber, index, path, value);
@@ -1841,7 +1885,7 @@ export function attach(
}
function setInProps(id: number, path: Array<string | number>, value: any) {
const fiber = findCurrentFiberUsingSlowPath(idToFiberMap.get(id));
const fiber = findCurrentFiberUsingSlowPathById(id);
if (fiber !== null) {
const instance = fiber.stateNode;
if (instance === null) {
@@ -1856,7 +1900,7 @@ export function attach(
}
function setInState(id: number, path: Array<string | number>, value: any) {
const fiber = findCurrentFiberUsingSlowPath(idToFiberMap.get(id));
const fiber = findCurrentFiberUsingSlowPathById(id);
if (fiber !== null) {
const instance = fiber.stateNode;
setInObject(instance.state, path, value);
@@ -1870,7 +1914,7 @@ export function attach(
// We need to remove the first part of the path (the "value") before continuing.
path = path.slice(1);
const fiber = findCurrentFiberUsingSlowPath(idToFiberMap.get(id));
const fiber = findCurrentFiberUsingSlowPathById(id);
if (fiber !== null) {
const instance = fiber.stateNode;
if (path.length === 0) {
@@ -2043,17 +2087,18 @@ export function attach(
}
const initialTreeBaseDurations = [];
((initialTreeBaseDurationsMap: any): Map<number, number>).forEach(
(treeBaseDuration, id) => {
if (initialTreeBaseDurationsMap != null) {
initialTreeBaseDurationsMap.forEach((treeBaseDuration, id) => {
if (
((initialIDToRootMap: any): Map<number, number>).get(id) === rootID
initialIDToRootMap != null &&
initialIDToRootMap.get(id) === rootID
) {
// We don't need to convert milliseconds to microseconds in this case,
// because the profiling summary is JSON serialized.
initialTreeBaseDurations.push(id, treeBaseDuration);
}
}
);
});
}
return {
commitDurations,
+62 -2
View File
@@ -7,8 +7,68 @@ type BundleType =
| 0 // PROD
| 1; // DEV
// TODO: Better type for Fiber
export type Fiber = Object;
export type WorkTag = number;
export type SideEffectTag = number;
export type ExpirationTime = number;
export type RefObject = {|
current: any,
|};
export type Source = {
fileName: string,
lineNumber: number,
};
export type HookType =
| 'useState'
| 'useReducer'
| 'useContext'
| 'useRef'
| 'useEffect'
| 'useLayoutEffect'
| 'useCallback'
| 'useMemo'
| 'useImperativeHandle'
| 'useDebugValue';
// The Fiber type is copied from React and should be kept in sync:
// https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiber.js
// The properties we don't use in DevTools are omitted.
export type Fiber = {|
tag: WorkTag,
key: null | string,
elementType: any,
type: any,
stateNode: any,
return: Fiber | null,
child: Fiber | null,
sibling: Fiber | null,
index: number,
ref: null | (((handle: mixed) => void) & { _stringRef: ?string }) | RefObject,
pendingProps: any, // This type will be more specific once we overload the tag.
memoizedProps: any, // The props used to create the output.
memoizedState: any,
effectTag: SideEffectTag,
alternate: Fiber | null,
actualDuration?: number,
actualStartTime?: number,
treeBaseDuration?: number,
_debugSource?: Source | null,
_debugOwner?: Fiber | null,
|};
// TODO: If it's useful for the frontend to know which types of data an Element has
// (e.g. props, state, context, hooks) then we could add a bitmask field for this