@samitouri / QOS-React / commits / f5f7cb5bdf

Fixed some missing operations that could happen after reload-and-profile

Brian Vaughn committed Apr 1, 2019 at 14:29 UTC f5f7cb5bdf7822a65b772ccdb901aa678f645c45
6 files changed +65 -33
src/backend/index.js
+4 -1
@@ -23,7 +23,10 @@ export function initBackend(
23 rendererInterface: RendererInterface,
24 }) => {
25 agent.setRendererInterface(id, rendererInterface);
26 - rendererInterface.walkTree();
26 +
27 + // Now that the Store and the renderer interface are connected,
28 + // it's time to flush the pending operation codes to the frontend.
29 + rendererInterface.flushInitialOperations();
30 }
31 ),
32
src/backend/renderer.js
+50 -25
@@ -567,6 +567,7 @@ export function attach(
567 }
568
569 let pendingOperations: Uint32Array = new Uint32Array(0);
570 + let pendingOperationsQueue: Array<Uint32Array> | null = [];
571
572 function addOperation(
573 newAction: Uint32Array,
@@ -604,7 +605,16 @@ export function attach(
605 // Let the frontend know about tree operations.
606 // The first value in this array will identify which root it corresponds to,
607 // so we do no longer need to dispatch a separate root-committed event.
607 - hook.emit('operations', pendingOperations);
608 + if (pendingOperationsQueue !== null) {
609 + // Until the frontend has been connected, store the tree operations.
610 + // This will let us avoid walking the tree later when the frontend connects,
611 + // and it enables the Profiler's reload-and-profile functionality to work as well.
612 + pendingOperationsQueue.push(pendingOperations);
613 + } else {
614 + // If we've already connected to the frontend, just pass the operations through.
615 + hook.emit('operations', pendingOperations);
616 + }
617 +
618 pendingOperations = new Uint32Array(0);
619 }
620
@@ -914,31 +924,46 @@ export function attach(
924 // We don't patch any methods so there is no cleanup.
925 }
926
917 - function walkTree() {
918 - // Hydrate all the roots for the first time.
919 - hook.getFiberRoots(rendererID).forEach(root => {
920 - currentRootID = getFiberID(getPrimaryFiber(root.current));
927 + function flushInitialOperations() {
928 + const localPendingOperationsQueue = pendingOperationsQueue;
929
922 - if (isProfiling) {
923 - // If profiling is active, store commit time and duration, and the current interactions.
924 - // The frontend may request this information after profiling has stopped.
925 - currentCommitProfilingMetadata = {
926 - actualDurations: [],
927 - commitTime: performance.now() - profilingStartTime,
928 - interactions: Array.from(root.memoizedInteractions).map(
929 - (interaction: Interaction) => ({
930 - ...interaction,
931 - timestamp: interaction.timestamp - profilingStartTime,
932 - })
933 - ),
934 - maxActualDuration: 0,
935 - };
936 - }
930 + pendingOperationsQueue = null;
931
938 - mountFiber(root.current, null);
939 - flushPendingEvents(root);
940 - currentRootID = -1;
941 - });
932 + if (
933 + localPendingOperationsQueue !== null &&
934 + localPendingOperationsQueue.length > 0
935 + ) {
936 + // We may have already queued up some operations before the frontend connected
937 + // If so, let the frontend know about them.
938 + localPendingOperationsQueue.forEach(pendingOperations => {
939 + hook.emit('operations', pendingOperations);
940 + });
941 + } else {
942 + // If we have not been profiling, then we can just walk the tree and build up its current state as-is.
943 + hook.getFiberRoots(rendererID).forEach(root => {
944 + currentRootID = getFiberID(getPrimaryFiber(root.current));
945 +
946 + if (isProfiling) {
947 + // If profiling is active, store commit time and duration, and the current interactions.
948 + // The frontend may request this information after profiling has stopped.
949 + currentCommitProfilingMetadata = {
950 + actualDurations: [],
951 + commitTime: performance.now() - profilingStartTime,
952 + interactions: Array.from(root.memoizedInteractions).map(
953 + (interaction: Interaction) => ({
954 + ...interaction,
955 + timestamp: interaction.timestamp - profilingStartTime,
956 + })
957 + ),
958 + maxActualDuration: 0,
959 + };
960 + }
961 +
962 + mountFiber(root.current, null);
963 + flushPendingEvents(root);
964 + currentRootID = -1;
965 + });
966 + }
967 }
968
969 function handleCommitFiberUnmount(fiber) {
@@ -1623,6 +1648,7 @@ export function attach(
1648
1649 return {
1650 cleanup,
1651 + flushInitialOperations,
1652 getCommitDetails,
1653 getFiberIDFromNative,
1654 getInteractions,
@@ -1641,6 +1667,5 @@ export function attach(
1667 setInState,
1668 startProfiling,
1669 stopProfiling,
1644 - walkTree,
1670 };
1671 }
src/backend/types.js
+1 -1
@@ -82,6 +82,7 @@ export type ProfilingSummary = {|
82
83 export type RendererInterface = {
84 cleanup: () => void,
85 + flushInitialOperations: () => void,
86 getCommitDetails: (rootID: number, commitIndex: number) => CommitDetails,
87 getNativeFromReactElement?: ?(component: Fiber) => ?NativeType,
88 getFiberIDFromNative: (
@@ -108,7 +109,6 @@ export type RendererInterface = {
109 setInState: (id: number, path: Array<string | number>, value: any) => void,
110 startProfiling: () => void,
111 stopProfiling: () => void,
111 - walkTree: () => void,
112 };
113
114 export type Handler = (data: any) => void;
src/devtools/views/Profiler/CommitTreeBuilder.js
+1 -6
@@ -112,14 +112,9 @@ export function getCommitTree({
112 }
113 }
114
115 - console.error(
115 + throw Error(
116 `getCommitTree(): Unable to reconstruct tree for root "${rootID}" and commit ${commitIndex}`
117 );
118 -
119 - return {
120 - nodes: new Map(),
121 - rootID,
122 - };
118 }
119
120 function recursivelyIniitliazeTree(
src/devtools/views/Profiler/FlamegraphChartBuilder.js
+5
@@ -56,6 +56,11 @@ export function getChartData({
56 idToDepthMap.set(id, currentDepth);
57
58 const node = ((nodes.get(id): any): Node);
59 +
60 + if (node == null) {
61 + throw Error(`Could not find node with id "${id}" in commit tree`);
62 + }
63 +
64 const name = node.displayName || 'Unknown';
65
66 const selfDuration = calculateSelfDuration(id, commitTree, commitDetails);
src/devtools/views/Profiler/RankedChartBuilder.js
+4
@@ -41,6 +41,10 @@ export function getChartData({
41 actualDurations.forEach((actualDuration, id) => {
42 const node = ((nodes.get(id): any): Node);
43
44 + if (node == null) {
45 + throw Error(`Could not find node with id "${id}" in commit tree`);
46 + }
47 +
48 // Don't show the root node in this chart.
49 if (node.parentID === 0) {
50 return;