44
44
/* eslint-disable no-use-before-define */
45
45
/* eslint-disable no-param-reassign */
46
46
47
- < << << << HEAD
48
- const { Tree , UnfilteredTreeNode } = require ( './tree' ) ;
49
- const astParser = require ( './astParser' ) ;
50
- const { saveState } = require ( './masterState' ) ;
51
- // import * as reactWorkTags from './reactWorkTags';
52
- = === ===
53
47
const Tree = require ( './tree' ) ;
54
48
const componentActionsRecord = require ( './masterState' ) ;
55
- > >>> >>> 8e774670 f36699322d70300c6382bcdcc7b349e0
56
49
57
50
module . exports = ( snap , mode ) => {
58
51
let fiberRoot = null ;
59
- let astHooks ;
60
- let concurrent = false ; // flag to check if we are in concurrent mode
61
- const reactWorkTags = [
62
- 'FunctionComponent' ,
63
- 'ClassComponent' ,
64
- 'IndeterminateComponent' ,
65
- 'HostRoot' , // Root of a host tree. Could be nested inside another node.
66
- 'HostPortal' , // A subtree. Could be an entry point to a different renderer.
67
- 'HostComponent' ,
68
- 'HostText' ,
69
- ] ;
70
-
71
52
72
53
async function sendSnapshot ( ) {
73
54
// Don't send messages while jumping or while paused
74
55
if ( mode . jumping || mode . paused ) return ;
75
- // console.log('PAYLOAD: before cleaning', snap.tree);
56
+ console . log ( 'PAYLOAD: before cleaning' , snap . tree ) ;
76
57
const payload = snap . tree . cleanTreeCopy ( ) ; // snap.tree.getCopy();
77
- // console.log('PAYLOAD: after cleaning', payload);
58
+ console . log ( 'PAYLOAD: after cleaning' , payload ) ;
78
59
try {
79
60
await window . postMessage ( {
80
61
action : 'recordSnap' ,
@@ -88,14 +69,14 @@ module.exports = (snap, mode) => {
88
69
// Carlos: Injects instrumentation to update our state tree every time
89
70
// a hooks component changes state
90
71
function traverseHooks ( memoizedState ) {
91
- const hooksComponents = [ ] ;
72
+ const hooksStates = [ ] ;
92
73
while ( memoizedState && memoizedState . queue ) {
93
74
// Carlos: these two are legacy comments, we should look into them later
94
75
// prevents useEffect from crashing on load
95
76
// if (memoizedState.next.queue === null) { // prevents double pushing snapshot updates
96
77
if ( memoizedState . memoizedState ) {
97
78
console . log ( 'memoizedState in traverseHooks is:' , memoizedState ) ;
98
- hooksComponents . push ( {
79
+ hooksStates . push ( {
99
80
component : memoizedState . queue ,
100
81
state : memoizedState . memoizedState ,
101
82
} ) ;
@@ -104,14 +85,15 @@ module.exports = (snap, mode) => {
104
85
memoizedState = memoizedState . next !== memoizedState
105
86
? memoizedState . next : null ;
106
87
}
107
- return hooksComponents ;
88
+ return hooksStates ;
108
89
}
109
90
110
91
// Carlos: This runs after EVERY Fiber commit. It creates a new snapshot,
111
92
//
112
93
function createTree ( currentFiber , tree = new Tree ( 'root' ) ) {
113
94
// Base case: child or sibling pointed to null
114
- if ( ! currentFiber ) return tree ;
95
+ if ( ! currentFiber ) return null ;
96
+ if ( ! tree ) return tree ;
115
97
116
98
// These have the newest state. We update state and then
117
99
// called updateSnapshotTree()
@@ -122,40 +104,81 @@ module.exports = (snap, mode) => {
122
104
memoizedState,
123
105
elementType,
124
106
tag,
107
+ actualDuration,
108
+ actualStartTime,
109
+ selfBaseDuration,
110
+ treeBaseDuration,
125
111
} = currentFiber ;
126
112
127
- let index ;
128
- // Check if node is a stateful component
113
+ let newState = null ;
114
+ let componentData = { } ;
115
+ let componentFound = false ;
116
+
117
+ // Check if node is a stateful setState component
129
118
if ( stateNode && stateNode . state && ( tag === 0 || tag === 1 ) ) {
130
119
// Save component's state and setState() function to our record for future
131
120
// time-travel state changing. Add record index to snapshot so we can retrieve.
132
- index = componentActionsRecord . saveNew ( stateNode . state , stateNode ) ;
133
- tree . appendChild ( stateNode . state , elementType . name , index ) ; // Add component to tree
134
- } else {
135
- // grab stateless components here
121
+ componentData . index = componentActionsRecord . saveNew ( stateNode . state , stateNode ) ;
122
+ newState . state = stateNode . state ;
123
+ componentFound = true ;
136
124
}
137
125
138
- // Check if node is a hooks function
126
+ // Check if node is a hooks useState function
127
+ let hooksIndex ;
139
128
if ( memoizedState && ( tag === 0 || tag === 1 || tag === 10 ) ) {
140
129
if ( memoizedState . queue ) {
141
- const hooksComponents = traverseHooks ( memoizedState ) ;
142
- hooksComponents . forEach ( c => {
143
- if ( elementType . name ) {
144
- index = componentActionsRecord . saveNew ( c . state , c . component ) ;
145
- tree . appendChild ( c . state , elementType . name ? elementType . name : 'nameless' , index ) ;
130
+ // Hooks states are stored as a linked list using memoizedState.next,
131
+ // so we must traverse through the list and get the states.
132
+ // We then store them along with the corresponding memoizedState.queue,
133
+ // which includes the dispatch() function we use to change their state.
134
+ const hooksStates = traverseHooks ( memoizedState ) ;
135
+ hooksStates . forEach ( state => {
136
+ hooksIndex = componentActionsRecord . saveNew ( state . state , state . component ) ;
137
+ if ( newState && newState . hooksState ) {
138
+ newState . hooksState . push ( [ state . state , hooksIndex ] ) ;
139
+ } else if ( newState ) {
140
+ newState . hooksState = [ [ state . state , hooksIndex ] ] ;
141
+ } else {
142
+ newState = { hooksState : [ [ state . state , hooksIndex ] ] } ;
146
143
}
144
+ componentFound = true ;
147
145
} ) ;
148
146
}
149
147
}
150
148
151
- // Recurse on siblings
152
- createTree ( sibling , tree ) ;
149
+ // This grabs stateless components
150
+ if ( ! componentFound && ( tag === 0 || tag === 1 ) ) {
151
+ newState = 'stateless' ;
152
+ }
153
+
154
+ // Adds performance metrics to the component data
155
+ componentData = {
156
+ ...componentData ,
157
+ actualDuration,
158
+ actualStartTime,
159
+ selfBaseDuration,
160
+ treeBaseDuration,
161
+ } ;
162
+
163
+ if ( componentFound ) {
164
+ tree . addChild ( newState , elementType . name ? elementType . name : elementType , componentData ) ;
165
+ } else if ( newState === 'stateless' ) {
166
+ tree . addChild ( newState , elementType . name ? elementType . name : elementType , componentData ) ;
167
+ }
168
+
153
169
// Recurse on children
154
- if ( tree . children . length > 0 ) {
155
- createTree ( child , tree . children [ 0 ] ) ;
156
- } else {
157
- createTree ( child , tree ) ;
170
+ if ( child ) {
171
+ // If this node had state we appended to the children array,
172
+ // so attach children to the newly appended child.
173
+ // Otherwise, attach children to this same node.
174
+ if ( tree . children . length > 0 ) {
175
+ createTree ( child , tree . children [ tree . children . length - 1 ] ) ;
176
+ } else {
177
+ createTree ( child , tree ) ;
178
+ }
158
179
}
180
+ // Recurse on siblings
181
+ if ( sibling ) createTree ( sibling , tree ) ;
159
182
160
183
return parentNode ;
161
184
}
@@ -194,6 +217,7 @@ module.exports = (snap, mode) => {
194
217
195
218
// ! BUG: skips 1st hook click
196
219
function updateSnapShotTree ( ) {
220
+ < << << << HEAD
197
221
/* let current;
198
222
// If concurrent mode, grab current.child
199
223
if (concurrent) {
@@ -218,28 +242,26 @@ module.exports = (snap, mode) => {
218
242
// fs.appendFile('fiberlog.txt', util.inspect(current, false, 10));
219
243
snap . tree = createTree ( current ) ; // Carlos: pass new hooks state here?
220
244
> >>> >>> 8e774670 f36699322d70300c6382bcdcc7b349e0
245
+ === = ===
246
+ const { current } = fiberRoot ;
247
+ snap . tree = createTree ( current ) ;
248
+ > >>> >>> 7 a59cf2ae4fd041fc21b23c396e02eae0fc01e84
221
249
}
222
250
223
251
return async container => {
224
252
// Point fiberRoot to FiberRootNode
225
253
if ( container . _internalRoot ) {
226
254
fiberRoot = container . _internalRoot ;
227
- concurrent = true ;
228
255
} else {
229
256
const {
230
257
_reactRootContainer : { _internalRoot } ,
231
258
_reactRootContainer,
232
259
} = container ;
233
260
// Only assign internal root if it actually exists
234
261
fiberRoot = _internalRoot || _reactRootContainer ;
235
- // console.log('_reactRootContainer is:', _reactRootContainer);
236
- // console.log('linkFiber.js, fiberRoot:', fiberRoot);
237
262
}
238
263
const devTools = window . __REACT_DEVTOOLS_GLOBAL_HOOK__ ;
239
264
const reactInstance = devTools ? devTools . renderers . get ( 1 ) : null ;
240
- const overrideHookState = reactInstance ? reactInstance . overrideHookState : null ;
241
- console . log ( 'DEVTOOLS:' , devTools ) ;
242
- console . log ( 'roots:' , reactInstance . getCurrentFiber ( ) )
243
265
244
266
if ( reactInstance && reactInstance . version ) {
245
267
devTools . onCommitFiberRoot = ( function ( original ) {
0 commit comments