4
4
// links component state tree to library
5
5
// changes the setState method to also update our snapshot
6
6
const Tree = require ( './tree' ) ;
7
+ const astParser = require ( './astParser' ) ;
8
+ const { saveState } = require ( './masterState' ) ;
7
9
8
10
module . exports = ( snap , mode ) => {
9
11
let fiberRoot = null ;
12
+ let astHooks ;
10
13
11
14
function sendSnapshot ( ) {
12
15
// don't send messages while jumping or while paused
@@ -20,20 +23,15 @@ module.exports = (snap, mode) => {
20
23
} ) ;
21
24
}
22
25
23
- // DEV: This is how we know when a change has happened
24
- // (by injecting an event listener to every component's setState functionality).
25
- // Will need to create a separate one for useState components
26
26
function changeSetState ( component ) {
27
27
// check that setState hasn't been changed yet
28
28
if ( component . setState . linkFiberChanged ) return ;
29
-
30
29
// make a copy of setState
31
30
const oldSetState = component . setState . bind ( component ) ;
32
-
33
31
// replace component's setState so developer doesn't change syntax
34
32
// component.setState = newSetState.bind(component);
35
- component . setState = ( state , callback = ( ) => { } ) => {
36
- // dont do anything if state is locked
33
+ component . setState = ( state , callback = ( ) => { } ) => {
34
+ // don't do anything if state is locked
37
35
// UNLESS we are currently jumping through time
38
36
if ( mode . locked && ! mode . jumping ) return ;
39
37
// continue normal setState functionality, except add sending message middleware
@@ -46,26 +44,46 @@ module.exports = (snap, mode) => {
46
44
component . setState . linkFiberChanged = true ;
47
45
}
48
46
49
- // Helper function to
47
+ function changeUseState ( component ) {
48
+ if ( component . queue . dispatch . linkFiberChanged ) return ;
49
+ // store the original dispatch function definition
50
+ const oldDispatch = component . queue . dispatch . bind ( component . queue ) ;
51
+ // redefine the dispatch function so we can inject our code
52
+ component . queue . dispatch = ( fiber , queue , action ) => {
53
+ // don't do anything if state is locked
54
+ if ( mode . locked && ! mode . jumping ) return ;
55
+ //oldDispatch(fiber, queue, action);
56
+ setTimeout ( ( ) => {
57
+ oldDispatch ( fiber , queue , action ) ;
58
+ updateSnapShotTree ( ) ;
59
+ sendSnapshot ( ) ;
60
+ } , 100 ) ;
61
+ } ;
62
+ component . queue . dispatch . linkFiberChanged = true ;
63
+ }
50
64
51
65
// Helper function to traverse through the memoized state
52
66
function traverseHooks ( memoizedState ) {
53
67
// Declare variables and assigned to 0th index and an empty object, respectively
54
- let index = 0 ;
55
- const memoizedObj = { } ;
68
+ const memoized = { } ;
69
+ let index = 0 ;
70
+ astHooks = Object . values ( astHooks ) ;
56
71
// while memoizedState is truthy, save the value to the object
57
72
while ( memoizedState ) {
58
- // Increment the index by 1
59
- memoizedObj [ `state${ index += 1 } ` ] = memoizedState . memoizedState ;
73
+ changeUseState ( memoizedState ) ;
74
+ //memoized[astHooks[index]] = memoizedState.memoizedState;
75
+ memoized [ astHooks [ index ] ] = memoizedState . memoizedState ;
60
76
// Reassign memoizedState to its next value
61
77
memoizedState = memoizedState . next ;
78
+ // Increment the index by 2
79
+ index += 2 ;
62
80
}
63
- return memoizedObj ;
81
+ return memoized ;
64
82
}
65
83
66
84
function createTree ( currentFiber , tree = new Tree ( 'root' ) ) {
67
85
if ( ! currentFiber ) return tree ;
68
-
86
+
69
87
const {
70
88
sibling,
71
89
stateNode,
@@ -82,88 +100,43 @@ module.exports = (snap, mode) => {
82
100
changeSetState ( stateNode ) ;
83
101
}
84
102
// Check if the component uses hooks
85
- // TODO: Refactor the conditionals - think about the edge case where a stateful
86
- // component might have a key called 'baseState' in the state
87
- if ( memoizedState && memoizedState . hasOwnProperty ( 'baseState' ) ) {
88
- // console.log('The memoizedState is: ', memoizedState)
89
-
90
- const traversed = traverseHooks ( memoizedState ) ;
91
- nextTree = tree . appendChild ( traversed ) ;
103
+ if ( memoizedState && memoizedState . hasOwnProperty ( 'baseState' ) ) {
104
+ // Add a traversed property and initialize to the evaluated result
105
+ // of invoking traverseHooks, and reassign nextTree
106
+ memoizedState . traversed = traverseHooks ( memoizedState ) ;
107
+ nextTree = tree . appendChild ( memoizedState ) ;
92
108
}
93
-
94
109
// iterate through siblings
95
110
createTree ( sibling , tree ) ;
96
111
// iterate through children
97
112
createTree ( child , nextTree ) ;
98
113
99
114
return tree ;
100
115
}
101
-
116
+ // runs when page initially loads
117
+ // but skips 1st hook click
102
118
function updateSnapShotTree ( ) {
103
119
const { current } = fiberRoot ;
104
120
snap . tree = createTree ( current ) ;
105
121
}
106
- // return container => {
107
- // console.log('this is the container', container)
108
- // const {
109
- // _reactRootContainer: { _internalRoot },
110
- // _reactRootContainer,
111
- // } = container;
112
- // // only assign internal root if it actually exists
113
- // fiberRoot = _internalRoot || _reactRootContainer;
114
- // console.log('fiberRoot', fiberRoot);
115
- // updateSnapShotTree();
116
122
117
- // // send the initial snapshot once the content script has started up
118
- // window.addEventListener('message', ({ data: { action } }) => {
119
- // if (action === 'contentScriptStarted') sendSnapshot();
120
- // });
121
- // };
122
-
123
- return {
124
- _ ( container ) {
125
- const {
126
- _reactRootContainer : { _internalRoot } ,
127
- _reactRootContainer,
128
- } = container ;
129
- // only assign internal root if it actually exists
130
- fiberRoot = _internalRoot || _reactRootContainer ;
131
- updateSnapShotTree ( ) ;
132
- // send the initial snapshot once the content script has started up
133
- window . addEventListener ( 'message' , ( { data : { action } } ) => {
134
- if ( action === 'contentScriptStarted' ) sendSnapshot ( ) ;
135
- } ) ;
136
- } ,
137
- testUseState ( useState ) {
138
- return function ( initial ) {
139
- // running the original useState and storing its result (state and dispatch function)
140
- const toReturn = useState ( initial ) ;
141
- // storing the original dispatch function definition somewhere
142
- const oldDispatch = toReturn [ 1 ] ;
143
- // redefining the dispatch function so we can inject our code
144
- toReturn [ 1 ] = function ( newVal ) {
145
- oldDispatch ( newVal ) ;
146
- updateSnapShotTree ( ) ;
147
- sendSnapshot ( ) ;
148
- } ;
149
- return toReturn ;
150
- } ;
151
- } ,
152
- testUseReducer ( useReducer ) {
153
- return function ( reducer , initialState , init ) {
154
- // Declare a constant and initialize to the built-in useReducer method
155
- // Which returns an array with the state and dispatch
156
- const reduced = useReducer ( reducer , initialState , init ) ;
157
- // Save the dispatch method
158
- const oldDispatch = reduced [ 1 ] ;
159
- // reassign the dispatch method with the additional methods
160
- reduced [ 1 ] = function ( type ) {
161
- oldDispatch ( type ) ;
162
- updateSnapShotTree ( ) ;
163
- sendSnapshot ( ) ;
164
- }
165
- return reduced ;
166
- }
167
- } ,
168
- } ;
169
- } ;
123
+ return ( container , entryFile ) => {
124
+ const {
125
+ _reactRootContainer : { _internalRoot } ,
126
+ _reactRootContainer,
127
+ } = container ;
128
+ // only assign internal rootp if it actually exists
129
+ fiberRoot = _internalRoot || _reactRootContainer ;
130
+ // If hooks are implemented, traverse through the source code
131
+ // Save the getter/setter combo for timeJump
132
+ if ( entryFile ) {
133
+ astHooks = astParser ( entryFile ) ;
134
+ saveState ( astHooks ) ;
135
+ }
136
+ updateSnapShotTree ( ) ;
137
+ // send the initial snapshot once the content script has started up
138
+ window . addEventListener ( 'message' , ( { data : { action } } ) => {
139
+ if ( action === 'contentScriptStarted' ) sendSnapshot ( ) ;
140
+ } ) ;
141
+ }
142
+ } ;
0 commit comments