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,34 +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
-
61
- // not sure why we need the bind, seems to work without it
62
- // const oldDispatch = component.queue.dispatch.bind(component.queue);
63
- const oldDispatch = component . queue . dispatch ;
64
-
51
+ const oldDispatch = component . queue . dispatch . bind ( component . queue ) ;
65
52
// redefine the dispatch function so we can inject our code
66
53
component . queue . dispatch = ( fiber , queue , action ) => {
67
- // don't do anything if state is locked, UNLESS we are currently jumping through time
54
+ // don't do anything if state is locked
68
55
if ( mode . locked && ! mode . jumping ) return ;
69
- oldDispatch ( fiber , queue , action ) ; // hooks sees this and thinks its a side effect, that's why it's throwing an error
70
- // setTimeout(() => {
71
- updateSnapShotTree ( ) ;
72
- sendSnapshot ( ) ;
73
- // }, 100);
56
+ oldDispatch ( fiber , queue , action ) ;
57
+ setTimeout ( ( ) => {
58
+ updateSnapShotTree ( ) ;
59
+ sendSnapshot ( ) ;
60
+ } , 100 ) ;
74
61
} ;
75
62
component . queue . dispatch . linkFiberChanged = true ;
76
63
}
@@ -83,13 +70,8 @@ module.exports = (snap, mode) => {
83
70
let index = 0 ;
84
71
astHooks = Object . values ( astHooks ) ;
85
72
// while memoizedState is truthy, save the value to the object
86
- while ( memoizedState && memoizedState . queue !== null ) {
87
- // we only want to changeUseState (which updates and sends the snapshot)
88
- // on the last item in the memoizedState chain. This makes sure it doesn't double-push
89
- // values to the timeline.
90
- if ( astHooks [ index + 2 ] === undefined ) {
91
- changeUseState ( memoizedState ) ;
92
- }
73
+ while ( memoizedState && memoizedState . queue ) { // prevents useEffect from crashing on load
74
+ changeUseState ( memoizedState ) ;
93
75
// memoized[astHooks[index]] = memoizedState.memoizedState;
94
76
memoized [ astHooks [ index ] ] = memoizedState . memoizedState ;
95
77
// Reassign memoizedState to its next value
@@ -101,72 +83,60 @@ module.exports = (snap, mode) => {
101
83
}
102
84
103
85
function createTree ( currentFiber , tree = new Tree ( 'root' ) ) {
104
- // if there is no current fiber just return the new tree as-is
105
86
if ( ! currentFiber ) return tree ;
106
- // console.log("what is currentFiber", currentFiber);
87
+
107
88
const {
108
89
sibling,
109
90
stateNode,
110
91
child,
111
92
memoizedState,
112
93
elementType,
113
- } = currentFiber ; // extract properties of current fiber
94
+ } = currentFiber ;
114
95
115
- let childTree = tree ; // initialize child fiber tree as current fiber tree
96
+ let nextTree = tree ;
116
97
// check if stateful component
117
98
if ( stateNode && stateNode . state ) {
118
99
// add component to tree
119
- childTree = tree . appendChild ( stateNode ) ; // returns newly appended tree
100
+ nextTree = tree . appendChild ( stateNode ) ;
120
101
// change setState functionality
121
102
changeSetState ( stateNode ) ;
122
103
}
123
104
// Check if the component uses hooks
124
-
125
105
if ( memoizedState && Object . hasOwnProperty . call ( memoizedState , 'baseState' ) ) {
126
106
// Traverse through the currentFiber and extract the getters/setters
127
107
astHooks = astParser ( elementType ) ;
128
108
saveState ( astHooks ) ;
129
109
// Create a traversed property and assign to the evaluated result of
130
110
// invoking traverseHooks with memoizedState
131
111
memoizedState . traversed = traverseHooks ( memoizedState ) ;
132
- childTree = tree . appendChild ( memoizedState ) ;
112
+ nextTree = tree . appendChild ( memoizedState ) ;
133
113
}
134
114
// iterate through siblings
135
115
createTree ( sibling , tree ) ;
136
116
// iterate through children
137
- createTree ( child , childTree ) ;
117
+ createTree ( child , nextTree ) ;
138
118
139
119
return tree ;
140
120
}
141
-
142
- // runs when page initially loads and on subsequent state changes
121
+ // runs when page initially loads
143
122
// but skips 1st hook click
144
123
function updateSnapShotTree ( ) {
145
- const { current } = fiberRoot ; // on initial page load, current - fiberNode is tag type HostRoot (entire fiber tree)
146
- console . log ( 'current' , current ) ;
124
+ const { current } = fiberRoot ;
147
125
snap . tree = createTree ( current ) ;
148
126
}
149
127
150
- // RUNS ONCE, ON INITIAL PAGE LOAD ?
151
128
return container => {
152
- // on first page load, container is entire html hierarchy of top level div
153
- // _reactRootContainer is that invisible top level object which wraps the top level div
154
- // _reactRootContainer._internalRoot is an object with property .current which includes HostRoot fiberNode (entire fiber tree)
155
129
const {
156
130
_reactRootContainer : { _internalRoot } ,
157
131
_reactRootContainer,
158
132
} = container ;
159
- // only assign internal root if it actually exists
133
+ // only assign internal rootp if it actually exists
160
134
fiberRoot = _internalRoot || _reactRootContainer ;
161
135
162
136
updateSnapShotTree ( ) ;
163
137
// send the initial snapshot once the content script has started up
164
138
window . addEventListener ( 'message' , ( { data : { action } } ) => {
165
- if ( action === 'contentScriptStarted' ) { // runs once on initial page load
166
- // console.log("in window.addEL")
167
- console . log ( 'page running' ) ;
168
- sendSnapshot ( ) ;
169
- }
139
+ if ( action === 'contentScriptStarted' ) sendSnapshot ( ) ;
170
140
} ) ;
171
141
} ;
172
142
} ;
0 commit comments