Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

move source range data into Sources #6146

Merged
merged 3 commits into from Jul 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1,4 +1,4 @@
import { useEffect, useRef } from "react";
import { useEffect, useRef, useState } from "react";
import { basename } from "path";
import { createStyles, Tabs } from "@mantine/core";
import Source from "src/components/composed/Debugger/Sources/Source";
Expand All @@ -9,6 +9,7 @@ import type {
Source as SourceType,
UnknownAddress
} from "src/components/composed/Debugger/utils";
import { getCurrentSourceRange } from "src/components/composed/Debugger/utils";

const useStyles = createStyles((theme, _params, _getRef) => ({
maxHeight: {
Expand Down Expand Up @@ -67,25 +68,32 @@ interface SourcesProps {
session: Session;
sessionUpdated: any;
sources: SourceType[];
currentSourceRange: SourceRange;
unknownAddresses: UnknownAddress[] | null;
currentSourceId: string | undefined;
setCurrentSourceId: (sourceId: string) => void;
scrollToLine: (arg: { sourceId: string; line: number }) => void;
}

function Sources({
sources,
session,
sessionUpdated,
currentSourceRange,
unknownAddresses,
currentSourceId,
setCurrentSourceId
setCurrentSourceId,
scrollToLine
}: SourcesProps): JSX.Element {
const { classes } = useStyles();
const currentSourceIdRef = useRef(currentSourceId);
currentSourceIdRef.current = currentSourceId;

const [currentSourceRange, setCurrentSourceRange] = useState<
SourceRange | { traceIndex: number; source: any }
>({
traceIndex: -1,
source: {}
});

// display the first source when currentSourceRange is `undefined`
useEffect(() => {
if (currentSourceId === undefined) {
Expand All @@ -94,7 +102,7 @@ function Sources({
}, [sources, currentSourceId, setCurrentSourceId]);

useEffect(() => {
const sessionSourceId = currentSourceRange.source.id;
const sessionSourceId = currentSourceRange.source!.id;
if (sessionSourceId !== currentSourceIdRef.current) {
setCurrentSourceId(sessionSourceId);
}
Expand All @@ -105,10 +113,37 @@ function Sources({
setCurrentSourceId
]);

useEffect(() => {
setCurrentSourceRange(getCurrentSourceRange(session));
// if the starting source is unknown, we may get `undefined` in the source
// range - in that case we'll initialize it manually from the stacktrace
if (!currentSourceRange.source?.id && !currentSourceId) {
const currentContractAddress = session.view(
session.selectors.stacktrace.current.report
)[0].address;
// when the contract is "unknown", the source id will be the address
// we need this if check so that no loop occurs when the value is falsy
if (currentContractAddress) {
setCurrentSourceId(currentContractAddress);
}
}
}, [session.view(session.selectors.trace.index)]);

const isSourceRange = (item: any): item is SourceRange => {
return item.source.id !== undefined;
};

useEffect(() => {
if (isSourceRange(currentSourceRange)) {
const { source, start } = currentSourceRange!;
scrollToLine({ sourceId: source.id, line: start.line });
}
}, [session!.view(session!.selectors.trace.index), currentSourceId]);

const unknownSourcesExist = unknownAddresses && unknownAddresses.length > 0;

let sourcesContent, unknownSourcesContent;
if (currentSourceId !== undefined) {
if (isSourceRange(currentSourceRange) && currentSourceId !== undefined) {
sourcesContent = sources.map((source: SourceType) => (
<Tabs.Panel
key={source.id}
Expand Down
22 changes: 13 additions & 9 deletions packages/dashboard/src/components/composed/Debugger/Stack.tsx
@@ -1,6 +1,6 @@
import { useEffect, useState } from "react";
import type { Session } from "src/components/composed/Debugger/utils";
import { createStyles, Flex } from "@mantine/core";
import { useDash } from "src/hooks";

const useStyles = createStyles(theme => ({
sectionHeader: {
Expand Down Expand Up @@ -40,25 +40,29 @@ const useStyles = createStyles(theme => ({
}
}));

type StackArgs = {
session: Session;
currentStep: string;
};

function Stack({ session, currentStep }: StackArgs): JSX.Element | null {
function Stack(): JSX.Element | null {
const { classes } = useStyles();
const {
state: {
debugger: { session }
}
} = useDash()!;

const [stackReport, setStackReport] = useState<JSX.Element[] | null>(null);
// when the debugger step changes, update variables
useEffect(() => {
async function getStack() {
const report = session.view(session.selectors.stacktrace.current.report);
// we don't render this component until session is defined
const report = session!.view(
session!.selectors.stacktrace.current.report
);
if (!report) return;
// we need to display this information in the reverse order
report.reverse();
setStackReport(report);
}
getStack();
}, [currentStep, session]);
}, [session!.view(session!.selectors.trace.index)]);

const output = stackReport
? stackReport.map((reportItem: any, index: number) => {
Expand Down
26 changes: 12 additions & 14 deletions packages/dashboard/src/components/composed/Debugger/Variables.tsx
@@ -1,8 +1,8 @@
import { useEffect, useState } from "react";
import type { Session } from "src/components/composed/Debugger/utils";
import * as CodecComponents from "@truffle/codec-components/react";
import "@truffle/codec-components/react-styles";
import { createStyles, Flex } from "@mantine/core";
import { useDash } from "src/hooks";

const useStyles = createStyles(theme => ({
sectionHeader: {
Expand Down Expand Up @@ -58,25 +58,23 @@ const useStyles = createStyles(theme => ({
}
}));

type VariablesArgs = {
session: Session;
currentStep: string;
};

function Variables({
session,
currentStep
}: VariablesArgs): JSX.Element | null {
function Variables(): JSX.Element | null {
const { classes } = useStyles();
const {
state: {
debugger: { session }
}
} = useDash()!;
const [variables, setVariables] = useState<any>(null);

// when the debugger step changes, update variables
useEffect(() => {
async function getVariables() {
const sections = session.view(
session.selectors.data.current.identifiers.sections
// we don't render this component until session is defined
const sections = session!.view(
session!.selectors.data.current.identifiers.sections
);
const vars = await session.variables();
const vars = await session!.variables();
if (!vars || Object.keys(vars).length === 0) return;

const variableValues: { [key: string]: any } = {};
Expand All @@ -97,7 +95,7 @@ function Variables({
}

getVariables();
}, [currentStep, session, classes.variablesTypes, classes.variablesSection]);
}, [session!.view(session!.selectors.trace.index)]);

const output = variables
? Object.keys(variables).map(sectionName => {
Expand Down
49 changes: 5 additions & 44 deletions packages/dashboard/src/components/composed/Debugger/index.tsx
Expand Up @@ -15,11 +15,7 @@ import {
SessionStatus
} from "src/components/composed/Debugger/utils";
import { useDash } from "src/hooks";
import { getCurrentSourceRange } from "src/components/composed/Debugger/utils";
import type {
BreakpointType,
SourceRange
} from "src/components/composed/Debugger/utils";
import type { BreakpointType } from "src/components/composed/Debugger/utils";
import { etherscanApiKeyName } from "src/utils/constants";

const useStyles = createStyles(theme => ({
Expand Down Expand Up @@ -109,29 +105,6 @@ function Debugger(): JSX.Element {
undefined
);

let currentSourceRange: SourceRange | Partial<SourceRange> = {
traceIndex: -1
};

let currentStep;
// wait until the debugger has been initialized and then get source info
if (session) {
currentSourceRange = getCurrentSourceRange(session);
// if the starting source is unknown, we may get `undefined` in the source
// range - in that case we'll initialize it manually from the stacktrace
if (!currentSourceRange.source?.id && !currentSourceId) {
const currentContractAddress = session.view(
session.selectors.stacktrace.current.report
)[0].address;
// when the contract is "unknown", the source id will be the address
// we need this if check so that no loop occurs when the value is falsy
if (currentContractAddress) {
setCurrentSourceId(currentContractAddress);
}
}
currentStep = session.view(session.selectors.trace.index);
}

const scrollToLine = ({
sourceId,
line
Expand Down Expand Up @@ -201,13 +174,6 @@ function Debugger(): JSX.Element {
}
};

useEffect(() => {
if (isSourceRange(currentSourceRange) && currentSourceRange.source.id) {
const { source, start } = currentSourceRange!;
scrollToLine({ sourceId: source.id, line: start.line });
}
}, [currentStep, currentSourceId]);

// check whether we need to scroll to a breakpoint
// this is to ensure the source has fully rendered before scrolling
useEffect(() => {
Expand All @@ -233,13 +199,8 @@ function Debugger(): JSX.Element {
});
};

const isSourceRange = (item: any): item is SourceRange => {
// when source exists, that means it should be a full SourceRange
return item.source !== undefined;
};

let content;
if (session && sources && isSourceRange(currentSourceRange)) {
if (session && sources) {
content = (
<div className={classes.mainContent}>
<Grid
Expand All @@ -256,19 +217,19 @@ function Debugger(): JSX.Element {
unknownAddresses={unknownAddresses}
session={session}
sessionUpdated={sessionUpdated}
currentSourceRange={currentSourceRange}
currentSourceId={currentSourceId}
setCurrentSourceId={setCurrentSourceId}
scrollToLine={scrollToLine}
/>
</Grid.Col>
<Grid.Col span={2} className={classes.fullHeight}>
<Variables currentStep={currentStep} session={session} />
<Variables />
<Breakpoints
sources={sources}
handleBreakpointComponentClick={handleBreakpointComponentClick}
handleBreakpointDeleteClick={handleBreakpointDeleteClick}
/>
<Stack session={session} currentStep={currentStep} />
<Stack />
</Grid.Col>
</Grid>
</div>
Expand Down