Skip to content

Commit 3d8e98d

Browse files
committed
adding time-travel for setState components; setting up dispatch() function storage and retrieval for possible use in hooks time-travel
1 parent 69252d1 commit 3d8e98d

File tree

5 files changed

+93
-59
lines changed

5 files changed

+93
-59
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
const componentActionsRecord = {};
2+
const index = 0;
3+
4+
module.exports = {
5+
saveNew: (state, setterFunction) => {
6+
componentActionsRecord[index] = { state, setterFunction };
7+
},
8+
};

dev-reactime/linkFiber.js

Lines changed: 23 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
/* eslint-disable no-param-reassign */
4343

4444
const Tree = require('./tree');
45-
const { saveState, saveHooksComponent } = require('./masterState');
45+
const componentActionsRecord = require('./masterState');
4646

4747
module.exports = (snap, mode) => {
4848
let fiberRoot = null;
@@ -74,21 +74,22 @@ module.exports = (snap, mode) => {
7474
// prevents useEffect from crashing on load
7575
// if (memoizedState.next.queue === null) { // prevents double pushing snapshot updates
7676
if (memoizedState.memoizedState) {
77+
console.log('memoizedState in traverseHooks is:', memoizedState);
7778
hooksComponents.push({
78-
action: memoizedState.queue.dispatch,
79+
component: memoizedState.queue,
7980
state: memoizedState.memoizedState,
8081
});
8182
}
82-
//console.log('GOT STATE', memoizedState.memoizedState);
83+
// console.log('GOT STATE', memoizedState.memoizedState);
8384
memoizedState = memoizedState.next !== memoizedState
8485
? memoizedState.next : null;
8586
}
8687
return hooksComponents;
8788
}
8889

8990
// Carlos: This runs after EVERY Fiber commit. It creates a new snapshot,
90-
//
91-
function createTree(currentFiber, tree = new Tree('root'), hooksDispatch) {
91+
//
92+
function createTree(currentFiber, tree = new Tree('root')) {
9293
// Base case: child or sibling pointed to null
9394
if (!currentFiber) return tree;
9495

@@ -103,55 +104,30 @@ module.exports = (snap, mode) => {
103104
tag,
104105
} = currentFiber;
105106

106-
let nextTree = tree;
107-
108-
// Check if stateful component
107+
let index;
108+
// Check if node is a stateful component
109109
if (stateNode && stateNode.state && (tag === 0 || tag === 1)) {
110-
// Carlos: this is a Tree class object, which has an appendChild
111-
// method that adds stateNode to an array. We should refactor
112-
// into variable because there is always at most one element in the array
113-
tree.appendChild(stateNode.state, elementType.name); // Add component to tree
114-
Map(currentFiber, UUID) -> UUID
115-
tree.components[elementType.name] = stateNode.setState;
110+
// Save component's state and setState() function to our record for future
111+
// time-travel state changing. Add record index to snapshot so we can retrieve.
112+
index = componentActionsRecord.saveNew(stateNode.state, stateNode);
113+
tree.appendChild(stateNode.state, elementType.name, index); // Add component to tree
116114
} else {
117115
// grab stateless components here
118116
}
119117

120-
// Check if the component uses hooks
121-
if (
122-
memoizedState
123-
&& (tag === 0 || tag === 1 || tag === 10)
124-
) {
125-
126-
// Traverse through the currentFiber and extract the getters/setters
127-
// astHooks = astParser(elementType);
128-
// console.log('astHooks: ', astHooks);
129-
// saveState(astHooks);
130-
// Create a traversed property and assign to the evaluated result of
131-
// invoking traverseHooks with memoizedState
132-
// Carlos: try passing new state in updateSnapShotTree instead ****
133-
// memoizedState.traversed = traverseHooks(memoizedState);
118+
// Check if node is a hooks function
119+
if (memoizedState && (tag === 0 || tag === 1 || tag === 10)) {
134120
if (memoizedState.queue) {
135121
const hooksComponents = traverseHooks(memoizedState);
136122
hooksComponents.forEach(c => {
137123
if (elementType.name) {
138-
const hooksSnapshot = { [elementType.name]: { action: c.action, state: c.state } };
139-
if (hooksSnapshot) saveHooksComponent(hooksSnapshot);
140-
tree.appendChild({ state: c.state }, elementType.name ? elementType.name : 'nameless');
141-
// console.log('GOT STATE, HOOKS SNAPSHOT:', hooksSnapshot);
124+
index = componentActionsRecord.saveNew(c.state, c.component);
125+
tree.appendChild(c.state, elementType.name ? elementType.name : 'nameless', index);
142126
}
143127
});
144128
}
145-
146-
/*
147-
if (hooksDispatch) {
148-
memoizedState.component = { hooksDispatch };
149-
console.log('hooks dispatch args saved:', memoizedState);
150-
nextTree = tree.appendChild(memoizedState.hooksDispatch);
151-
} */
152129
}
153130

154-
155131
// Recurse on siblings
156132
createTree(sibling, tree);
157133
// Recurse on children
@@ -165,27 +141,24 @@ module.exports = (snap, mode) => {
165141
}
166142

167143
// ! BUG: skips 1st hook click
168-
function updateSnapShotTree(hooksDispatch) {
144+
function updateSnapShotTree() {
169145
/* let current;
170146
// If concurrent mode, grab current.child
171147
if (concurrent) {
172148
// we need a way to wait for current child to populate
173149
const promise = new Promise((resolve, reject) => {
174150
setTimeout(() => resolve(fiberRoot.current.child), 400);
175151
});
176-
177152
current = await promise;
178-
179153
current = fiberRoot.current.child;
180-
} else {
154+
} else {
181155
current = fiberRoot.current;
182156
} */
183-
const current = fiberRoot.current; // Carlos: get rid of concurrent mode for now
157+
const { current } = fiberRoot; // Carlos: get rid of concurrent mode for now
184158

185159
// console.log('FIBER COMMITTED, new fiber is:', util.inspect(current, false, 4));
186160
// fs.appendFile('fiberlog.txt', util.inspect(current, false, 10));
187-
snap.tree = createTree(current, undefined, hooksDispatch); // Carlos: pass new hooks state here?
188-
// console.log("GOT STATE, MOVING TO CHILD/SIBLING, tree:", snap.tree);
161+
snap.tree = createTree(current); // Carlos: pass new hooks state here?
189162
}
190163

191164
return async container => {
@@ -205,6 +178,9 @@ module.exports = (snap, mode) => {
205178
}
206179
const devTools = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
207180
const reactInstance = devTools ? devTools.renderers.get(1) : null;
181+
const overrideHookState = reactInstance ? reactInstance.overrideHookState : null;
182+
console.log('DEVTOOLS:', devTools);
183+
console.log('roots:', reactInstance.getCurrentFiber())
208184

209185
if (reactInstance && reactInstance.version) {
210186
devTools.onCommitFiberRoot = (function (original) {

dev-reactime/masterState.js

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,24 @@
1+
/* eslint-disable no-plusplus */
12
/* eslint-disable guard-for-in */
23
/* eslint-disable no-restricted-syntax */
3-
// Export two functions that either saves the AST state object into an array
4-
// or returns the array for use
5-
const masterState = [];
4+
5+
const componentActionsRecord = {};
6+
let index = 0;
7+
8+
module.exports = {
9+
saveNew: (state, component) => {
10+
componentActionsRecord[index] = { state, component };
11+
index++;
12+
return index - 1;
13+
},
14+
getRecordByIndex: inputIndex => componentActionsRecord[inputIndex],
15+
getComponentByIndex: inputIndex => (componentActionsRecord[inputIndex]
16+
? componentActionsRecord[inputIndex].component
17+
: undefined),
18+
};
19+
20+
21+
/* const masterState = [];
622
const hooksComponentsActions = {};
723
824
module.exports = {
@@ -13,9 +29,10 @@ module.exports = {
1329
return masterState;
1430
},
1531
returnState: () => masterState,
16-
saveHooksComponent: comp => {
17-
for (const key in comp) {
18-
hooksComponentsActions[key] = comp[key];
32+
saveHooksComponent: stateAndAction => {
33+
for (const elementName in stateAndAction) {
34+
hooksComponentsActions[elementName] = stateAndAction[elementName];
1935
}
2036
},
2137
};
38+
*/

dev-reactime/timeJump.js

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
/* eslint-disable no-param-reassign */
1313

14-
const { returnState } = require('./masterState');
14+
const componentActionsRecord = require('./masterState');
1515

1616
// Carlos: origin is latest snapshot, linking to the fiber,
1717
// so changes to origin change app
@@ -21,8 +21,39 @@ module.exports = (origin, mode) => {
2121

2222
function jump(target, originNode = origin.tree) {
2323
console.log('origin (link to current app state) in jump():', origin);
24+
console.log('target state is: ', target);
2425
// Set the state of the origin tree if the component is stateful
2526
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+
35+
if (component && component.setState) {
36+
console.log('time-travel calling setState', component);
37+
component.setState(prevState => {
38+
Object.keys(prevState).forEach(key => {
39+
if (target.state[key] === undefined) {
40+
target.state[key] = undefined;
41+
}
42+
});
43+
return target.state;
44+
// Iterate through new children after state has been set
45+
}, () => 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);
50+
target.children.forEach(child => jump(child));
51+
} else {
52+
console.log('time-travel did not call setState nor dispatch', component);
53+
target.children.forEach(child => jump(child));
54+
}
55+
56+
/*
2657
if (originNode.component.setState) {
2758
console.log('stateful component jump, originNode: ', originNode.component);
2859
console.log('new target is:', target);
@@ -59,6 +90,7 @@ module.exports = (origin, mode) => {
5990
index += 2;
6091
}
6192
}
93+
*/
6294
}
6395

6496
return target => {

dev-reactime/tree.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,23 @@ function scrubUnserializableMembers(tree) {
1212

1313
// this is the current snapshot that is being sent to the snapshots array.
1414
class Tree {
15-
constructor(state, name = 'nameless') {
15+
constructor(state, name = 'nameless', index) {
1616
this.state = state === 'root' ? 'root' : JSON.parse(JSON.stringify(state));
1717
this.name = name;
18+
this.index = index;
1819
this.children = [];
1920
}
2021

21-
appendChild(state, name) {
22-
const child = new Tree(state, name);
22+
appendChild(state, name, index) {
23+
const child = new Tree(state, name, index);
2324
this.children.push(child);
2425
}
2526

2627
cleanTreeCopy() {
27-
const copy = new Tree(this.state, this.name);
28+
const copy = new Tree(this.state, this.name, this.index);
2829
let newChild;
2930
copy.children = this.children.map(child => {
30-
newChild = new Tree(child.state, child.name);
31+
newChild = new Tree(child.state, child.name, child.index);
3132
newChild.children = child.children;
3233
return scrubUnserializableMembers(newChild);
3334
});

0 commit comments

Comments
 (0)