@@ -46,8 +46,6 @@ const componentActionsRecord = require('./masterState');
46
46
47
47
module . exports = ( snap , mode ) => {
48
48
let fiberRoot = null ;
49
- let astHooks ;
50
- let concurrent = false ; // flag to check if we are in concurrent mode
51
49
52
50
async function sendSnapshot ( ) {
53
51
// Don't send messages while jumping or while paused
@@ -68,14 +66,14 @@ module.exports = (snap, mode) => {
68
66
// Carlos: Injects instrumentation to update our state tree every time
69
67
// a hooks component changes state
70
68
function traverseHooks ( memoizedState ) {
71
- const hooksComponents = [ ] ;
69
+ const hooksStates = [ ] ;
72
70
while ( memoizedState && memoizedState . queue ) {
73
71
// Carlos: these two are legacy comments, we should look into them later
74
72
// prevents useEffect from crashing on load
75
73
// if (memoizedState.next.queue === null) { // prevents double pushing snapshot updates
76
74
if ( memoizedState . memoizedState ) {
77
75
console . log ( 'memoizedState in traverseHooks is:' , memoizedState ) ;
78
- hooksComponents . push ( {
76
+ hooksStates . push ( {
79
77
component : memoizedState . queue ,
80
78
state : memoizedState . memoizedState ,
81
79
} ) ;
@@ -84,7 +82,7 @@ module.exports = (snap, mode) => {
84
82
memoizedState = memoizedState . next !== memoizedState
85
83
? memoizedState . next : null ;
86
84
}
87
- return hooksComponents ;
85
+ return hooksStates ;
88
86
}
89
87
90
88
// Carlos: This runs after EVERY Fiber commit. It creates a new snapshot,
@@ -94,7 +92,6 @@ module.exports = (snap, mode) => {
94
92
if ( ! currentFiber ) return null ;
95
93
if ( ! tree ) return tree ;
96
94
97
-
98
95
// These have the newest state. We update state and then
99
96
// called updateSnapshotTree()
100
97
const {
@@ -113,39 +110,45 @@ module.exports = (snap, mode) => {
113
110
let newState = null ;
114
111
let componentData = { } ;
115
112
let componentFound = false ;
116
- // Check if node is a stateful component
113
+
114
+ // Check if node is a stateful setState component
117
115
if ( stateNode && stateNode . state && ( tag === 0 || tag === 1 ) ) {
118
116
// Save component's state and setState() function to our record for future
119
117
// time-travel state changing. Add record index to snapshot so we can retrieve.
120
118
componentData . index = componentActionsRecord . saveNew ( stateNode . state , stateNode ) ;
121
- newState = stateNode . state ;
119
+ newState . state = stateNode . state ;
122
120
componentFound = true ;
123
- // tree.appendToChild(stateNode.state, elementType.name, index); // Add component to tree
124
- } else if ( tag === 0 || tag === 1 ) {
125
- // grab stateless components here
126
- newState = 'stateless' ;
127
- // tree.appendChild({}, elementType.name) // Add component to tree
128
121
}
129
122
130
- // Check if node is a hooks function
123
+ // Check if node is a hooks useState function
131
124
let hooksIndex ;
132
125
if ( memoizedState && ( tag === 0 || tag === 1 || tag === 10 ) ) {
133
126
if ( memoizedState . queue ) {
134
- const hooksComponents = traverseHooks ( memoizedState ) ;
135
- hooksComponents . forEach ( c => {
136
- hooksIndex = componentActionsRecord . saveNew ( c . state , c . component ) ;
137
- if ( newState . hooksState ) {
138
- newState . hooksState . push ( [ c . state , hooksIndex ] ) ;
127
+ // Hooks states are stored as a linked list using memoizedState.next,
128
+ // so we must traverse through the list and get the states.
129
+ // We then store them along with the corresponding memoizedState.queue,
130
+ // which includes the dispatch() function we use to change their state.
131
+ const hooksStates = traverseHooks ( memoizedState ) ;
132
+ hooksStates . forEach ( state => {
133
+ hooksIndex = componentActionsRecord . saveNew ( state . state , state . component ) ;
134
+ if ( newState && newState . hooksState ) {
135
+ newState . hooksState . push ( [ state . state , hooksIndex ] ) ;
136
+ } else if ( newState ) {
137
+ newState . hooksState = [ [ state . state , hooksIndex ] ] ;
139
138
} else {
140
- newState . hooksState = [ [ c . state , hooksIndex ] ] ;
139
+ newState = { hooksState : [ [ state . state , hooksIndex ] ] } ;
141
140
}
142
141
componentFound = true ;
143
- // newState = { ...newState, hooksState: c.state };
144
- // tree.appendSibling(c.state, elementType.name ? elementType.name : 'nameless', index);
145
142
} ) ;
146
143
}
147
144
}
148
145
146
+ // This grabs stateless components
147
+ if ( ! componentFound && ( tag === 0 || tag === 1 ) ) {
148
+ newState = 'stateless' ;
149
+ }
150
+
151
+ // Adds performance metrics to the component data
149
152
componentData = {
150
153
...componentData ,
151
154
actualDuration,
@@ -162,6 +165,9 @@ module.exports = (snap, mode) => {
162
165
163
166
// Recurse on children
164
167
if ( child ) {
168
+ // If this node had state we appended to the children array,
169
+ // so attach children to the newly appended child.
170
+ // Otherwise, attach children to this same node.
165
171
if ( tree . children . length > 0 ) {
166
172
createTree ( child , tree . children [ tree . children . length - 1 ] ) ;
167
173
} else {
@@ -176,43 +182,24 @@ module.exports = (snap, mode) => {
176
182
177
183
// ! BUG: skips 1st hook click
178
184
function updateSnapShotTree ( ) {
179
- /* let current;
180
- // If concurrent mode, grab current.child
181
- if (concurrent) {
182
- // we need a way to wait for current child to populate
183
- const promise = new Promise((resolve, reject) => {
184
- setTimeout(() => resolve(fiberRoot.current.child), 400);
185
- });
186
- current = await promise;
187
- current = fiberRoot.current.child;
188
- } else {
189
- current = fiberRoot.current;
190
- } */
191
- const { current } = fiberRoot ; // Carlos: get rid of concurrent mode for now
192
-
193
- // console.log('FIBER COMMITTED, new fiber is:', util.inspect(current, false, 4));
194
- // fs.appendFile('fiberlog.txt', util.inspect(current, false, 10));
195
- snap . tree = createTree ( current ) ; // Carlos: pass new hooks state here?
185
+ const { current } = fiberRoot ;
186
+ snap . tree = createTree ( current ) ;
196
187
}
197
188
198
189
return async container => {
199
190
// Point fiberRoot to FiberRootNode
200
191
if ( container . _internalRoot ) {
201
192
fiberRoot = container . _internalRoot ;
202
- concurrent = true ;
203
193
} else {
204
194
const {
205
195
_reactRootContainer : { _internalRoot } ,
206
196
_reactRootContainer,
207
197
} = container ;
208
198
// Only assign internal root if it actually exists
209
199
fiberRoot = _internalRoot || _reactRootContainer ;
210
- // console.log('_reactRootContainer is:', _reactRootContainer);
211
- // console.log('linkFiber.js, fiberRoot:', fiberRoot);
212
200
}
213
201
const devTools = window . __REACT_DEVTOOLS_GLOBAL_HOOK__ ;
214
202
const reactInstance = devTools ? devTools . renderers . get ( 1 ) : null ;
215
- const overrideHookState = reactInstance ? reactInstance . overrideHookState : null ;
216
203
217
204
if ( reactInstance && reactInstance . version ) {
218
205
devTools . onCommitFiberRoot = ( function ( original ) {
0 commit comments