Skip to content

Commit 85d09ec

Browse files
committed
commiting changes
2 parents c685cd5 + 42050d8 commit 85d09ec

19 files changed

+279
-127
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ coverage
88
src/extension/build.zip
99
src/extension/build.crx
1010
src/extension/build/key.pem
11+
package/__tests__

package-lock.json

Lines changed: 45 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "reacttime-extension",
2+
"name": "reactime",
33
"description": "build web extension bundle.js",
44
"scripts": {
55
"build": "webpack --mode production",
@@ -26,7 +26,7 @@
2626
"David Chai",
2727
"Josh Kim",
2828
"Ruthba Anam",
29-
"Ryan Dang",
29+
"Ryan Dang",
3030
"Sierra Swaby",
3131
"Yujin Kang"
3232
],
@@ -59,6 +59,8 @@
5959
"webpack-cli": "^3.3.6"
6060
},
6161
"dependencies": {
62+
"acorn": "^7.1.0",
63+
"acorn-jsx": "^5.0.2",
6264
"d3": "^3.5.17",
6365
"immer": "^3.2.0",
6466
"jsondiffpatch": "^0.3.11",

package/astParser.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const acorn = require('acorn');
2+
const jsx = require('acorn-jsx');
3+
const JSXParser = acorn.Parser.extend(jsx());
4+
5+
// Helper function to recursively traverse through the user's codebase
6+
// INSERT HERE
7+
8+
module.exports = file => {
9+
// Initialize empty object to store the setters and getter
10+
const hookState = {};
11+
const ast = JSXParser.parse(file).body;
12+
// Iterate through AST of every function declaration
13+
// Check within each function declaration if there are hook declarations
14+
ast.forEach(func => {
15+
const { body } = func.body;
16+
const statements = [];
17+
// Traverse through the function's funcDecs and Expression Statements
18+
body.forEach(program => {
19+
if (program.type === 'VariableDeclaration') {
20+
program.declarations.forEach(dec => {
21+
statements.push(dec.id.name);
22+
});
23+
}
24+
});
25+
// Iterate through the array and determine getter/setters based on pattern
26+
for (let i = 0; i < statements.length; i += 1) {
27+
if (statements[i].match(/_use/)) {
28+
hookState[statements[i]] = statements[i + 2];
29+
}
30+
}
31+
});
32+
// Return the object with setters and getters
33+
return hookState;
34+
};

package/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ window.addEventListener('message', ({ data: { action, payload } }) => {
2525
}
2626
});
2727

28-
module.exports = linkFiber;
28+
module.exports = linkFiber;

package/linkFiber.js

Lines changed: 59 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44
// links component state tree to library
55
// changes the setState method to also update our snapshot
66
const Tree = require('./tree');
7+
const astParser = require('./astParser');
8+
const { saveState } = require('./masterState');
79

810
module.exports = (snap, mode) => {
911
let fiberRoot = null;
12+
let astHooks;
1013

1114
function sendSnapshot() {
1215
// don't send messages while jumping or while paused
@@ -20,20 +23,15 @@ module.exports = (snap, mode) => {
2023
});
2124
}
2225

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
2626
function changeSetState(component) {
2727
// check that setState hasn't been changed yet
2828
if (component.setState.linkFiberChanged) return;
29-
3029
// make a copy of setState
3130
const oldSetState = component.setState.bind(component);
32-
3331
// replace component's setState so developer doesn't change syntax
3432
// 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
3735
// UNLESS we are currently jumping through time
3836
if (mode.locked && !mode.jumping) return;
3937
// continue normal setState functionality, except add sending message middleware
@@ -46,26 +44,46 @@ module.exports = (snap, mode) => {
4644
component.setState.linkFiberChanged = true;
4745
}
4846

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+
}
5064

5165
// Helper function to traverse through the memoized state
5266
function traverseHooks(memoizedState) {
5367
// 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);
5671
// while memoizedState is truthy, save the value to the object
5772
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;
6076
// Reassign memoizedState to its next value
6177
memoizedState = memoizedState.next;
78+
// Increment the index by 2
79+
index += 2;
6280
}
63-
return memoizedObj;
81+
return memoized;
6482
}
6583

6684
function createTree(currentFiber, tree = new Tree('root')) {
6785
if (!currentFiber) return tree;
68-
86+
6987
const {
7088
sibling,
7189
stateNode,
@@ -82,88 +100,43 @@ module.exports = (snap, mode) => {
82100
changeSetState(stateNode);
83101
}
84102
// 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);
92108
}
93-
94109
// iterate through siblings
95110
createTree(sibling, tree);
96111
// iterate through children
97112
createTree(child, nextTree);
98113

99114
return tree;
100115
}
101-
116+
// runs when page initially loads
117+
// but skips 1st hook click
102118
function updateSnapShotTree() {
103119
const { current } = fiberRoot;
104120
snap.tree = createTree(current);
105121
}
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();
116122

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

Comments
 (0)