Skip to content

Commit 8d9ac04

Browse files
Zachary FreemanZachary Freeman
authored andcommitted
updating notes to backend
1 parent 83427c6 commit 8d9ac04

File tree

7 files changed

+138
-43
lines changed

7 files changed

+138
-43
lines changed

demo-app/src/client/Components/Nav.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ function Nav() {
1313
<Link className='link' to='/buttons'>
1414
Counter
1515
</Link>
16-
<Link className='link' to='/test'>
16+
{/* <Link className='link' to='/test'>
1717
Test
18-
</Link>
18+
</Link> */}
1919
</div>
2020
);
2121
}

src/backend/controllers/timeJump.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ async function initiateJump(target, mode): Promise<void> {
6666
updateTreeState(target).then(() => {
6767
document.body.onmouseover = () => {
6868
mode.jumping = false;
69+
console.log('mouseover');
6970
};
7071
});
7172
}

src/backend/models/masterState.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,35 @@
44
/* eslint-disable guard-for-in */
55
/* eslint-disable no-restricted-syntax */
66

7+
/**
8+
* @type ComponentAction - an array of actions that can be performed on a component
9+
*/
710
type ComponentAction = any[];
811

9-
// HookState is an array that contains a "component" for
10-
// every single state change that occurs in the app
12+
// The HookState data structure is an array that holds the current value of a hook's state, as well as a dispatch function that is used to update that state.
1113
// Information on these components include ComponentData as well as state
1214
// For class components, there will be one "component" for each snapshot
1315
// For functional components that utilize Hooks, there will be one "component"
1416
// for each setter/getter every time we have a new snapshot
1517
let componentActionsRecord: ComponentAction = [];
18+
// index keeps track of the current position in the array
1619
let index: number;
1720
index = 0;
1821

1922
export default {
23+
/**
24+
* @function clear - Clears componentActionsRecord
25+
*/
2026
clear: () => {
2127
componentActionsRecord = [];
2228
index = 0;
2329
},
24-
// Adds new component to ComponentActionsRecord
30+
31+
/**
32+
* @function saveNew - Adds a new component to the componentActionsRecord array and returns its index.
33+
* @param component
34+
* @returns number
35+
*/
2536
saveNew: (component): number => {
2637
componentActionsRecord[index] = component;
2738
index++;
@@ -30,23 +41,23 @@ export default {
3041
},
3142
// ----------------------------CLASS COMPONENT--------------------------------
3243
/**
33-
* This function is used for stateful Class Component to retrieve an object that has the bound setState method
44+
* @function getComponentByIndex - This function is used for stateful Class Component to retrieve an object that has the bound setState method
3445
* @param inputIndex - index of component inside `componentActionsRecord` coming from `timeJump.ts`
3546
* @returns - an object containing the bound setState method
3647
*/
3748
getComponentByIndex: (inputIndex: number): any | undefined => componentActionsRecord[inputIndex],
3849

3950
//---------------------------FUNCTIONAL COMPONENT-----------------------------
4051
/**
41-
* This function is used for Functional Component to retrieve an array of objects that have the bound dispatch methods.
52+
* @function getComponentByIndexHooks - This function is used for Functional Component to retrieve an array of objects that have the bound dispatch methods.
4253
* @param inputIndex - index of component inside `componentActionsRecord` coming from `timeJump.ts`
4354
* @returns - an array of objects containing the bound dispatch methods
4455
*/
4556
getComponentByIndexHooks: (inputIndex: Array<number> = []): any[] | undefined =>
4657
inputIndex.map((index) => componentActionsRecord[index]),
4758
// ----------------------------------DEBUGGING--------------------------------
4859
/**
49-
* This method is used for debugging purpose to access the array of setState/dispatch methods
60+
* @function getAllComponents - This method is used for debugging purpose to access the array of setState/dispatch methods
5061
* @returns - an array of objects containing the bound methods for updating state
5162
*/
5263
getAllComponents: (): any[] => componentActionsRecord,

src/backend/models/tree.ts

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77
/* eslint-disable no-param-reassign */
88
import { Route } from './routes';
99

10-
let copyInstances = 0; // Tells you if we have already made a copy of current tree??
11-
const circularComponentTable = new Set<Tree>(); // Keeps track of the nodes added to the tree
12-
let componentNames = {}; // {componentName: frequency of use} => component name as a key and it's frequency of use as its value
10+
// The circularComponentTable is used to handle circular references in the state object. It keeps tracks of the components that have already been serialized. When a component is encountered for the first time, it is added to the table along with a unique identifier. If the same component is encountered again, the identifier is used to reference the previously serialized component in the output instead of serializing it again, thus avoiding the infinite loop.
11+
const circularComponentTable = new Set<Tree>();
12+
// Used to keep track of which objects have already been copied during the serialization process. This is necessary to handle circular references correctly. When an object is serialized, all its properties are copied to the serialized object. If an object property is an object itself, it needs to be serialized recursively. However, if the object being serialized has already been serialized before, it should not be serialized again to prevent an infinite loop.
13+
let copyInstances = 0;
14+
// ComponentNames is used to store a mapping between a component's unique identifier and its name. This mapping is used to reconstruct the component instances during deserialization.
15+
let componentNames = {};
1316

1417
// Functions dont serialize properly so we need to scrub for that
1518
export function scrubUnserializableMembers(tree: Tree): Tree {
@@ -20,6 +23,11 @@ export function scrubUnserializableMembers(tree: Tree): Tree {
2023
}
2124

2225
// Making a deep clone of state becuase we want to make a copy
26+
/**
27+
* @function serializeState - In the context of React, state is often used to store data that determines the behavior and appearance of a component. By serializing the state, we can preserve the component's data across page refreshes, server-side rendering, and other transitions. Additionally, by serializing the state and passing it to a child component, we can create a deep clone of the state, which allows the child component to manipulate the state without affecting the original component. This is useful in situations where we want to keep the state of the parent component immutable, but still allow child components to modify a copy of the state.
28+
* @param state - Object that contains the current state of the application or system that needs to be serialized.
29+
* @returns
30+
*/
2331
export function serializeState(state) {
2432
try {
2533
// makes a deep clone
@@ -33,15 +41,14 @@ export function serializeState(state) {
3341
/**
3442
* This is the current snapshot that is being sent to the snapshots array.
3543
* Creates a Tree
36-
* @param state - {string| {}} - the tree's current state
37-
* @param name - {string} - the tree's name
38-
* @param componentData - {props: {}} - Data in the component tree
39-
* @param chilren - {(Tree | string)[]} - An array of children nodes
40-
* @param parent - {Tree} - the parent node
41-
* @param isExpanded - {boolean}
42-
* @param rtid - {any}
43-
* @param route -
44-
* @parent generates a new tree (recursive call)
44+
* @param state - the current state of the component represented by this node.
45+
* @param name - the name of the component represented by this node.
46+
* @param componentData - an object containing the props of the component represented by this node.
47+
* @param chilren - an array of child nodes.
48+
* @param parent - a reference to the parent node.
49+
* @param isExpanded - a boolean value indicating whether the node is expanded in the UI.
50+
* @param rtid - a unique identifier for the node.
51+
* @param route - an object representing the route associated with the node.
4552
*/
4653
class Tree {
4754
state: string | {};
@@ -87,6 +94,11 @@ class Tree {
8794
}
8895

8996
// Returns a unique name ready to be used for when new components gets added to the tree
97+
/**
98+
* @function checkForDuplicates - Generates a unique name for a component that is being added to the component tree
99+
* @param name
100+
* @returns
101+
*/
90102
checkForDuplicates(name: string): string {
91103
// check for empty name
92104
if (name === '' && typeof this.rtid === 'string') {

src/backend/reactFiberForDummies.ts

Lines changed: 78 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,20 @@ interface ReactElement {
3030
*/
3131

3232
interface FiberNode {
33-
element: ReactElement;
33+
element: ReactElement | null;
3434
parent: FiberNode | null;
3535
child: FiberNode | null;
3636
sibling: FiberNode | null;
3737
alternate: FiberNode | null;
3838
effectTag: string | null;
3939
effects?: FiberNode[];
40+
stateNode: any;
4041
}
4142

4243
/**
43-
*
44-
* @param element
45-
* @param parent
44+
* @function createFiberNode - Responsible for creating a new Fiber Node. A Fiber node is an object that represents a React element in the reconciliation process. It contains information about the element, its parent, and its children as well other data
45+
* @param element - React element that represents the component or DOM node that the fiber will represent. It is an object that contains information about the type of element, its props, its children, etc.
46+
* @param parent - The fiber node that represents the parent component of the element. It is used to link the new fiber node to the fiber tree by setting its parent property to the parent fiber node
4647
* @returns
4748
*/
4849
const createFiberNode = (element: ReactElement, parent: FiberNode | null): FiberNode => {
@@ -53,11 +54,16 @@ const createFiberNode = (element: ReactElement, parent: FiberNode | null): Fiber
5354
sibling: null,
5455
alternate: null,
5556
effectTag: null,
57+
stateNode: null,
5658
};
5759
};
5860

59-
// Fiber Reconciliation
60-
const reconcile = (parentFiber: FiberNode, children: any[]) => {
61+
/**
62+
* @function reconcile - The purpose of the reconcile function is to reconcile the children array with the parentFiber node. In other words, it creates a fiber tree that reflects the current state of the React element tree
63+
* @param parentFiber - The fiber node of the parent element in the tree
64+
* @param children - An array of child elements (React elements) that belong to the parent element
65+
*/
66+
const reconcile = (parentFiber: FiberNode, children: any[]): void => {
6167
// checks to see if the parent fiber has an alternate fiber and if it does, it sets oldFiber to its child
6268
// If there is an alternate fiber for the parent fiber, it means that there was a previous version of the fiber tree that was reconciled, and oldFiber is set to its child fiber so that it can compared to the new children in the current version of the tree
6369
let oldFiber = parentFiber.alternate && parentFiber.alternate.child;
@@ -66,20 +72,81 @@ const reconcile = (parentFiber: FiberNode, children: any[]) => {
6672
let prevFiber: FiberNode | null = null; // used to keep track of the last fiber that was process in the loop
6773

6874
while (index < children.length || !oldFiber) {
69-
const element = children[index];
75+
const reactElement = children[index];
7076
// see if same type
71-
let sameType = oldFiber && element && element.type === oldFiber.element.type;
72-
// if same type is founf, create a newFiber
77+
let sameType = oldFiber && reactElement && reactElement.type === oldFiber.element.type;
78+
// if same type is found, create a newFiber
7379
if (sameType) {
7480
newFiber = {
75-
element,
81+
element: reactElement,
7682
child: null,
7783
sibling: null,
7884
parent: parentFiber,
7985
alternate: oldFiber,
8086
effectTag: 'UPDATE',
87+
stateNode: oldFiber.stateNode,
8188
};
89+
} else {
90+
if (reactElement) {
91+
newFiber = createFiberNode(reactElement, parentFiber);
92+
newFiber.effectTag = 'PLACEMENT';
93+
94+
if (typeof reactElement.type === 'function') {
95+
newFiber.stateNode = new (reactElement.type as any)(reactElement.props);
96+
} else {
97+
newFiber.stateNode = document.createElement(reactElement.type as string);
98+
}
99+
}
100+
101+
if (oldFiber) {
102+
oldFiber.effectTag = 'DELETION';
103+
parentFiber.effects = parentFiber.effects || [];
104+
parentFiber.effects.push(oldFiber);
105+
}
82106
}
107+
108+
oldFiber === null ? null : oldFiber.sibling;
109+
// this block of code if responsible for creating a singly linked list of child nodes for the parent element, where each node has a child property pointing to its first child node and a sibling property pointing to its next sibling
110+
if (index === 0) {
111+
parentFiber.child = newFiber;
112+
} else if (reactElement) {
113+
prevFiber!.sibling = newFiber;
114+
}
115+
116+
prevFiber = newFiber;
117+
index++;
83118
}
84119
};
85-
// Perform updates to DOM
120+
121+
/**
122+
* @function commitRoot - Responsible for committing the changes made to the DOM during the reconcilation phase
123+
* @param rootFiber - Root of the fiber tree. It contains information about the element and changes that need to be made to the DOM
124+
*/
125+
const commitRoot = (rootFiber: FiberNode) => {
126+
if (!rootFiber) return;
127+
rootFiber.effects?.forEach((fiber) => {
128+
if (fiber.effectTag === 'PLACEMENT') {
129+
// place existing element
130+
} else if (fiber.effectTag === 'UPDATE') {
131+
// update existing element
132+
} else if (fiber.effectTag === 'DELETION') {
133+
// remove element from DOM
134+
}
135+
});
136+
};
137+
138+
/**
139+
* @function render - Creates a root fiber which is the top-level fiber that represents the root of the React element ree.
140+
* @param element - The react element that you want to render into the container. It represents the root of your component tree
141+
* @param container - The DOM element that you want to render your React element into. It is typically a <div>
142+
*/
143+
const render = (element: ReactElement, container: HTMLElement) => {
144+
const rootFiber: FiberNode = createFiberNode(element, null);
145+
rootFiber.element = container as any as ReactElement; // cast container to ReactElement
146+
const workInProgressRootFiber: FiberNode = {
147+
...rootFiber,
148+
alternate: rootFiber,
149+
};
150+
reconcile(workInProgressRootFiber, element.props.children);
151+
commitRoot(workInProgressRootFiber);
152+
};

src/backend/routers/linkFiber.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ declare global {
3636
}
3737

3838
/**
39-
* linkFiber contains core module functionality, exported as an anonymous function, perform the following logic:
39+
* @function linkFiber - linkFiber contains core module functionality, exported as an anonymous function, perform the following logic:
4040
* 1. Check if React Dev Tool is installed.
4141
* 2. Check if the target application (on the browser) is a valid react application.
4242
* 3. Initiate a event listener for visibility update of the target React Applicaiton.
43-
* 4. Obtain the initial fiberRootNode, which is the root node of a tree of React component.
44-
* 5. Initialize the tree snapShot on Chrome Extension.
43+
* 4. Obtain the initial fiberRootNode, which is the root node of the fiber tree
44+
* 5. Initialize the fiber tree snapShot on Chrome Extension.
4545
* 6. Monkey patching the onCommitFiberRoot from REACT DEV TOOL to obtain updated data after React Applicaiton is re-rendered.
46-
* @param snapShot The current snapshot
46+
* @param snapShot The current snapshot (i.e fiber tree)
4747
* @param mode The current mode (i.e. jumping, time-traveling, or paused)
4848
* @return a function to be invoked by index.js that initiates snapshot monitoring
4949
*/
@@ -53,8 +53,9 @@ export default function linkFiber(snapShot: Snapshot, mode: Status): () => void
5353
*/
5454
let isVisible: boolean = true;
5555
/**
56-
* The `fiberRootNode`, which is the root node of a tree of React component.
57-
* The `current` property of `fiberRoot` has data structure of a Tree, which can be used to traverse and obtain all child component data.
56+
* Every React application has one or more DOM elements that act as containers. React creates a fiber root object for each of those containers.
57+
* This fiber root is where React holds reference to a fiber tree
58+
* The `fiberRootNode`, which is the root node of the fiber tree is stored in the current property of the fiber root object
5859
*/
5960
let fiberRoot: FiberRoot;
6061
/**
@@ -76,6 +77,8 @@ export default function linkFiber(snapShot: Snapshot, mode: Status): () => void
7677
// react devtools global hook is a global object that was injected by the React Devtools content script, allows access to fiber nodes and react version
7778
// Obtain React Devtools Object:
7879
const devTools = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
80+
const { onCommitFiberRoot } = devTools;
81+
console.log('onCommit..', onCommitFiberRoot);
7982
// If React Devtools is not installed, object will be undefined.
8083
if (!devTools) {
8184
return;

src/backend/routers/snapShot.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import createTree from '../controllers/createTree/createTree';
66

77
// ---------------------------UPDATE TREE SNAP SHOT-----------------------------
88
/**
9-
* - Create a new `snapShot` tree with the provided `fiberRoot`. This runs after every Fiber commit.
9+
* @function updateSnapShotTree - Creates a new `snapShot` fiber tree with the provided `fiberRoot`. This runs after every Fiber commit.
1010
* - Middleware: Updates snapShot object with latest snapshot, using `sendSnapshot`
11-
* @param snapShot The current snapshot
11+
* @param snapShot The current snapshot of the fiber tree
1212
* @param mode The current mode (i.e. jumping, time-traveling, or paused)
13-
* @param fiberRoot The `fiberRootNode`, which is the root node of a tree of React component. The `current` property of `fiberRoot` has data structure of a Tree, which can be used to traverse and obtain all child component data.
13+
* @param fiberRoot The `fiberRootNode`, which is the root node of the fiber tree is stored in the current property of the fiber root object which we can use to traverse the tree
1414
*/
1515
// updating tree depending on current mode on the panel (pause, etc)
1616
export default function updateSnapShotTree(
@@ -20,17 +20,18 @@ export default function updateSnapShotTree(
2020
): void {
2121
// this is the currently active root fiber(the mutable root of the tree)
2222
const { current } = fiberRoot;
23+
// clear all of the legacy actions from old fiber tree becuase we are about to create a new one
2324
componentActionsRecord.clear();
24-
// creates snapshot that is a tree based on properties in fiberRoot object
25+
// calls the createTree function which creates the new Fiber tree and adds it to tree property on the snapShot object
2526
snapShot.tree = createTree(current);
2627
// sends the updated tree back
2728
sendSnapshot(snapShot, mode);
2829
}
2930

3031
// -------------------SEND TREE SNAP SHOT TO FRONT END--------------------------
3132
/**
32-
* Gets a copy of the current snapShot.tree and posts a recordSnap message to the window
33-
* @param snapShot The current snapshot
33+
* @function sendSnapshot - Gets a copy of the current snapShot.tree and posts a recordSnap message to the window
34+
* @param snapShot The current snapshot of the fiber tree that is shown in the extension
3435
* @param mode The current mode (i.e. jumping, time-traveling, or paused)
3536
* @return void
3637
*

0 commit comments

Comments
 (0)