Skip to content

Commit 5fb3916

Browse files
committed
Added logic for rendering component context. Need additional logic to update Context when a state is update
1 parent 1ea1628 commit 5fb3916

File tree

5 files changed

+85
-25
lines changed

5 files changed

+85
-25
lines changed

src/app/components/StateRoute/ComponentMap/ComponentMap.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,8 @@ export default function ComponentMap({
216216

217217
const formatContext = (data) => {
218218
const contextFormat = [];
219-
// const nestedObj = [];
220219
for (const key in data) {
220+
// Suggestion: update the front end to display as a list if we have object
221221
contextFormat.push(<p className='statecontext'>{`${key}: ${data[key]}`}</p>);
222222
}
223223
return contextFormat;

src/backend/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111
import 'regenerator-runtime/runtime';
1212
import linkFiberStart from './linkFiber';
1313
import timeJumpStart from './timeJump';
14-
import { Snapshot, Mode, MsgData } from './types/backendTypes';
14+
import { Snapshot, Status, MsgData } from './types/backendTypes';
1515

1616
// * State snapshot object initialized here
1717
const snapShot: Snapshot = {
1818
tree: null,
1919
unfilteredTree: null,
2020
};
2121

22-
const mode: Mode = {
22+
const mode: Status = {
2323
jumping: false,
2424
paused: false,
2525
};

src/backend/linkFiber.ts

Lines changed: 79 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,42 @@ import {
1616
// tree
1717
Snapshot,
1818
// jump, pause
19-
Mode,
19+
Status,
2020
// array of state and component
2121
HookStates,
2222
// object with tree structure
2323
Fiber,
2424
} from './types/backendTypes';
25+
import {
26+
FunctionComponent,
27+
ClassComponent,
28+
IndeterminateComponent, // Before we know whether it is function or class
29+
HostRoot, // Root of a host tree. Could be nested inside another node.
30+
HostPortal, // A subtree. Could be an entry point to a different renderer.
31+
/**
32+
* Host Component: a type of component that represents a native DOM element in the browser environment, such as div, span, input, h1 etc.
33+
*/
34+
HostComponent, // has stateNode of html elements
35+
HostText,
36+
Fragment,
37+
Mode,
38+
ContextConsumer,
39+
ContextProvider,
40+
ForwardRef,
41+
Profiler,
42+
SuspenseComponent,
43+
MemoComponent,
44+
SimpleMemoComponent, // A higher order component where if the component renders the same result given the same props, react skips rendering the component and uses last rendered result. Has memoizedProps/memoizedState but no stateNode
45+
LazyComponent,
46+
IncompleteClassComponent,
47+
DehydratedFragment,
48+
SuspenseListComponent,
49+
FundamentalComponent,
50+
ScopeComponent,
51+
Block,
52+
OffscreenComponent,
53+
LegacyHiddenComponent,
54+
} from './types/backendTypes';
2555
// import function that creates a tree
2656
import Tree from './tree';
2757
// passes the data down to its components
@@ -54,7 +84,7 @@ let rtid = null;
5484
*
5585
* Middleware: Gets a copy of the current snap.tree and posts a recordSnap message to the window
5686
*/
57-
function sendSnapshot(snap: Snapshot, mode: Mode): void {
87+
function sendSnapshot(snap: Snapshot, mode: Status): void {
5888
// Don't send messages while jumping or while paused
5989
if (mode.jumping || mode.paused) return;
6090
// If there is no current tree creates a new one
@@ -87,7 +117,7 @@ function sendSnapshot(snap: Snapshot, mode: Mode): void {
87117
* Middleware: Updates snap object with latest snapshot, using @sendSnapshot
88118
*/
89119
// updating tree depending on current mode on the panel (pause, etc)
90-
function updateSnapShotTree(snap: Snapshot, mode: Mode): void {
120+
function updateSnapShotTree(snap: Snapshot, mode: Status): void {
91121
// this is the currently active root fiber(the mutable root of the tree)
92122
if (fiberRoot) {
93123
const { current } = fiberRoot;
@@ -138,6 +168,7 @@ function traverseHooks(memoizedState: any): HookStates {
138168
// This runs after every Fiber commit. It creates a new snapshot
139169
const exclude = new Set([
140170
'alternate',
171+
'basename',
141172
'baseQueue',
142173
'baseState',
143174
'child',
@@ -149,20 +180,25 @@ const exclude = new Set([
149180
'deps',
150181
'dependencies',
151182
'destroy',
183+
'dispatch',
184+
'location',
152185
'effects',
153186
'element',
154187
'elementType',
155188
'firstBaseUpdate',
156189
'firstEffect',
157190
'flags',
158191
'get key',
192+
'getState',
159193
'key',
160194
'lanes',
161195
'lastBaseUpdate',
162196
'lastEffect',
197+
'liftedStore',
163198
'navigator',
164199
'memoizedState',
165200
'mode',
201+
'navigationType',
166202
'next',
167203
'nextEffect',
168204
'pending',
@@ -172,12 +208,15 @@ const exclude = new Set([
172208
'Provider',
173209
'updateQueue',
174210
'ref',
211+
'replaceReducer',
175212
'responders',
176213
'return',
177214
'route',
178215
'routeContext',
179216
'shared',
180217
'sibling',
218+
'subscribe',
219+
'subscription',
181220
'stateNode',
182221
'tag',
183222
'type',
@@ -193,6 +232,7 @@ const exclude = new Set([
193232
'_store',
194233
'_threadCount',
195234
'$$typeof',
235+
'@@observable',
196236
]);
197237
// -----------------TRIMMING PASSED IN FIBER ROOT DATA--------------------------
198238
/**
@@ -204,27 +244,37 @@ const exclude = new Set([
204244
* @param depth - reactDevData is nested object. The value in reactDevData can be another object. Depth is use to keep track the depth during the unraveling of nested object
205245
* @returns reactimeData - the updated data object to send to front end of ReactTime
206246
*/
207-
function convertDataToString(reactDevData, reactimeData = {}, depth = 0) {
247+
function convertDataToString(reactDevData, reactimeData = {}, excludeSet?: any) {
248+
if (!excludeSet) excludeSet = exclude;
208249
for (const key in reactDevData) {
209-
// Skip keys that are in exclude list OR if there is no value at key
210-
if (exclude.has(key) || !reactDevData[key]) {
250+
// Skip keys that are in exclude set OR if there is no value at key
251+
// Falsy values such as 0, false, null are still valid value
252+
if (excludeSet.has(key) || reactDevData[key] === undefined) {
211253
continue;
212254
}
213255
// If value at key is a function, assign key with value 'function' to reactimeData object
214256
else if (typeof reactDevData[key] === 'function') {
215257
reactimeData[key] = 'function';
216-
}
217-
// If value at key is an object, recusive call convertDataToString to traverse through all keys and append to reactimeData object accodingly
218-
else if (typeof reactDevData[key] === 'object') {
219-
depth > 10
220-
? 'convertDataToString reached max depth'
221-
: convertDataToString(reactDevData[key], reactimeData, depth + 1);
222258
} else {
223259
reactimeData[key] = reactDevData[key];
224260
}
225261
}
226262
return reactimeData;
227263
}
264+
// ------------------------TRIMMING CONTEXT DATA--------------------------------
265+
function trimContextData(memoizedState, reactimeContextData = {}) {
266+
const exclude = new Set(['children', 'store', 'subscription']);
267+
while (memoizedState) {
268+
//Trim the current level of memoizedState data:
269+
const updateMemoizedState = convertDataToString(memoizedState?.memoizedState[0], {}, exclude);
270+
//Update Reactime data:
271+
Object.assign(reactimeContextData, updateMemoizedState);
272+
//Move on to the next level:
273+
memoizedState = memoizedState?.next;
274+
}
275+
276+
return reactimeContextData;
277+
}
228278
// -------------------------CREATE TREE TO SEND TO FRONT END--------------------
229279
/**
230280
* Every time a state change is made in the accompanying app, the extension creates a Tree “snapshot” of the current state, and adds it to the current “cache” of snapshots in the extension
@@ -273,8 +323,8 @@ function createTree(
273323
_debugHookTypes,
274324
});
275325

276-
// Tag === 5 signify this is a React Fragment. Each JSX component return a React fragment => The parent of a React Fragment could be a JSX component
277-
if (tag === 5) {
326+
// TODO: Understand this if statement
327+
if (tag === HostComponent) {
278328
try {
279329
// Ensure parent component has memoizedProps property
280330
if (
@@ -311,15 +361,24 @@ function createTree(
311361
} = {};
312362
let componentFound = false;
313363

364+
/**
365+
* In addition to React Component JSX from user input, there are other components that user would be using under the hood without needing to see it. For example, if Redux is used, a ContextProvider, called ReactRedux.Provider is created under the hood to manage the context store.
366+
* @variable filteredComponents is boolean value, used to filter out 'under-the-hood' components
367+
*/
368+
// const filteredComponents = tag != ContextProvider;
369+
const filteredComponents = true;
314370
// check to see if the parent component has any state/props
315-
if (memoizedProps && Object.keys(memoizedProps).length) {
371+
if (filteredComponents && memoizedProps && Object.keys(memoizedProps).length) {
316372
componentData.props = convertDataToString(memoizedProps);
317373
}
318374
// if the component uses the useContext hook, we want to grab the context object and add it to the componentData object for that fiber
319-
if (tag === 0 && _debugHookTypes && dependencies?.firstContext?.memoizedValue) {
320-
componentData.context = convertDataToString(dependencies.firstContext.memoizedValue);
321-
console.log('Linkfiber', { context: componentData.context });
375+
// if (tag === 0 && _debugHookTypes && dependencies?.firstContext?.memoizedValue) {
376+
// componentData.context = convertDataToString(dependencies.firstContext.memoizedValue);
377+
// }
378+
if ((tag === FunctionComponent || tag === ClassComponent) && memoizedState?.memoizedState) {
379+
componentData.context = trimContextData(memoizedState);
322380
}
381+
323382
// Check if node is a stateful class component
324383
if (stateNode && stateNode.state && (tag === 0 || tag === 1 || tag === 2)) {
325384
// Save component's state and setState() function to our record for future
@@ -369,6 +428,7 @@ function createTree(
369428
treeBaseDuration,
370429
};
371430
console.log('props', componentData.props);
431+
console.log('context', componentData.context);
372432
let newNode = null;
373433

374434
// We want to add this fiber node to the snapshot
@@ -458,7 +518,7 @@ interface DevTools {
458518
* @return a function to be invoked by index.js that initiates snapshot monitoring
459519
* linkFiber contains core module functionality, exported as an anonymous function.
460520
*/
461-
export default (snap: Snapshot, mode: Mode): (() => void) => {
521+
export default (snap: Snapshot, mode: Status): (() => void) => {
462522
// Checks for visiblity of document
463523
function onVisibilityChange() {
464524
// Hidden property = background tab/minimized window

src/backend/types/backendTypes.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ export interface Snapshot {
1414
}
1515

1616
/**
17-
* @type Mode - object that describes where we are
17+
* @type Status - object that describes where we are
1818
* @member jumping - whether we are jumping steps by
1919
* @member paused - true/false for whether pausing to see the state
2020
*/
21-
export interface Mode {
21+
export interface Status {
2222
jumping: boolean;
2323
paused: boolean;
2424
}

src/extension/background.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
324324

325325
// DUPLICATE SNAPSHOT CHECK
326326
const previousSnap =
327-
tabsObj[tabId].currLocation.stateSnapshot.children[0].componentData.actualDuration;
327+
tabsObj[tabId]?.currLocation?.stateSnapshot?.children[0]?.componentData?.actualDuration;
328328
const incomingSnap = request.payload.children[0].componentData.actualDuration;
329329
if (previousSnap === incomingSnap) break;
330330

0 commit comments

Comments
 (0)