Skip to content

Commit e66fa2f

Browse files
committed
Compelte createTree documentation
1 parent f5caebc commit e66fa2f

File tree

4 files changed

+57
-48
lines changed

4 files changed

+57
-48
lines changed

src/backend/controllers/createTree.ts

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ export default function createTree(currentFiberNode: Fiber): Tree {
6262
} = currentFiberNode;
6363

6464
// Obtain component name:
65-
let componentName =
65+
/** Name of the current component */
66+
let componentName: string =
6667
elementType?._context?.displayName || //For ContextProvider
6768
elementType?._result?.name || //For lazy Component
6869
elementType?.render?.name ||
@@ -111,17 +112,19 @@ export default function createTree(currentFiberNode: Fiber): Tree {
111112
};
112113

113114
// ---------------APPEND PROP DATA FROM REACT DEV TOOL----------------------
114-
// Check to see if the parent component has any props
115+
// Check to see if the currentFiberNode has any props
115116
if (memoizedProps) {
116117
switch (elementType.name) {
118+
// If component comes from React Router, extract only pathname:
117119
case 'Router':
118120
componentData.props = { pathname: memoizedProps?.location?.pathname };
119121
break;
120122
case 'RenderedRoute':
121123
componentData.props = { pathname: memoizedProps?.match?.pathname };
122124
break;
125+
// Else filter & format props data to ensure they are JSON stringify-able, before sending to front end
123126
default:
124-
Object.assign(componentData.props, filterAndFormatData(memoizedProps));
127+
componentData.props = filterAndFormatData(memoizedProps);
125128
}
126129
}
127130

@@ -160,28 +163,23 @@ export default function createTree(currentFiberNode: Fiber): Tree {
160163
// componentName = 'Context';
161164
// }
162165

163-
// // DEPRECATED: This code might have worked previously. However, with the update of React Dev Tool, context can no longer be pulled using this method.
164-
// // Check to see if the component has any context:
165-
// // if the component uses the useContext hook, we want to grab the context object and add it to the componentData object for that fiber
166-
// // if (tag === FunctionComponent && _debugHookTypes && dependencies?.firstContext?.memoizedValue) {
167-
// // componentData.context = convertDataToString(dependencies.firstContext.memoizedValue);
168-
// // }
169-
170166
// ---------OBTAIN STATE & SET STATE METHODS FROM CLASS COMPONENT-----------
171-
// Check if node is a stateful class component when user use setState.
167+
// Check if currentFiberNode is a stateful class component when user use setState.
172168
// If user use setState to define/manage state, the state object will be stored in stateNode.state => grab the state object stored in the stateNode.state
173169
// Example: for tic-tac-toe demo-app: Board is a stateful component that use setState to store state data.
174170
if ((tag === ClassComponent || tag === IndeterminateComponent) && stateNode?.state) {
175171
// Save component's state and setState() function to our record for future time-travel state changing. Add record index to snapshot so we can retrieve.
176172
componentData.index = componentActionsRecord.saveNew(stateNode);
177173
// Save state information in componentData.
178174
componentData.state = stateNode.state;
179-
// Passess to front end
175+
// Pass to front end
180176
newState = componentData.state;
181177
}
182178

183179
// --------OBTAIN STATE & DISPATCH METHODS FROM FUNCTIONAL COMPONENT--------
184-
// Check if node is a hooks useState function
180+
// Check if currentFiberNode is a stateful functional component when user use useState hook.
181+
// If user use useState to define/manage state, the state object will be stored in memoizedState => grab the state object & its update method (dispatch) from memoizedState
182+
// Example: for Stateful buttons demo-app: Increment is a stateful component that use useState hook to store state data.
185183
if (
186184
(tag === FunctionComponent ||
187185
tag === IndeterminateComponent ||
@@ -191,20 +189,21 @@ export default function createTree(currentFiberNode: Fiber): Tree {
191189
) {
192190
if (memoizedState.queue) {
193191
try {
192+
// Obtain all hooksStates & the corresponding udpate method from memoizedState
194193
const hooksStates = getHooksStateAndUpdateMethod(memoizedState);
194+
// Obtain variable names by parsing the function definition stored in elementType.
195195
const hooksNames = getHooksNames(elementType.toString());
196196
// Intialize state & index:
197-
// newState.hooksState = [];
198197
componentData.hooksState = {};
199198
componentData.hooksIndex = [];
199+
200200
hooksStates.forEach(({ state, component }, i) => {
201201
// Save component's state and dispatch() function to our record for future time-travel state changing. Add record index to snapshot so we can retrieve.
202202
componentData.hooksIndex.push(componentActionsRecord.saveNew(component));
203-
// Passess to front end
203+
// Save state information in componentData.
204204
componentData.hooksState[hooksNames[i].varName] = state;
205205
});
206-
// Passess to front end
207-
// TODO: Refactor this, this is currently being used for Tree & Diff tabs
206+
// Pass to front end
208207
newState = componentData.hooksState;
209208
} catch (err) {
210209
// COMMENT OUT TO AVOID PRINTTING ON THE CONSOLE OF USER - KEEP IT FOR DEBUGGING PURPOSE
@@ -223,11 +222,6 @@ export default function createTree(currentFiberNode: Fiber): Tree {
223222
* `rtid` - The `Root ID` is a unique identifier that is assigned to each React root instance in a React application.
224223
*/
225224
let rtid: string | null = null;
226-
/**
227-
* The updated tree after adding the `componentData` obtained from `currentFiberNode`
228-
*/
229-
let childNode: Tree = tree;
230-
// We want to add this fiber node to the snapshot
231225

232226
// Grab JSX Component & replace the 'fromLinkFiber' class value
233227
if (currentFiberNode.child?.stateNode?.setAttribute) {
@@ -246,10 +240,12 @@ export default function createTree(currentFiberNode: Fiber): Tree {
246240
}
247241
currentFiberNode.child.stateNode.classList.add(rtid);
248242
}
249-
rtidCounter += 1; // I THINK THIS SHOULD BE UP IN THE IF STATEMENT. Still unsure the use of rtid
243+
rtidCounter += 1;
250244

251-
// Append the childNode to the tree
252-
childNode = tree.addChild(newState, componentName, componentData, rtid);
245+
/**
246+
* The updated tree after adding the `componentData` obtained from `currentFiberNode`
247+
*/
248+
const childNode = tree.addChild(newState, componentName, componentData, rtid);
253249

254250
// ---------------------TRAVERSE TO NEXT FIBERNODE--------------------------
255251
// If currentFiberNode has children, recurse on children

src/backend/controllers/statePropExtractors.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const acorn = require('acorn');
22
const jsx = require('acorn-jsx');
33
const JSXParser = acorn.Parser.extend(jsx());
4-
import { HookStates, Fiber } from '../types/backendTypes';
4+
import { HookStates, HookStateItem, Fiber } from '../types/backendTypes';
55
import { exclude } from '../models/filterConditions';
66

77
type ReactimeData = {
@@ -10,6 +10,7 @@ type ReactimeData = {
1010
// ------------FILTER DATA FROM REACT DEV TOOL && CONVERT TO STRING-------------
1111
/**
1212
* This function receives raw Data from REACT DEV TOOL and filter the Data based on the exclude list. The filterd data is then converted to string (if applicable) before being sent to reacTime front end.
13+
* NOTE: the formating is important since Chrome will only accept JSON.stringfiable object. Circular object & function are not JSON stringifiable.
1314
*
1415
* @param reactDevData - The data object obtained from React Devtool. Ex: memoizedProps, memoizedState
1516
* @param reactimeData - The cached data from the current component. This can be data about states, context and/or props of the component.
@@ -64,8 +65,10 @@ export function filterAndFormatData(
6465
* @return An array of array of HookStateItem objects
6566
*
6667
*/
67-
export function getHooksStateAndUpdateMethod(memoizedState: Fiber['memoizedState']): HookStates {
68-
const hooksStates: HookStates = [];
68+
export function getHooksStateAndUpdateMethod(
69+
memoizedState: Fiber['memoizedState'],
70+
): Array<HookStateItem> {
71+
const hooksStates: Array<HookStateItem> = [];
6972
while (memoizedState) {
7073
if (memoizedState.queue) {
7174
hooksStates.push({

src/backend/models/masterState.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
// For class components, there will be one "component" for each snapshot
44
// For functional components that utilize Hooks, there will be one "component"
55

6-
import { index } from 'd3';
7-
86
// for each setter/getter every time we have a new snapshot
97
let componentActionsRecord = [];
108

@@ -18,12 +16,11 @@ export default {
1816

1917
/**
2018
* @function saveNew - Adds a new component to the componentActionsRecord array and returns its index.
21-
* @param component
22-
* @returns number
19+
* @param component - An object that contains bound update method. For class component, the udpate method is `setState`. For functional component, the update method is `dispatch`.
20+
* @returns - the index of the newly added component
2321
*/
2422
saveNew: (component): number => {
25-
componentActionsRecord.push(component);
26-
return componentActionsRecord.length - 1;
23+
return componentActionsRecord.push(component) - 1;
2724
},
2825
// ----------------------------CLASS COMPONENT--------------------------------
2926
/**

src/backend/types/backendTypes.ts

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,25 +42,38 @@ export interface MsgData {
4242

4343
/**
4444
* @type ComponentData -
45-
* @member index -
46-
* @member hooksIndex -
47-
* @member actualDuration -
48-
* @member actualStartTime -
49-
* @member selfBaseDuration -
50-
* @member treeBaseDuration -
51-
* @member props -
45+
* @member actualDuration - The time taken to render the current Fiber node and its descendants during the previous render cycle. This value is used to optimize the rendering of components and to provide performance metrics to developers.
46+
* @member actualStartTime - The time at which the rendering of the current Fiber node started during the previous render cycle.
47+
* @member context - {in experiment} - An object contains all context information of the current component
48+
* @member index - {class component only} - The index of the bound setState method stored in `componentActionsRecord`
49+
* @member hooksState - {functional component only} - An object contains all states of the current functional component
50+
* @member hooksIndex - {functional component only} - An array of index of the bound dispatch method stored in `componentActionsRecord`
51+
* @member props - An object contains all props of the current component
52+
* @member selfBaseDuration - The base duration of the current Fiber node's render phase (excluding the time taken to render its children). This field is only set when the enableProfilerTimer flag is enabled.
53+
* @member state - {class component only} - An object contains all states of the current class component
54+
* @member treeBaseDuration - The total base duration of the current Fiber node's subtree. This field is only set when the enableProfilerTimer flag is enabled.
5255
*/
5356
export interface ComponentData {
57+
/** The time taken to render the current Fiber node and its descendants during the previous render cycle. */
5458
actualDuration?: number;
59+
/** The time at which the rendering of the current Fiber node started during the previous render cycle. */
5560
actualStartTime?: number;
56-
selfBaseDuration?: number;
57-
treeBaseDuration?: number;
58-
props: { [key: string]: any };
61+
/** {in experiment} - An object contains all context information of the current component */
5962
context: {};
60-
state: { [key: string]: any } | null;
63+
/** {class component only} - The index of the bound setState method stored in `componentActionsRecord` */
64+
index: number | null;
65+
/** {functional component only} - An object contains all states of the current functional component */
6166
hooksState: {} | null;
67+
/** {functional component only} - An array of index of the bound dispatch method stored in `componentActionsRecord` */
6268
hooksIndex: number[] | null;
63-
index: number | null;
69+
/** An object contains all props of the current component */
70+
props: { [key: string]: any };
71+
/** The base duration of the current Fiber node's render phase (excluding the time taken to render its children). */
72+
selfBaseDuration?: number;
73+
/** An object contains all states of the current class component */
74+
state: { [key: string]: any } | null;
75+
/** The total base duration of the current Fiber node's subtree. */
76+
treeBaseDuration?: number;
6477
}
6578

6679
/**
@@ -108,9 +121,9 @@ export type WorkTag =
108121
export const FunctionComponent = 0;
109122
export const ClassComponent = 1;
110123
/** Before we know whether it is function or class */
111-
export const IndeterminateComponent = 2;
124+
export const IndeterminateComponent = 2;
112125
/** Root of a host tree. Could be nested inside another node. */
113-
export const HostRoot = 3;
126+
export const HostRoot = 3;
114127
/** A subtree. Could be an entry point to a different renderer. */
115128
export const HostPortal = 4;
116129
/**

0 commit comments

Comments
 (0)