Skip to content

Commit 1e7df09

Browse files
committed
Merge branch 'dev' of https://github.com/reactrewind/react-rewind into readme
2 parents 65fb501 + a54e6da commit 1e7df09

File tree

7 files changed

+62
-61
lines changed

7 files changed

+62
-61
lines changed

package.json

+1-3
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
"eslint-config-airbnb": "^17.1.0",
2727
"eslint-plugin-jsx-a11y": "^6.2.1",
2828
"esprima": "^4.0.1",
29-
"estraverse": "^4.2.0",
30-
"lodash": "^4.17.11",
31-
"lodash.clonedeep": "^4.5.0"
29+
"estraverse": "^4.2.0"
3230
}
3331
}

src/app/components/App.jsx

+24-15
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,11 @@ class App extends Component {
7171
// adds listener to the effects that are gonna be sent from
7272
// our edited useReducer from the 'react' library.
7373
chrome.runtime.onConnect.addListener((port) => {
74-
if (port.name !== 'injected-app') return;
74+
// if our port is already open with the extension script,
75+
// we don't want to change this.portToExtension no more. We want
76+
// to keep every instance of the App associated with the specific
77+
// extension script that can communicated with the injected timeTravel.
78+
if (port.name !== 'injected-app' || this.portToExtension) return;
7579

7680
this.portToExtension = port;
7781

@@ -90,11 +94,10 @@ class App extends Component {
9094
// search field
9195
const { searchField } = this.state;
9296
const newDataActionType = newData.action.type.toLowerCase();
93-
94-
// get the date everytime an action fires and add it to state
9597

9698
const eventTime = Date.now();
97-
99+
100+
// get the date everytime an action fires and add it to state
98101
if (newDataActionType.includes(searchField.toLowerCase())) {
99102
this.setState(state => ({
100103
data: [...state.data, newData],
@@ -140,18 +143,18 @@ class App extends Component {
140143
}
141144

142145
setIsRecording() {
143-
// This variable will prevent the app from refreshing when we refresh
144-
// the userpage.
145-
this.justStartedRecording = true;
146-
const { isRecording, hasInjectedScript } = this.state;
146+
const { isRecording } = this.state;
147147
this.setState(state => ({
148148
isRecording: !state.isRecording,
149149
}));
150150

151151
// if we are hitting the pause or re-starting the record session
152-
if (isRecording || hasInjectedScript) return;
152+
if (isRecording || this.hasInjectedScript) return;
153153

154-
this.setState({ hasInjectedScript: true });
154+
// This variable will prevent the app from refreshing when we refresh
155+
// the userpage.
156+
this.justStartedRecording = true;
157+
this.hasInjectedScript = true;
155158

156159
// we query the active window so we can send it to the background script
157160
// so it knows on which URL to run our devtool.
@@ -167,11 +170,13 @@ class App extends Component {
167170
}
168171

169172
actionInPlay() {
170-
const { data, isPlayingIndex, isPlaying } = this.state;
173+
const { data, isPlayingIndex } = this.state;
171174

172175
setTimeout(() => {
173176
this.toTheFuture();
174-
if (isPlaying && isPlayingIndex + 1 < data.length - 1) {
177+
// We CANT deconstruct isPlaying because we want it to be the value
178+
// when this function gets executed - 1000s later.
179+
if (this.state.isPlaying && isPlayingIndex + 1 < data.length - 1) {
175180
this.actionInPlay();
176181
} else {
177182
this.setState({ isPlaying: false });
@@ -260,6 +265,7 @@ class App extends Component {
260265
if (isPlayingIndex === 0) return;
261266

262267
if (!this.portToExtension) return console.error('No connection on stored port.');
268+
263269
this.portToExtension.postMessage({
264270
type: 'TIMETRAVEL',
265271
direction: 'backwards',
@@ -278,11 +284,13 @@ class App extends Component {
278284

279285
resetApp() {
280286
if (this.justStartedRecording) {
281-
console.log('not reseting...');
282-
this.justStartedRecording = false;
287+
// hacky: some pages will fire update twice on the background script
288+
setTimeout(() => this.justStartedRecording = false, 50);
283289
return;
284290
}
285-
console.log('reseting...');
291+
292+
this.justStartedRecording = false;
293+
this.hasInjectedScript = false;
286294
this.setState({
287295
data: [],
288296
searchField: '',
@@ -294,6 +302,7 @@ class App extends Component {
294302
action: {},
295303
state: {},
296304
prevState: {},
305+
eventTimes: [],
297306
});
298307
}
299308

src/browser/chrome/background.js

+25-22
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,38 @@ const parseAndGenerate = require('./scripts/parser');
22
const injectBundleStr = require('./scripts/inject_bundle');
33

44
let ports = [];
5-
let interceptedUrl = '';
65
let reqIndex = 0;
6+
const interceptedURLs = {};
77

88
chrome.tabs.onUpdated.addListener((id, info, tab) => {
99
if (tab.status !== 'complete' || tab.url.startsWith('chrome')) return;
10-
10+
console.log('refresh completed on: ', tab.url);
1111
// active page action button and inject extension.js
1212
chrome.pageAction.show(tab.id);
1313
chrome.tabs.executeScript(null, {
1414
file: 'extension.js',
1515
runAt: 'document_end',
1616
});
1717

18-
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
19-
interceptedUrl = '';
18+
if (interceptedURLs.hasOwnProperty(tab.url)) {
19+
delete interceptedURLs[tab.url];
2020
reqIndex = 0;
21-
notifyPorts(
22-
{ action: 'refresh_devtool', tabId: tabs[0].id },
23-
'devtools',
24-
);
25-
});
21+
}
22+
23+
notifyPorts(
24+
{ action: 'refresh_devtool', tabId: tab.id },
25+
'devtools',
26+
);
2627
});
2728

2829
function handleRequest(request) {
2930
// TODO: filter the request from the webRequest call.
30-
if (!interceptedUrl.startsWith(request.initiator)) return { cancel: false };
31+
// We check wether or not the URL should have its requests intercepted
32+
let shouldInterceptUrl = false;
33+
Object.keys(interceptedURLs).forEach((url) => {
34+
if (url.startsWith(request.initiator)) shouldInterceptUrl = true;
35+
});
36+
if (!shouldInterceptUrl) return { cancel: false };
3137

3238
if (request.type === 'script' && !request.url.startsWith('chrome')
3339
&& request.frameId === 0 && ((request.url.slice(-3) === '.js')
@@ -57,18 +63,15 @@ chrome.runtime.onConnect.addListener((port) => {
5763
if (ports) ports.push(port);
5864

5965
port.onMessage.addListener((msg) => {
60-
if (msg.turnOnDevtool) {
61-
interceptedUrl = msg.url;
62-
addScriptInterception();
63-
64-
// after activating our interception script, we refresh the active tab
65-
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
66-
chrome.tabs.update(tabs[0].id, { url: tabs[0].url });
67-
});
68-
69-
} else {
70-
console.log('Got a msg not turnOnDevtool: ', msg);
71-
}
66+
if (!msg.turnOnDevtool) return;
67+
console.log('got turn on: ', msg);
68+
interceptedURLs[msg.url] = true;
69+
addScriptInterception();
70+
71+
// after activating our interception script, we refresh the active tab
72+
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
73+
chrome.tabs.update(tabs[0].id, { url: tabs[0].url });
74+
});
7275
});
7376
});
7477

src/browser/chrome/extension.js

+3-13
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,9 @@
99
window.postMessage(msg);
1010
});
1111

12-
port.onDisconnect.addListener(() => console.log('Disconecting...'));
13-
1412
window.addEventListener('message', (msg) => {
15-
// TODO: fix comments. Are we gonna receive msgs from reactDOM here??
16-
// When our injected scripts post messages (both from the 'react'
17-
// and 'react-dom'), we receive it here and send it to our app loaded
18-
// on the DevTool. If storage.isAppTurnedOff is false, it means that
19-
// the user started the application, but stopped recording. So even
20-
// though our injected scripts keep posting messages, we don't want to
21-
// send them over to the App anymore.
22-
chrome.storage.sync.get(['isAppTurnedOn'], (status) => {
23-
// if (!status.isAppTurnedOn) return;
24-
if (msg.data.type === 'DISPATCH') port.postMessage(msg.data.data);
25-
});
13+
// When our injected scripts post messages (from useRedute in 'react'),
14+
// we receive it here and send it to our app loaded on the DevTool.
15+
if (msg.data.type === 'DISPATCH') port.postMessage(msg.data.data);
2616
});
2717
}());

src/browser/chrome/manifest.json

+1-4
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,9 @@
2121
"tabs",
2222
"storage",
2323
"webRequest",
24-
"webRequestBlocking",
25-
"webNavigation"
24+
"webRequestBlocking"
2625
],
2726
"web_accessible_resources": [
28-
"scripts/linked_list.js",
29-
"scripts/time_travel.js",
3027
"scripts/deepclone_bundle.js"
3128
],
3229
"devtools_page": "devtools.html"

src/browser/chrome/page_action.html

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
</head>
99
<body>
1010
Page Action
11-
<button id="color_btn">CHANGE COLOR</button>
11+
<a href="http://www.google.com">Test - goto google</a>
12+
<button id="color_btn">CHANGE COLOR!</button>
1213
<script src="page_action.js"></script>
1314
</body>
1415
</html>

src/browser/chrome/scripts/parser.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,16 @@ function commitAllHostEffectsReplacement() {
107107
// method names
108108
const USEREDUCER = 'useReducer';
109109
const COMMITALLHOSTEFFECTS = 'commitAllHostEffects';
110+
110111
// library key inside of bundle
111112
const reactLibraryPath = './node_modules/react/cjs/react.development.js';
112113
const reactDOMLibraryPath = './node_modules/react-dom/cjs/react-dom.development.js';
114+
113115
// get replacer method
114116
let injectableUseReducer = esprima.parseScript(useReducerReplacement.toString());
115-
116-
let injectableCommitAllHostEffects = esprima.parseScript(commitAllHostEffectsReplacement.toString());
117+
let injectableCommitAllHostEffects = esprima.parseScript(
118+
commitAllHostEffectsReplacement.toString(),
119+
);
117120

118121
// traverse ast to find method and replace body with our node's body
119122
function traverseTree(replacementNode, functionName, ast) {
@@ -136,7 +139,7 @@ function traverseBundledTree(replacementNode, functionName, ast, library) {
136139
if (node.key && node.key.value === library) {
137140
if (node.value.body.body[1].type === 'ExpressionStatement') {
138141
if (node.value.body.body[1].expression.callee.name === 'eval') {
139-
// create new ast
142+
// create new ast
140143
const reactLib = esprima.parseScript(node.value.body.body[1].expression.arguments[0].value);
141144
estraverse.traverse(reactLib, {
142145
enter(libNode) {

0 commit comments

Comments
 (0)