Skip to content

Commit 72bdf0a

Browse files
committed
pull master
2 parents 0842afd + 7a59cf2 commit 72bdf0a

File tree

9 files changed

+180
-141
lines changed

9 files changed

+180
-141
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ src/extension/build.crx
1010
src/extension/build.pem
1111
bower_components
1212
sandboxes/manual-tests/NextJS/.next
13+
.vscode

dev-reactime/linkFiber.js

Lines changed: 71 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -44,37 +44,18 @@
4444
/* eslint-disable no-use-before-define */
4545
/* eslint-disable no-param-reassign */
4646

47-
<<<<<<< HEAD
48-
const { Tree, UnfilteredTreeNode } = require('./tree');
49-
const astParser = require('./astParser');
50-
const { saveState } = require('./masterState');
51-
// import * as reactWorkTags from './reactWorkTags';
52-
=======
5347
const Tree = require('./tree');
5448
const componentActionsRecord = require('./masterState');
55-
>>>>>>> 8e774670f36699322d70300c6382bcdcc7b349e0
5649

5750
module.exports = (snap, mode) => {
5851
let fiberRoot = null;
59-
let astHooks;
60-
let concurrent = false; // flag to check if we are in concurrent mode
61-
const reactWorkTags = [
62-
'FunctionComponent',
63-
'ClassComponent',
64-
'IndeterminateComponent',
65-
'HostRoot', // Root of a host tree. Could be nested inside another node.
66-
'HostPortal', // A subtree. Could be an entry point to a different renderer.
67-
'HostComponent',
68-
'HostText',
69-
];
70-
7152

7253
async function sendSnapshot() {
7354
// Don't send messages while jumping or while paused
7455
if (mode.jumping || mode.paused) return;
75-
// console.log('PAYLOAD: before cleaning', snap.tree);
56+
console.log('PAYLOAD: before cleaning', snap.tree);
7657
const payload = snap.tree.cleanTreeCopy();// snap.tree.getCopy();
77-
// console.log('PAYLOAD: after cleaning', payload);
58+
console.log('PAYLOAD: after cleaning', payload);
7859
try {
7960
await window.postMessage({
8061
action: 'recordSnap',
@@ -88,14 +69,14 @@ module.exports = (snap, mode) => {
8869
// Carlos: Injects instrumentation to update our state tree every time
8970
// a hooks component changes state
9071
function traverseHooks(memoizedState) {
91-
const hooksComponents = [];
72+
const hooksStates = [];
9273
while (memoizedState && memoizedState.queue) {
9374
// Carlos: these two are legacy comments, we should look into them later
9475
// prevents useEffect from crashing on load
9576
// if (memoizedState.next.queue === null) { // prevents double pushing snapshot updates
9677
if (memoizedState.memoizedState) {
9778
console.log('memoizedState in traverseHooks is:', memoizedState);
98-
hooksComponents.push({
79+
hooksStates.push({
9980
component: memoizedState.queue,
10081
state: memoizedState.memoizedState,
10182
});
@@ -104,14 +85,15 @@ module.exports = (snap, mode) => {
10485
memoizedState = memoizedState.next !== memoizedState
10586
? memoizedState.next : null;
10687
}
107-
return hooksComponents;
88+
return hooksStates;
10889
}
10990

11091
// Carlos: This runs after EVERY Fiber commit. It creates a new snapshot,
11192
//
11293
function createTree(currentFiber, tree = new Tree('root')) {
11394
// Base case: child or sibling pointed to null
114-
if (!currentFiber) return tree;
95+
if (!currentFiber) return null;
96+
if (!tree) return tree;
11597

11698
// These have the newest state. We update state and then
11799
// called updateSnapshotTree()
@@ -122,40 +104,81 @@ module.exports = (snap, mode) => {
122104
memoizedState,
123105
elementType,
124106
tag,
107+
actualDuration,
108+
actualStartTime,
109+
selfBaseDuration,
110+
treeBaseDuration,
125111
} = currentFiber;
126112

127-
let index;
128-
// Check if node is a stateful component
113+
let newState = null;
114+
let componentData = {};
115+
let componentFound = false;
116+
117+
// Check if node is a stateful setState component
129118
if (stateNode && stateNode.state && (tag === 0 || tag === 1)) {
130119
// Save component's state and setState() function to our record for future
131120
// time-travel state changing. Add record index to snapshot so we can retrieve.
132-
index = componentActionsRecord.saveNew(stateNode.state, stateNode);
133-
tree.appendChild(stateNode.state, elementType.name, index); // Add component to tree
134-
} else {
135-
// grab stateless components here
121+
componentData.index = componentActionsRecord.saveNew(stateNode.state, stateNode);
122+
newState.state = stateNode.state;
123+
componentFound = true;
136124
}
137125

138-
// Check if node is a hooks function
126+
// Check if node is a hooks useState function
127+
let hooksIndex;
139128
if (memoizedState && (tag === 0 || tag === 1 || tag === 10)) {
140129
if (memoizedState.queue) {
141-
const hooksComponents = traverseHooks(memoizedState);
142-
hooksComponents.forEach(c => {
143-
if (elementType.name) {
144-
index = componentActionsRecord.saveNew(c.state, c.component);
145-
tree.appendChild(c.state, elementType.name ? elementType.name : 'nameless', index);
130+
// Hooks states are stored as a linked list using memoizedState.next,
131+
// so we must traverse through the list and get the states.
132+
// We then store them along with the corresponding memoizedState.queue,
133+
// which includes the dispatch() function we use to change their state.
134+
const hooksStates = traverseHooks(memoizedState);
135+
hooksStates.forEach(state => {
136+
hooksIndex = componentActionsRecord.saveNew(state.state, state.component);
137+
if (newState && newState.hooksState) {
138+
newState.hooksState.push([state.state, hooksIndex]);
139+
} else if (newState) {
140+
newState.hooksState = [[state.state, hooksIndex]];
141+
} else {
142+
newState = { hooksState: [[state.state, hooksIndex]] };
146143
}
144+
componentFound = true;
147145
});
148146
}
149147
}
150148

151-
// Recurse on siblings
152-
createTree(sibling, tree);
149+
// This grabs stateless components
150+
if (!componentFound && (tag === 0 || tag === 1)) {
151+
newState = 'stateless';
152+
}
153+
154+
// Adds performance metrics to the component data
155+
componentData = {
156+
...componentData,
157+
actualDuration,
158+
actualStartTime,
159+
selfBaseDuration,
160+
treeBaseDuration,
161+
};
162+
163+
if (componentFound) {
164+
tree.addChild(newState, elementType.name ? elementType.name : elementType, componentData);
165+
} else if (newState === 'stateless') {
166+
tree.addChild(newState, elementType.name ? elementType.name : elementType, componentData);
167+
}
168+
153169
// Recurse on children
154-
if (tree.children.length > 0) {
155-
createTree(child, tree.children[0]);
156-
} else {
157-
createTree(child, tree);
170+
if (child) {
171+
// If this node had state we appended to the children array,
172+
// so attach children to the newly appended child.
173+
// Otherwise, attach children to this same node.
174+
if (tree.children.length > 0) {
175+
createTree(child, tree.children[tree.children.length - 1]);
176+
} else {
177+
createTree(child, tree);
178+
}
158179
}
180+
// Recurse on siblings
181+
if (sibling) createTree(sibling, tree);
159182

160183
return parentNode;
161184
}
@@ -194,6 +217,7 @@ module.exports = (snap, mode) => {
194217

195218
// ! BUG: skips 1st hook click
196219
function updateSnapShotTree() {
220+
<<<<<<< HEAD
197221
/* let current;
198222
// If concurrent mode, grab current.child
199223
if (concurrent) {
@@ -218,28 +242,26 @@ module.exports = (snap, mode) => {
218242
// fs.appendFile('fiberlog.txt', util.inspect(current, false, 10));
219243
snap.tree = createTree(current); // Carlos: pass new hooks state here?
220244
>>>>>>> 8e774670f36699322d70300c6382bcdcc7b349e0
245+
=======
246+
const { current } = fiberRoot;
247+
snap.tree = createTree(current);
248+
>>>>>>> 7a59cf2ae4fd041fc21b23c396e02eae0fc01e84
221249
}
222250

223251
return async container => {
224252
// Point fiberRoot to FiberRootNode
225253
if (container._internalRoot) {
226254
fiberRoot = container._internalRoot;
227-
concurrent = true;
228255
} else {
229256
const {
230257
_reactRootContainer: { _internalRoot },
231258
_reactRootContainer,
232259
} = container;
233260
// Only assign internal root if it actually exists
234261
fiberRoot = _internalRoot || _reactRootContainer;
235-
// console.log('_reactRootContainer is:', _reactRootContainer);
236-
// console.log('linkFiber.js, fiberRoot:', fiberRoot);
237262
}
238263
const devTools = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
239264
const reactInstance = devTools ? devTools.renderers.get(1) : null;
240-
const overrideHookState = reactInstance ? reactInstance.overrideHookState : null;
241-
console.log('DEVTOOLS:', devTools);
242-
console.log('roots:', reactInstance.getCurrentFiber())
243265

244266
if (reactInstance && reactInstance.version) {
245267
devTools.onCommitFiberRoot = (function (original) {

dev-reactime/timeJump.js

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,11 @@ module.exports = (origin, mode) => {
2020
// Carlos: target is past state we are travelling to
2121

2222
function jump(target, originNode = origin.tree) {
23-
console.log('origin (link to current app state) in jump():', origin);
24-
console.log('target state is: ', target);
2523
// Set the state of the origin tree if the component is stateful
2624
if (!target) return;
27-
const component = componentActionsRecord.getComponentByIndex(target.index);
28-
if (component) {
29-
console.log('time-travel component is true');
30-
if (component.setState) {
31-
console.log('time-travel component setState is true');
32-
}
33-
}
34-
25+
if (target.state === 'stateless') target.children.forEach(child => jump(child));
26+
const component = componentActionsRecord.getComponentByIndex(target.componentData.index);
3527
if (component && component.setState) {
36-
console.log('time-travel calling setState', component);
3728
component.setState(prevState => {
3829
Object.keys(prevState).forEach(key => {
3930
if (target.state[key] === undefined) {
@@ -43,16 +34,24 @@ module.exports = (origin, mode) => {
4334
return target.state;
4435
// Iterate through new children after state has been set
4536
}, () => target.children.forEach(child => jump(child)));
46-
} else if (component && component.dispatch) {
47-
// ** not entering here
48-
console.log('time-travel calling dispatch', component);
49-
component.dispatch(target.state);
37+
}
38+
39+
if (target.state.hooksState) {
40+
target.state.hooksState.forEach(hooksState => {
41+
if (component && component.dispatch) {
42+
const hooksComponent = componentActionsRecord.getComponentByIndex(hooksState[1]);
43+
hooksComponent.dispatch(target.state.hooksState[0]);
44+
}
45+
});
5046
target.children.forEach(child => jump(child));
51-
} else {
52-
console.log('time-travel did not call setState nor dispatch', component);
47+
}
48+
49+
if ((!component || !component.state) && !target.state.hooksState) {
5350
target.children.forEach(child => jump(child));
5451
}
5552

53+
54+
5655
/*
5756
if (originNode.component.setState) {
5857
console.log('stateful component jump, originNode: ', originNode.component);

0 commit comments

Comments
 (0)