make function stack clickable

pull/4072/head
yann300 1 year ago
parent 3ee974daf7
commit 29d22913cd
  1. 5
      libs/remix-debug/src/solidity-decoder/internalCallTree.ts
  2. 5
      libs/remix-debug/test/decoder/localsTests/int.ts
  3. 3
      libs/remix-ui/debugger-ui/src/lib/debugger-ui.css
  4. 2
      libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
  5. 8
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx
  6. 23
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/function-panel.tsx
  7. 10
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/vm-debugger-head.tsx
  8. 4
      libs/remix-ui/debugger-ui/src/types/index.ts

@ -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
@ -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 })
}
@ -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

@ -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')

@ -20,4 +20,7 @@
.debuggerPanels {
overflow-y: auto;
height: fit-content;
}
.jumpToFunctionClick span {
cursor: pointer;
}

@ -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}

@ -19,6 +19,8 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
extractFunc,
formatSelfFunc,
registerEvent,
handleExpandFunc,
formatClassNamesFunc,
triggerEvent,
loadMoreEvent,
loadMoreCompletedEvent,
@ -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 {
@ -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}
@ -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)}
/>
)
}

@ -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>
)
}

@ -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': '-',
@ -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)
})
@ -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>

@ -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,
@ -30,6 +32,8 @@ export interface DropdownPanelProps {
extractFunc?: ExtractFunc,
formatSelfFunc?: FormatSelfFunc,
registerEvent?: RegisterEventType,
handleExpandFunc?: HandleExpandFunc,
formatClassNamesFunc?: FormatClassNamesFunc
triggerEvent?: TriggerEventType,
loadMoreEvent?: string,
loadMoreCompletedEvent?: string,

Loading…
Cancel
Save