1
1
/* eslint-disable func-names */
2
2
/* eslint-disable no-use-before-define */
3
3
/* eslint-disable no-param-reassign */
4
-
5
4
// links component state tree to library
6
5
// changes the setState method to also update our snapshot
7
-
8
6
const Tree = require ( './tree' ) ;
9
7
const astParser = require ( './astParser' ) ;
10
- const { saveState } = require ( './masterState' ) ; // saves AST state as array for later use
8
+ const { saveState } = require ( './masterState' ) ;
11
9
12
10
module . exports = ( snap , mode ) => {
13
- // snap is the current tree
14
- // mode is {jumping: bool, locked: bool, paused: bool}
15
-
16
11
let fiberRoot = null ;
17
12
let astHooks ;
18
13
19
- function sendSnapshot ( ) { // send snapshot of current fiber tree to chrome extension ?
14
+ function sendSnapshot ( ) {
20
15
// don't send messages while jumping or while paused
21
- // DEV: So that when we are jumping to an old snapshot it wouldn't think we want to create new snapshots
16
+ // DEV: So that when we are jumping to an old snapshot it
17
+ // wouldn't think we want to create new snapshots
22
18
if ( mode . jumping || mode . paused ) return ;
23
- const payload = snap . tree . getCopy ( ) ; // copy of current react fiber tree
19
+ const payload = snap . tree . getCopy ( ) ;
24
20
// console.log('payload', payload);
25
- window . postMessage ( { // send to window
21
+ window . postMessage ( {
26
22
action : 'recordSnap' ,
27
23
payload,
28
24
} ) ;
29
25
}
30
26
31
- function changeSetState ( component ) { // if invoked, change setState functionality so that it also updates our snapshot
32
- // console.log("what is component?", component);
27
+ function changeSetState ( component ) {
33
28
// check that setState hasn't been changed yet
34
- if ( component . setState . linkFiberChanged ) {
35
- // console.log("setState has already been changed for", component);
36
- return ;
37
- } ;
29
+ if ( component . setState . linkFiberChanged ) return ;
38
30
// make a copy of setState
39
31
const oldSetState = component . setState . bind ( component ) ;
40
32
// replace component's setState so developer doesn't change syntax
@@ -43,30 +35,29 @@ module.exports = (snap, mode) => {
43
35
// don't do anything if state is locked
44
36
// UNLESS we are currently jumping through time
45
37
if ( mode . locked && ! mode . jumping ) return ;
46
- // continue normal setState functionality, except add sending message (to chrome extension) middleware
38
+ // continue normal setState functionality, except add sending message middleware
47
39
oldSetState ( state , ( ) => {
48
- updateSnapShotTree ( ) ; // this doubles the actions in reactime for star wars app, also invokes changeSetState twice, also invokes changeSetState with Route and Characters
49
- sendSnapshot ( ) ; //runs once on page load, after event listener: message (line 145)
50
- callback . bind ( component ) ( ) ; // WHY DO WE NEED THIS ?
40
+ updateSnapShotTree ( ) ;
41
+ sendSnapshot ( ) ;
42
+ callback . bind ( component ) ( ) ;
51
43
} ) ;
52
44
} ;
53
- component . setState . linkFiberChanged = true ; // we changed setState.
45
+ component . setState . linkFiberChanged = true ;
54
46
}
55
47
56
- function changeUseState ( component ) { // if invoked, change useState dispatch functionality so that it also updates our snapshot
57
- //check that changeUseState hasn't been changed yet
48
+ function changeUseState ( component ) {
58
49
if ( component . queue . dispatch . linkFiberChanged ) return ;
59
50
// store the original dispatch function definition
60
51
const oldDispatch = component . queue . dispatch . bind ( component . queue ) ;
61
52
// redefine the dispatch function so we can inject our code
62
53
component . queue . dispatch = ( fiber , queue , action ) => {
63
- // don't do anything if state is locked, UNLESS we are currently jumping through time
54
+ // don't do anything if state is locked
64
55
if ( mode . locked && ! mode . jumping ) return ;
65
56
oldDispatch ( fiber , queue , action ) ;
66
- setTimeout ( ( ) => {
67
- updateSnapShotTree ( ) ;
68
- sendSnapshot ( ) ;
69
- } , 100 ) ;
57
+ // setTimeout(() => {
58
+ updateSnapShotTree ( ) ;
59
+ sendSnapshot ( ) ;
60
+ // }, 100);
70
61
} ;
71
62
component . queue . dispatch . linkFiberChanged = true ;
72
63
}
@@ -79,8 +70,10 @@ module.exports = (snap, mode) => {
79
70
let index = 0 ;
80
71
astHooks = Object . values ( astHooks ) ;
81
72
// while memoizedState is truthy, save the value to the object
82
- while ( memoizedState ) {
83
- changeUseState ( memoizedState ) ;
73
+ while ( memoizedState && memoizedState . queue ) { // prevents useEffect from crashing on load
74
+ if ( memoizedState . next . queue === null ) { // prevents double pushing snapshot updates
75
+ changeUseState ( memoizedState ) ;
76
+ }
84
77
// memoized[astHooks[index]] = memoizedState.memoizedState;
85
78
memoized [ astHooks [ index ] ] = memoizedState . memoizedState ;
86
79
// Reassign memoizedState to its next value
@@ -92,22 +85,21 @@ module.exports = (snap, mode) => {
92
85
}
93
86
94
87
function createTree ( currentFiber , tree = new Tree ( 'root' ) ) {
95
- // if there is no current fiber just return the new tree as-is
96
88
if ( ! currentFiber ) return tree ;
97
- // console.log("what is currentFiber", currentFiber);
89
+
98
90
const {
99
91
sibling,
100
92
stateNode,
101
93
child,
102
94
memoizedState,
103
95
elementType,
104
- } = currentFiber ; // extract properties of current fiber
96
+ } = currentFiber ;
105
97
106
- let childTree = tree ; // initialize child fiber tree as current fiber tree
98
+ let nextTree = tree ;
107
99
// check if stateful component
108
100
if ( stateNode && stateNode . state ) {
109
101
// add component to tree
110
- childTree = tree . appendChild ( stateNode ) ; // returns newly appended tree
102
+ nextTree = tree . appendChild ( stateNode ) ;
111
103
// change setState functionality
112
104
changeSetState ( stateNode ) ;
113
105
}
@@ -119,43 +111,34 @@ module.exports = (snap, mode) => {
119
111
// Create a traversed property and assign to the evaluated result of
120
112
// invoking traverseHooks with memoizedState
121
113
memoizedState . traversed = traverseHooks ( memoizedState ) ;
122
- childTree = tree . appendChild ( memoizedState ) ;
114
+ nextTree = tree . appendChild ( memoizedState ) ;
123
115
}
124
116
// iterate through siblings
125
117
createTree ( sibling , tree ) ;
126
118
// iterate through children
127
- createTree ( child , childTree ) ;
119
+ createTree ( child , nextTree ) ;
128
120
129
121
return tree ;
130
122
}
131
-
132
- // runs when page initially loads and on subsequent state changes
123
+ // runs when page initially loads
133
124
// but skips 1st hook click
134
125
function updateSnapShotTree ( ) {
135
- const { current } = fiberRoot ; // on initial page load, current - fiberNode is tag type HostRoot (entire fiber tree)
136
- console . log ( "current" , current ) ;
126
+ const { current } = fiberRoot ;
137
127
snap . tree = createTree ( current ) ;
138
128
}
139
129
140
- // RUNS ONCE, ON INITIAL PAGE LOAD ?
141
130
return container => {
142
- // on first page load, container is entire html hierarchy of top level div
143
- // _reactRootContainer is that invisible top level object which wraps the top level div
144
- // _reactRootContainer._internalRoot is an object with property .current which includes HostRoot fiberNode (entire fiber tree)
145
131
const {
146
132
_reactRootContainer : { _internalRoot } ,
147
133
_reactRootContainer,
148
134
} = container ;
149
- // only assign internal root if it actually exists
135
+ // only assign internal rootp if it actually exists
150
136
fiberRoot = _internalRoot || _reactRootContainer ;
151
137
152
138
updateSnapShotTree ( ) ;
153
139
// send the initial snapshot once the content script has started up
154
140
window . addEventListener ( 'message' , ( { data : { action } } ) => {
155
- if ( action === 'contentScriptStarted' ) { // runs once on initial page load
156
- // console.log("in window.addEL")
157
- sendSnapshot ( )
158
- } ;
141
+ if ( action === 'contentScriptStarted' ) sendSnapshot ( ) ;
159
142
} ) ;
160
143
} ;
161
144
} ;
0 commit comments