@@ -20,6 +20,8 @@ import {
20
20
import Tree from './tree' ;
21
21
import componentActionsRecord from './masterState' ;
22
22
import { throttle , getHooksNames } from './helpers' ;
23
+ import { Console } from 'console' ;
24
+ import AtomsRelationship from '../app/components/AtomsRelationship' ;
23
25
24
26
// Set global variables to use in exported module and helper functions
25
27
declare global {
@@ -30,27 +32,29 @@ declare global {
30
32
let fiberRoot = null ;
31
33
let doWork = true ;
32
34
const circularComponentTable = new Set ( ) ;
33
- let allAtomsRelationship = [ ] ;
34
35
let isRecoil = false ;
36
+ let allAtomsRelationship = [ ] ;
37
+ let initialstart = false ;
35
38
36
39
// Simple check for whether our target app uses Recoil
37
40
if ( window [ `$recoilDebugStates` ] ) {
38
41
isRecoil = true ;
39
42
}
40
43
41
- function getRecoilState ( ) : any {
42
- const RecoilSnapshotsLength = window [ `$recoilDebugStates` ] . length ;
43
- const lastRecoilSnapshot = window [ `$recoilDebugStates` ] [ RecoilSnapshotsLength - 1 ] ;
44
- const nodeToNodeSubs = lastRecoilSnapshot . nodeToNodeSubscriptions ;
45
- const nodeToNodeSubsKeys = lastRecoilSnapshot . nodeToNodeSubscriptions . keys ( ) ;
46
- nodeToNodeSubsKeys . forEach (
47
- node => {
48
- nodeToNodeSubs . get ( node ) . forEach (
49
- nodeSubs => allAtomsRelationship . push ( [ node , nodeSubs , 'atoms and selectors' ] )
50
- ) ;
51
- }
52
- ) ;
53
- }
44
+ // function getRecoilState(): any {
45
+ // const RecoilSnapshotsLength = window[`$recoilDebugStates`].length;
46
+ // const lastRecoilSnapshot =
47
+ // window[`$recoilDebugStates`][RecoilSnapshotsLength - 1];
48
+ // const nodeToNodeSubs = lastRecoilSnapshot.nodeToNodeSubscriptions;
49
+ // const nodeToNodeSubsKeys = lastRecoilSnapshot.nodeToNodeSubscriptions.keys();
50
+ // nodeToNodeSubsKeys.forEach((node) => {
51
+ // nodeToNodeSubs
52
+ // .get(node)
53
+ // .forEach((nodeSubs) =>
54
+ // allAtomsRelationship.push([node, nodeSubs, 'atoms and selectors'])
55
+ // );
56
+ // });
57
+ // }
54
58
55
59
/**
56
60
* @method sendSnapshot
@@ -67,11 +71,14 @@ function sendSnapshot(snap: Snapshot, mode: Mode): void {
67
71
snap . tree = new Tree ( 'root' , 'root' ) ;
68
72
}
69
73
const payload = snap . tree . cleanTreeCopy ( ) ;
74
+
70
75
if ( isRecoil ) {
71
- getRecoilState ( ) ;
72
- payload . AtomsRelationship = allAtomsRelationship ;
76
+ // getRecoilState();
77
+ payload . AtomsComponents = atomsComponents ;
78
+ payload . AtomsSelectors = atomsSelectors ;
73
79
}
74
80
81
+
75
82
window . postMessage (
76
83
{
77
84
action : 'recordSnap' ,
@@ -103,13 +110,16 @@ function updateSnapShotTree(snap: Snapshot, mode: Mode): void {
103
110
* @param memoizedProps Property containing props on a stateful fctnl component's FiberNode object
104
111
* @return An array of array of HookStateItem objects (state and component properties)
105
112
*/
106
- function traverseRecoilHooks ( memoizedState : any , memoizedProps : any ) : HookStates {
113
+ function traverseRecoilHooks (
114
+ memoizedState : any ,
115
+ memoizedProps : any
116
+ ) : HookStates {
107
117
const hooksStates : HookStates = [ ] ;
108
118
while ( memoizedState && memoizedState . queue ) {
109
119
if (
110
- memoizedState . memoizedState
111
- && memoizedState . queue . lastRenderedReducer
112
- && memoizedState . queue . lastRenderedReducer . name === 'basicStateReducer'
120
+ memoizedState . memoizedState &&
121
+ memoizedState . queue . lastRenderedReducer &&
122
+ memoizedState . queue . lastRenderedReducer . name === 'basicStateReducer'
113
123
) {
114
124
if ( Object . entries ( memoizedProps ) . length !== 0 ) {
115
125
hooksStates . push ( {
@@ -118,7 +128,8 @@ function traverseRecoilHooks(memoizedState: any, memoizedProps: any): HookStates
118
128
} ) ;
119
129
}
120
130
}
121
- memoizedState = memoizedState . next !== memoizedState ? memoizedState . next : null ;
131
+ memoizedState =
132
+ memoizedState . next !== memoizedState ? memoizedState . next : null ;
122
133
}
123
134
124
135
return hooksStates ;
@@ -129,21 +140,20 @@ function traverseRecoilHooks(memoizedState: any, memoizedProps: any): HookStates
129
140
* @param memoizedState memoizedState property on a stateful fctnl component's FiberNode object
130
141
* @return An array of array of HookStateItem objects
131
142
*
132
- * Helper function to traverse through memoizedState and inject instrumentation to update our state tree
143
+ * Helper function to traverse through memoizedState and inject instrumentation to update our state tree
133
144
* every time a hooks component changes state
134
145
*/
135
146
function traverseHooks ( memoizedState : any ) : HookStates {
136
147
const hooksStates : HookStates = [ ] ;
137
148
while ( memoizedState && memoizedState . queue ) {
138
- if (
139
- memoizedState . memoizedState
140
- ) {
149
+ if ( memoizedState . memoizedState ) {
141
150
hooksStates . push ( {
142
151
component : memoizedState . queue ,
143
152
state : memoizedState . memoizedState ,
144
153
} ) ;
145
154
}
146
- memoizedState = memoizedState . next !== memoizedState ? memoizedState . next : null ;
155
+ memoizedState =
156
+ memoizedState . next !== memoizedState ? memoizedState . next : null ;
147
157
}
148
158
return hooksStates ;
149
159
}
@@ -160,6 +170,9 @@ function traverseHooks(memoizedState: any): HookStates {
160
170
* 3. Build a new state snapshot
161
171
*/
162
172
// This runs after every Fiber commit. It creates a new snapshot
173
+ let atomsSelectors = { } ;
174
+ let atomsComponents = { } ;
175
+
163
176
function createTree (
164
177
currentFiber : Fiber ,
165
178
tree : Tree = new Tree ( 'root' , 'root' ) ,
@@ -172,6 +185,7 @@ function createTree(
172
185
173
186
// These have the newest state. We update state and then
174
187
// called updateSnapshotTree()
188
+
175
189
const {
176
190
sibling,
177
191
stateNode,
@@ -186,20 +200,49 @@ function createTree(
186
200
treeBaseDuration,
187
201
} = currentFiber ;
188
202
189
- if ( elementType ?. name && isRecoil ) {
190
- let pointer = memoizedState ;
191
- while ( pointer !== null && pointer !== undefined && pointer . next !== null ) {
192
- pointer = pointer . next ;
193
- }
203
+ //Checks Recoil Atom and Selector Relationships
204
+ if (
205
+ currentFiber . memoizedState &&
206
+ currentFiber . memoizedState . next &&
207
+ currentFiber . memoizedState . next . memoizedState &&
208
+ currentFiber . memoizedState . next . memoizedState . deps &&
209
+ isRecoil &&
210
+ currentFiber . tag === 0 &&
211
+ currentFiber . key === null //prevents capturing the same Fiber nodes but different key values that result from being changed
212
+ ) {
213
+ let pointer = currentFiber . memoizedState . next ;
214
+ let componentName = currentFiber . elementType . name ;
194
215
195
- if ( pointer ?. memoizedState [ 1 ] ?. [ 0 ] . current ) {
196
- const atomName = pointer . memoizedState [ 1 ] ?. [ 0 ] . current . keys ( ) . next ( ) . value ;
197
- allAtomsRelationship . push ( [ atomName , elementType ?. name , 'atoms and components' ] ) ;
216
+ if ( ! atomsComponents [ componentName ] ) {
217
+ atomsComponents [ componentName ] = [ ] ;
218
+ while ( pointer !== null ) {
219
+ if ( ! Array . isArray ( pointer . memoizedState ) ) {
220
+ let atomName = pointer . memoizedState . deps [ 0 ] [ 'key' ] ;
221
+ atomsComponents [ componentName ] . push ( atomName ) ;
222
+ }
223
+ pointer = pointer . next ;
224
+ }
198
225
}
199
226
200
- if ( pointer ?. memoizedState [ 1 ] ?. [ 0 ] . key ) {
201
- const atomName = pointer . memoizedState [ 1 ] ?. [ 0 ] . key ;
202
- allAtomsRelationship . push ( [ atomName , elementType ?. name , 'atoms and components' ] ) ;
227
+ if (
228
+ currentFiber . memoizedState . next . memoizedState . deps [ 1 ] . current &&
229
+ ! initialstart
230
+ ) {
231
+ let getState = currentFiber . memoizedState . next . memoizedState . deps [ 1 ] . current . getState ( )
232
+ . graphsByVersion ;
233
+ getState . entries ( ) . forEach ( ( value ) => {
234
+ value [ 1 ] . nodeDeps . entries ( ) . forEach ( ( obj ) => {
235
+ if ( ! atomsSelectors [ obj [ 0 ] ] ) {
236
+ atomsSelectors [ obj [ 0 ] ] = [ ] ;
237
+ }
238
+ obj [ 1 ] . values ( ) . forEach ( ( selector ) => {
239
+ if ( ! atomsSelectors [ obj [ 0 ] ] . includes ( selector ) ) {
240
+ atomsSelectors [ obj [ 0 ] ] . push ( selector ) ;
241
+ }
242
+ } ) ;
243
+ } ) ;
244
+ } ) ;
245
+ initialstart = true ;
203
246
}
204
247
}
205
248
@@ -235,17 +278,17 @@ function createTree(
235
278
236
279
// RECOIL HOOKS
237
280
if (
238
- memoizedState
239
- && ( tag === 0 || tag === 1 || tag === 2 || tag === 10 )
240
- && isRecoil === true
281
+ memoizedState &&
282
+ ( tag === 0 || tag === 1 || tag === 2 || tag === 10 ) &&
283
+ isRecoil === true
241
284
) {
242
285
if ( memoizedState . queue ) {
243
286
// Hooks states are stored as a linked list using memoizedState.next,
244
287
// so we must traverse through the list and get the states.
245
288
// We then store them along with the corresponding memoizedState.queue,
246
289
// which includes the dispatch() function we use to change their state.
247
290
const hooksStates = traverseRecoilHooks ( memoizedState , memoizedProps ) ;
248
- hooksStates . forEach ( state => {
291
+ hooksStates . forEach ( ( state ) => {
249
292
hooksIndex = componentActionsRecord . saveNew (
250
293
state . state ,
251
294
state . component
@@ -268,9 +311,9 @@ function createTree(
268
311
// Check if node is a hooks useState function
269
312
// REGULAR REACT HOOKS
270
313
if (
271
- memoizedState
272
- && ( tag === 0 || tag === 1 || tag === 2 || tag === 10 )
273
- && isRecoil === false
314
+ memoizedState &&
315
+ ( tag === 0 || tag === 1 || tag === 2 || tag === 10 ) &&
316
+ isRecoil === false
274
317
) {
275
318
if ( memoizedState . queue ) {
276
319
// Hooks states are stored as a linked list using memoizedState.next,
@@ -364,6 +407,7 @@ export default (snap: Snapshot, mode: Mode): (() => void) => {
364
407
const devTools = window . __REACT_DEVTOOLS_GLOBAL_HOOK__ ;
365
408
const reactInstance = devTools ? devTools . renderers . get ( 1 ) : null ;
366
409
fiberRoot = devTools . getFiberRoots ( 1 ) . values ( ) . next ( ) . value ;
410
+
367
411
const throttledUpdateSnapshot = throttle ( ( ) => updateSnapShotTree ( snap , mode ) , 70 ) ;
368
412
document . addEventListener ( 'visibilitychange' , onVisibilityChange ) ;
369
413
if ( reactInstance && reactInstance . version ) {
@@ -376,7 +420,7 @@ export default (snap: Snapshot, mode: Mode): (() => void) => {
376
420
}
377
421
return original ( ...args ) ;
378
422
} ;
379
- } ( devTools . onCommitFiberRoot ) ) ;
423
+ } ) ( devTools . onCommitFiberRoot ) ;
380
424
}
381
425
throttledUpdateSnapshot ( ) ;
382
426
} ;
0 commit comments