Skip to content

Commit

Permalink
make function stack clickable
Browse files Browse the repository at this point in the history
  • Loading branch information
yann300 committed Sep 18, 2023
1 parent 9cc541b commit 28e9aa3
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 11 deletions.
5 changes: 4 additions & 1 deletion libs/remix-debug/src/solidity-decoder/internalCallTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ export class InternalCallTree {
const scope = this.findScope(vmtraceIndex)
if (!scope) return []
let scopeId = this.scopeStarts[scope.firstStep]
const scopeDetail = this.scopes[scopeId]
const functions = []
if (!scopeId) return functions
let i = 0
Expand All @@ -174,6 +173,7 @@ export class InternalCallTree {
i += 1
if (i > 1000) throw new Error('retrieFunctionStack: recursion too deep')
const functionDefinition = this.functionDefinitionsByScope[scopeId]
const scopeDetail = this.scopes[scopeId]
if (functionDefinition !== undefined) {
functions.push({ ...functionDefinition, ...scopeDetail })
}
Expand Down Expand Up @@ -280,7 +280,10 @@ async function buildTree (tree, step, scopeId, isCreation, functionDefinition?,
const stepDetail: StepDetail = tree.traceManager.trace[step]
const nextStepDetail: StepDetail = tree.traceManager.trace[step + 1]
if (stepDetail && nextStepDetail) {
// for complicated opcodes which don't have a static gas cost:
stepDetail.gasCost = parseInt(stepDetail.gas as string) - parseInt(nextStepDetail.gas as string)
} else {
stepDetail.gasCost = parseInt(stepDetail.gasCost as unknown as string)
}

// gas per line
Expand Down
5 changes: 5 additions & 0 deletions libs/remix-debug/test/decoder/localsTests/int.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ module.exports = function (st, privateKey, contractBytecode, compilationResult,
st.equals(functions3.length, 1)

st.equal(functions1[0].gasCost, 54)
st.equal(functions1[1].gasCost, 436)

st.equal(functions2[0].gasCost, 23)
st.equal(functions2[1].gasCost, 54)
st.equal(functions2[2].gasCost, 436)

st.equals(Object.keys(functions1[0])[0], 'functionDefinition')
st.equals(Object.keys(functions1[0])[1], 'inputs')
Expand Down
3 changes: 3 additions & 0 deletions libs/remix-ui/debugger-ui/src/lib/debugger-ui.css
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,7 @@
.debuggerPanels {
overflow-y: auto;
height: fit-content;
}
.jumpToFunctionClick span {
cursor: pointer;
}
2 changes: 1 addition & 1 deletion libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
{state.debugging && <StepManager stepManager={stepManager} />}
</div>
<div className="debuggerPanels" ref={panelsRef}>
{state.debugging && <VmDebuggerHead debugging={state.debugging} vmDebugger={vmDebugger} />}
{state.debugging && <VmDebuggerHead debugging={state.debugging} vmDebugger={vmDebugger} stepManager={stepManager} />}
{state.debugging && (
<VmDebugger
debugging={state.debugging}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
extractFunc,
formatSelfFunc,
registerEvent,
handleExpandFunc,
formatClassNamesFunc,
triggerEvent,
loadMoreEvent,
loadMoreCompletedEvent,
Expand Down Expand Up @@ -133,9 +135,9 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
toggleDropdown: !prevState.toggleDropdown
}
})
}
};

const handleExpand = (keyPath) => {
const handleExpand = handleExpandFunc || function (keyPath) {
if (!state.expandPath.includes(keyPath)) {
state.expandPath.push(keyPath)
} else {
Expand Down Expand Up @@ -215,6 +217,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
label={formatSelfFunc ? formatSelfFunc(key, data) : formatSelfDefault(key, data)}
onClick={() => handleExpand(keyPath)}
expand={state.expandPath.includes(keyPath)}
labelClass={formatClassNamesFunc && formatClassNamesFunc(key, data)}
>
<TreeView id={`treeView${key}`} key={keyPath}>
{children}
Expand All @@ -240,6 +243,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
label={formatSelfFunc ? formatSelfFunc(key, data) : formatSelfDefault(key, data)}
onClick={() => handleExpand(keyPath)}
expand={state.expandPath.includes(keyPath)}
labelClass={formatClassNamesFunc && formatClassNamesFunc(key, data)}
/>
)
}
Expand Down
23 changes: 19 additions & 4 deletions libs/remix-ui/debugger-ui/src/lib/vm-debugger/function-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,31 @@ import React, {useState, useEffect} from 'react' // eslint-disable-line
import DropdownPanel from './dropdown-panel' // eslint-disable-line
import {default as deepequal} from 'deep-equal' // eslint-disable-line

export const FunctionPanel = ({data, className}) => {
const [calldata, setCalldata] = useState(null)
export const FunctionPanel = ({data, className, stepManager}) => {
const [functionData, setFunctionData] = useState(null)

useEffect(() => {
if (!deepequal(calldata, data)) setCalldata(data)
if (!deepequal(functionData, data)) {
setFunctionData(data.map(el => el.label))
}
}, [data])

const formatSelfFunc = (key, data) => {
return data.self
}

const handleExpandFunc = (keyPath) => {
stepManager.jumpTo(data[parseInt(keyPath)].function.firstStep)
}

const formatClassNamesFunc = (keyPath, data) => {
return 'jumpToFunctionClick'
}

return (

<div id="FunctionPanel" className={className} data-id="functionPanel">
<DropdownPanel dropdownName="Function Stack" calldata={calldata || {}} />
<DropdownPanel dropdownName="Function Stack" calldata={functionData || {}} formatSelfFunc={formatSelfFunc} formatClassNamesFunc={formatClassNamesFunc} handleExpandFunc={handleExpandFunc} />
</div>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import StepDetail from './step-detail' // eslint-disable-line
import SolidityState from './solidity-state' // eslint-disable-line
import SolidityLocals from './solidity-locals' // eslint-disable-line

export const VmDebuggerHead = ({vmDebugger: {registerEvent, triggerEvent}, debugging}) => {
export const VmDebuggerHead = ({vmDebugger: {registerEvent, triggerEvent}, debugging, stepManager}) => {
const [functionPanel, setFunctionPanel] = useState(null)
const [stepDetail, setStepDetail] = useState({
'vm trace step': '-',
Expand All @@ -32,7 +32,11 @@ export const VmDebuggerHead = ({vmDebugger: {registerEvent, triggerEvent}, debug
const functions = []

for (const func of stack) {
functions.push((func.functionDefinition.name || func.functionDefinition.kind) + '(' + func.inputs.join(', ') + ')' + ' - ' + func.gasCost + ' gas')
const label = (func.functionDefinition.name || func.functionDefinition.kind) + '(' + func.inputs.join(', ') + ')' + ' - ' + func.gasCost + ' gas'
functions.push({
label,
function: func
})
}
setFunctionPanel(() => functions)
})
Expand Down Expand Up @@ -127,7 +131,7 @@ export const VmDebuggerHead = ({vmDebugger: {registerEvent, triggerEvent}, debug
return (
<div id="vmheadView" className="mt-1 px-2 d-flex">
<div className="d-flex flex-column pr-2" style={{flex: 1}}>
<FunctionPanel className="pb-1" data={functionPanel} />
<FunctionPanel className="pb-1" data={functionPanel} stepManager={stepManager} />
<SolidityLocals className="pb-1" data={solidityLocals.calldata} message={solidityLocals.message} registerEvent={registerEvent} triggerEvent={triggerEvent} />
<CodeListView className="pb-2 flex-grow-1" registerEvent={registerEvent} />
</div>
Expand Down
4 changes: 4 additions & 0 deletions libs/remix-ui/debugger-ui/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export type ExtractFunc = (json: any, parent?: any) => ExtractData
export type FormatSelfFunc = (key: string | number, data: ExtractData) => JSX.Element
export type RegisterEventType = (type: string, listener: any) => void // listener is a function
export type TriggerEventType = (type: string, payload: Array<any>) => void
export type HandleExpandFunc = (keyPath: string) => void
export type FormatClassNamesFunc = (key: string | number, data: ExtractData) => string
export interface DropdownPanelProps {
dropdownName: string,
className?: string,
Expand All @@ -30,6 +32,8 @@ export interface DropdownPanelProps {
extractFunc?: ExtractFunc,
formatSelfFunc?: FormatSelfFunc,
registerEvent?: RegisterEventType,
handleExpandFunc?: HandleExpandFunc,
formatClassNamesFunc?: FormatClassNamesFunc
triggerEvent?: TriggerEventType,
loadMoreEvent?: string,
loadMoreCompletedEvent?: string,
Expand Down

0 comments on commit 28e9aa3

Please sign in to comment.