1+ /**
2+ * This file contains core module functionality.
3+ *
4+ * It exports an anonymous
5+ * @function
6+ * that is invoked on
7+ * @param snap --> Current snapshot
8+ * @param mode --> Current mode (jumping i.e. time-traveling, locked, or paused)
9+ * and @returns a function to be invoked on the rootContainer HTMLElement
10+ *
11+ * @function updateSnapShotTree
12+ * --> Middleware #1: Updates snap object with latest snapshot
13+ *
14+ * @function sendSnapshot
15+ * --> Middleware #2: Gets a copy of the current snapshot state tree and posts it to the window
16+ *
17+ * @function changeSetState
18+ * @param component : stateNode property on a stateful class component's FiberNode object
19+ * --> Binds class component setState method to the component
20+ * --> Injects middleware into class component's setState method
21+ *
22+ * @function changeUseState
23+ * @param component : memoizedState property on a stateful functional component's FiberNode object
24+ * --> Binds functional component dispatch method to the component
25+ * --> Injects middleware into component's dispatch method
26+ * Note: dispatch is hook equivalent to setState()
27+ *
28+ * @function traverseHooks
29+ * @param memoizedState : memoizedState property on a stateful functional component's FiberNode object
30+ * --> Helper function to traverse through memoizedState
31+ * --> Invokes @changeUseState on each stateful functional component
32+ *
33+ * @function createTree
34+ * @param currentFiber : a FiberNode object
35+ * --> Recursive function to traverse from FiberRootNode and create
36+ * an instance of custom Tree class and build up state snapshot
37+ */
38+
139/* eslint-disable no-underscore-dangle */
240/* eslint-disable func-names */
341/* eslint-disable no-use-before-define */
442/* eslint-disable no-param-reassign */
5- // links component state tree to library
6- // changes the setState method to also update our snapshot
43+
744const Tree = require ( './tree' ) ;
845const astParser = require ( './astParser' ) ;
946const { saveState } = require ( './masterState' ) ;
@@ -27,67 +64,69 @@ module.exports = (snap, mode) => {
2764 }
2865
2966 function changeSetState ( component ) {
30- // check that setState hasn't been changed yet
3167 if ( component . setState . linkFiberChanged ) return ;
32- // make a copy of setState
68+
69+ // Persist the old setState and bind to component so we can continue to setState({})
3370 const oldSetState = component . setState . bind ( component ) ;
34- // replace component's setState so developer doesn't change syntax
35- // component.setState = newSetState.bind(component);
71+
3672 component . setState = ( state , callback = ( ) => { } ) => {
37- // don't do anything if state is locked
38- // UNLESS we are currently jumping through time
73+ // Don't do anything if state is locked UNLESS we are currently jumping through time
3974 if ( mode . locked && ! mode . jumping ) return ;
40- // continue normal setState functionality, except add sending message middleware
75+ // Continue normal setState functionality, with middleware in callback
4176 oldSetState ( state , ( ) => {
4277 updateSnapShotTree ( ) ;
4378 sendSnapshot ( ) ;
4479 callback . bind ( component ) ( ) ;
4580 } ) ;
4681 } ;
82+ // Set a custom property to ensure we don't change this method again
4783 component . setState . linkFiberChanged = true ;
4884 }
4985
5086 function changeUseState ( component ) {
5187 if ( component . queue . dispatch . linkFiberChanged ) return ;
52- // store the original dispatch function definition
88+
89+ // Persist the old dispatch and bind to component so we can continue to dispatch()
5390 const oldDispatch = component . queue . dispatch . bind ( component . queue ) ;
54- // redefine the dispatch function so we can inject our code
91+
5592 component . queue . dispatch = ( fiber , queue , action ) => {
56- // don't do anything if state is locked
5793 if ( mode . locked && ! mode . jumping ) return ;
5894 oldDispatch ( fiber , queue , action ) ;
95+ // * Uncomment setTimeout to prevent snapshot lag-effect
96+ // * (i.e. getting the prior snapshot on each state change)
5997 // setTimeout(() => {
6098 updateSnapShotTree ( ) ;
6199 sendSnapshot ( ) ;
62100 // }, 100);
63101 } ;
102+ // Set a custom property to ensure we don't change this method again
64103 component . queue . dispatch . linkFiberChanged = true ;
65104 }
66105
67- // Helper function to traverse through the memoized state
68106 // TODO: WE NEED TO CLEAN IT UP A BIT
69107 function traverseHooks ( memoizedState ) {
70108 // Declare variables and assigned to 0th index and an empty object, respectively
71109 const memoized = { } ;
72110 let index = 0 ;
73111 astHooks = Object . values ( astHooks ) ;
74- // while memoizedState is truthy, save the value to the object
112+ // While memoizedState is truthy, save the value to the object
75113 while ( memoizedState && memoizedState . queue ) {
76- // prevents useEffect from crashing on load
114+ // // prevents useEffect from crashing on load
77115 // if (memoizedState.next.queue === null) { // prevents double pushing snapshot updates
78116 changeUseState ( memoizedState ) ;
79117 // }
80118 // memoized[astHooks[index]] = memoizedState.memoizedState;
81119 memoized [ astHooks [ index ] ] = memoizedState . memoizedState ;
82120 // Reassign memoizedState to its next value
83121 memoizedState = memoizedState . next ;
84- // Increment the index by 2
122+ // See astParser.js for explanation of this increment
85123 index += 2 ;
86124 }
87125 return memoized ;
88126 }
89127
90128 function createTree ( currentFiber , tree = new Tree ( 'root' ) ) {
129+ // Base case: child or sibling pointed to null
91130 if ( ! currentFiber ) return tree ;
92131
93132 const {
@@ -99,16 +138,14 @@ module.exports = (snap, mode) => {
99138 } = currentFiber ;
100139
101140 let nextTree = tree ;
102- // check if stateful component
141+
142+ // Check if stateful component
103143 if ( stateNode && stateNode . state ) {
104- // add component to tree
105- nextTree = tree . appendChild ( stateNode ) ;
106- // change setState functionality
107- changeSetState ( stateNode ) ;
144+ nextTree = tree . appendChild ( stateNode ) ; // Add component to tree
145+ changeSetState ( stateNode ) ; // Change setState functionality
108146 }
109- // Check if the component uses hooks
110- // console.log("memoizedState", memoizedState);
111147
148+ // Check if the component uses hooks
112149 if (
113150 memoizedState &&
114151 Object . hasOwnProperty . call ( memoizedState , 'baseState' )
@@ -123,18 +160,19 @@ module.exports = (snap, mode) => {
123160 memoizedState . traversed = traverseHooks ( memoizedState ) ;
124161 nextTree = tree . appendChild ( memoizedState ) ;
125162 }
126- // iterate through siblings
163+
164+ // Recurse on siblings
127165 createTree ( sibling , tree ) ;
128- // iterate through children
166+ // Recurse on children
129167 createTree ( child , nextTree ) ;
130168
131169 return tree ;
132170 }
133- // runs when page initially loads
134- // but skips 1st hook click
171+
172+ // ! BUG: skips 1st hook click
135173 async function updateSnapShotTree ( ) {
136174 let current ;
137- // if concurrent mode, grab current.child'
175+ // If concurrent mode, grab current.child
138176 if ( concurrent ) {
139177 // we need a way to wait for current child to populate
140178 const promise = new Promise ( ( resolve , reject ) => {
@@ -152,6 +190,7 @@ module.exports = (snap, mode) => {
152190 }
153191
154192 return async container => {
193+ // Point fiberRoot to FiberRootNode
155194 if ( container . _internalRoot ) {
156195 fiberRoot = container . _internalRoot ;
157196 concurrent = true ;
@@ -160,12 +199,13 @@ module.exports = (snap, mode) => {
160199 _reactRootContainer : { _internalRoot } ,
161200 _reactRootContainer,
162201 } = container ;
163- // only assign internal root if it actually exists
202+ // Only assign internal root if it actually exists
164203 fiberRoot = _internalRoot || _reactRootContainer ;
165204 }
166205
167206 await updateSnapShotTree ( ) ;
168- // send the initial snapshot once the content script has started up
207+ // Send the initial snapshot once the content script has started up
208+ // This message is sent from contentScript.js in chrome extension bundles
169209 window . addEventListener ( 'message' , ( { data : { action } } ) => {
170210 if ( action === 'contentScriptStarted' ) sendSnapshot ( ) ;
171211 } ) ;
0 commit comments