44
44
/* eslint-disable no-use-before-define */
45
45
/* eslint-disable no-param-reassign */
46
46
47
- const Tree = require ( './tree' ) ;
48
- const componentActionsRecord = require ( './masterState' ) ;
47
+ // const Tree = require('./tree').default;
48
+ // const componentActionsRecord = require('./masterState');
49
+ import Tree from './tree' ;
50
+ import componentActionsRecord from './masterState' ;
49
51
50
- module . exports = ( snap , mode ) => {
52
+ const DEBUG_MODE = false ;
53
+
54
+ const alwaysLog = console . log ;
55
+
56
+ console . log = ( original => {
57
+ return ( ...args ) => {
58
+ if ( DEBUG_MODE ) original ( ...args ) ;
59
+ }
60
+ } ) ( console . log ) ;
61
+
62
+
63
+ const circularComponentTable = new Set ( ) ;
64
+
65
+ // module.exports = (snap, mode) => {
66
+ export default ( snap , mode ) => {
51
67
let fiberRoot = null ;
52
68
53
- async function sendSnapshot ( ) {
69
+ function sendSnapshot ( ) {
70
+ alwaysLog ( 'sendSnapshot called' ) ;
54
71
// Don't send messages while jumping or while paused
72
+ circularComponentTable . clear ( ) ;
73
+ // console.log('sending snapshot');
55
74
if ( mode . jumping || mode . paused ) return ;
56
- console . log ( 'PAYLOAD: before cleaning' , snap . tree ) ;
75
+ // console.log('PAYLOAD: before cleaning', snap.tree);
76
+
77
+ if ( ! snap . tree ) {
78
+ // console.log('snapshot empty, sending root');
79
+ snap . tree = new Tree ( 'root' , 'root' ) ;
80
+ }
57
81
const payload = snap . tree . cleanTreeCopy ( ) ; // snap.tree.getCopy();
58
- console . log ( 'PAYLOAD: after cleaning' , payload ) ;
59
- try {
60
- await window . postMessage ( {
82
+
83
+ // console.log('PAYLOAD: after cleaning', payload);
84
+ // try {
85
+ // await window.postMessage({
86
+ window . postMessage ( {
61
87
action : 'recordSnap' ,
62
88
payload,
63
89
} ) ;
64
- } catch ( e ) {
65
- console . log ( 'failed to send postMessage:' , e ) ;
66
- }
90
+ // } catch (e) {
91
+ // console.log('failed to send postMessage:', e);
92
+ // }
67
93
}
68
94
69
95
// Carlos: Injects instrumentation to update our state tree every time
@@ -75,13 +101,11 @@ module.exports = (snap, mode) => {
75
101
// prevents useEffect from crashing on load
76
102
// if (memoizedState.next.queue === null) { // prevents double pushing snapshot updates
77
103
if ( memoizedState . memoizedState ) {
78
- console . log ( 'memoizedState in traverseHooks is:' , memoizedState ) ;
79
104
hooksStates . push ( {
80
105
component : memoizedState . queue ,
81
106
state : memoizedState . memoizedState ,
82
107
} ) ;
83
108
}
84
- // console.log('GOT STATE', memoizedState.memoizedState);
85
109
memoizedState = memoizedState . next !== memoizedState
86
110
? memoizedState . next : null ;
87
111
}
@@ -90,8 +114,11 @@ module.exports = (snap, mode) => {
90
114
91
115
// Carlos: This runs after EVERY Fiber commit. It creates a new snapshot,
92
116
//
93
- function createTree ( currentFiber , tree = new Tree ( 'root' ) ) {
117
+
118
+ let ctRunning = 0 ;
119
+ function createTree ( currentFiber , tree = new Tree ( 'root' , 'root' ) , fromSibling = false ) {
94
120
// Base case: child or sibling pointed to null
121
+ console . log ( 'createTree: creating tree' ) ;
95
122
if ( ! currentFiber ) return null ;
96
123
if ( ! tree ) return tree ;
97
124
@@ -115,22 +142,20 @@ module.exports = (snap, mode) => {
115
142
let componentFound = false ;
116
143
117
144
// Check if node is a stateful setState component
118
- if ( stateNode && stateNode . state && ( tag === 0 || tag === 1 ) ) {
119
- console . log ( 'in create tree if' ) ;
120
- console . log ( 'this is currentFiber from createTree' , currentFiber ) ;
145
+ if ( stateNode && stateNode . state && ( tag === 0 || tag === 1 || tag === 2 ) ) { // { || tag === 2)) {
121
146
// Save component's state and setState() function to our record for future
122
147
// time-travel state changing. Add record index to snapshot so we can retrieve.
148
+ console . log ( 'createTree() found setState component' ) ;
123
149
componentData . index = componentActionsRecord . saveNew ( stateNode . state , stateNode ) ;
124
150
newState = stateNode . state ;
125
151
componentFound = true ;
126
152
}
127
153
128
154
// Check if node is a hooks useState function
129
155
let hooksIndex ;
130
- if ( memoizedState && ( tag === 0 || tag === 1 || tag === 10 ) ) {
131
- console . log ( 'in create tree if' ) ;
132
- console . log ( 'this is currentFiber from createTree' , currentFiber ) ;
156
+ if ( memoizedState && ( tag === 0 || tag === 1 || tag === 2 || tag === 10 ) ) {
133
157
if ( memoizedState . queue ) {
158
+ console . log ( 'createTree() found hooks component' ) ;
134
159
// Hooks states are stored as a linked list using memoizedState.next,
135
160
// so we must traverse through the list and get the states.
136
161
// We then store them along with the corresponding memoizedState.queue,
@@ -151,9 +176,10 @@ module.exports = (snap, mode) => {
151
176
}
152
177
153
178
// This grabs stateless components
154
- if ( ! componentFound && ( tag === 0 || tag === 1 ) ) {
179
+ /*
180
+ if (!componentFound && (tag === 0 || tag === 1 || tag === 2)) {
155
181
newState = 'stateless';
156
- }
182
+ }*/
157
183
158
184
// Adds performance metrics to the component data
159
185
componentData = {
@@ -164,52 +190,70 @@ module.exports = (snap, mode) => {
164
190
treeBaseDuration,
165
191
} ;
166
192
167
- if ( componentFound ) {
168
- tree . addChild ( newState , elementType . name ? elementType . name : elementType , componentData ) ;
169
- } else if ( newState === 'stateless' ) {
170
- tree . addChild ( newState , elementType . name ? elementType . name : elementType , componentData ) ;
193
+ let newNode = null ;
194
+ if ( componentFound || newState === 'stateless' ) {
195
+ if ( fromSibling ) {
196
+ console . log ( 'createTree(), relevant component found in sibling' ) ;
197
+ newNode = tree . addSibling ( newState ,
198
+ elementType ? elementType . name : 'nameless' ,
199
+ componentData ) ;
200
+ } else {
201
+ console . log ( 'createTree(), relevant component found in child' ) ;
202
+ newNode = tree . addChild ( newState ,
203
+ elementType ? elementType . name : 'nameless' ,
204
+ componentData ) ;
205
+ }
206
+ } else {
207
+ console . log ( 'createTree(), no new relevant nodes, continuing from same node' )
208
+ newNode = tree ;
171
209
}
172
210
173
211
// Recurse on children
174
- if ( child ) {
212
+
213
+ if ( child && ! circularComponentTable . has ( child ) ) {
175
214
// If this node had state we appended to the children array,
176
215
// so attach children to the newly appended child.
177
216
// Otherwise, attach children to this same node.
178
- if ( tree . children . length > 0 ) {
179
- createTree ( child , tree . children [ tree . children . length - 1 ] ) ;
180
- } else {
181
- createTree ( child , tree ) ;
182
- }
217
+ console . log ( 'going into child' ) ;
218
+ circularComponentTable . add ( child ) ;
219
+ createTree ( child , newNode ) ;
183
220
}
184
221
// Recurse on siblings
185
- if ( sibling ) createTree ( sibling , tree ) ;
222
+ if ( sibling && ! circularComponentTable . has ( sibling ) ) {
223
+ console . log ( 'going into sibling' ) ;
224
+ circularComponentTable . add ( sibling ) ;
225
+ createTree ( sibling , newNode , true ) ;
226
+ }
227
+
228
+ if ( circularComponentTable . has ( child ) ) {
229
+ console . log ( 'found circular child, exiting tree loop' ) ;
230
+ }
231
+
232
+ if ( circularComponentTable . has ( sibling ) ) {
233
+ console . log ( 'found circular sibling, exiting tree loop' ) ;
234
+ }
186
235
236
+ // // console.log('linkFiber.js: processed children and sibling, returning tree');
187
237
return tree ;
188
238
}
189
239
190
- // ! BUG: skips 1st hook click
240
+ let updateSnapshotTreeCount = 0 ;
191
241
function updateSnapShotTree ( ) {
192
- /* let current;
193
- // If concurrent mode, grab current.child
194
- if (concurrent) {
195
- // we need a way to wait for current child to populate
196
- const promise = new Promise((resolve, reject) => {
197
- setTimeout(() => resolve(fiberRoot.current.child), 400);
198
- });
199
- current = await promise;
200
- current = fiberRoot.current.child;
201
- } else {
202
- current = fiberRoot.current;
203
- } */
204
- const { current } = fiberRoot ; // Carlos: get rid of concurrent mode for now
242
+ // console.log('updateSnapshotTree(), checking if fiberRoot updated');
205
243
206
- // console.log('FIBER COMMITTED, new fiber is:', util.inspect(current, false, 4));
207
- // fs.appendFile('fiberlog.txt', util.inspect(current, false, 10));
208
- snap . tree = createTree ( current ) ; // Carlos: pass new hooks state here?
244
+ updateSnapshotTreeCount ++ ;
245
+ if ( updateSnapshotTreeCount > 1 ) alwaysLog ( 'MULTIPLE SNAPSHOT TREE UPDATES:' , updateSnapshotTreeCount ) ;
246
+ if ( fiberRoot ) {
247
+ console . log ( 'updateSnapshotTree(), updating snapshot' , snap . tree ) ;
248
+ const { current } = fiberRoot ;
249
+ snap . tree = createTree ( current ) ;
250
+ console . log ( 'updateSnapshotTree(), completed snapshot' , snap . tree ) ;
251
+ }
252
+ updateSnapshotTreeCount -- ;
209
253
}
210
254
211
- return async container => {
212
- // Point fiberRoot to FiberRootNode
255
+ return async ( ) => {
256
+ /* const container = document.getElementById('root');
213
257
if (container._internalRoot) {
214
258
fiberRoot = container._internalRoot;
215
259
} else {
@@ -220,28 +264,35 @@ module.exports = (snap, mode) => {
220
264
// Only assign internal root if it actually exists
221
265
fiberRoot = _internalRoot || _reactRootContainer;
222
266
}
267
+ */
223
268
const devTools = window . __REACT_DEVTOOLS_GLOBAL_HOOK__ ;
224
- console . log ( 'this is devTools' , devTools ) ;
225
269
const reactInstance = devTools ? devTools . renderers . get ( 1 ) : null ;
226
-
270
+ fiberRoot = devTools . getFiberRoots ( 1 ) . values ( ) . next ( ) . value ;
271
+
272
+ alwaysLog ( 'fiberRoot:' , fiberRoot ) ;
227
273
if ( reactInstance && reactInstance . version ) {
228
274
devTools . onCommitFiberRoot = ( function ( original ) {
229
275
return function ( ...args ) {
230
276
fiberRoot = args [ 1 ] ;
231
- console . log ( 'this is fiberRoot ' , fiberRoot ) ;
277
+ // console.log('Fiber committed, updating snapshot tree with: ', fiberRoot);
232
278
updateSnapShotTree ( ) ;
279
+ console . log ( 'Fiber committed, sending latest snapshot' ) ;
233
280
sendSnapshot ( ) ;
281
+ console . log ( 'Fiber committed, latest snapshot sent' ) ;
234
282
return original ( ...args ) ;
235
283
} ;
236
284
} ( devTools . onCommitFiberRoot ) ) ;
237
285
}
238
286
updateSnapShotTree ( ) ;
287
+ sendSnapshot ( ) ;
288
+ // updateSnapShotTree();
239
289
// Send the initial snapshot once the content script has started up
240
290
// This message is sent from contentScript.js in chrome extension bundles
241
- window . addEventListener ( 'message' , ( { data : { action } } ) => {
242
- if ( action === 'contentScriptStarted' ) {
243
- sendSnapshot ( ) ;
244
- }
245
- } ) ;
291
+ // window.addEventListener('message', ({ data: { action } }) => {
292
+ // if (action === 'contentScriptStarted') {
293
+ // // console.log('content script started received at linkFiber.js')
294
+ // sendSnapshot();
295
+ // }
296
+ // });
246
297
} ;
247
298
} ;
0 commit comments