vm debugger component

pull/5370/head
ioedeveloper 5 years ago
parent 3e74157959
commit aef86018c7
  1. 3
      libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
  2. 2
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/code-list-view.tsx
  3. 6
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx
  4. 4
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/solidity-locals.tsx
  5. 4
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/solidity-state.tsx
  6. 58
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/step-detail.tsx
  7. 196
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/vm-debugger.tsx
  8. 1
      libs/remix-ui/debugger-ui/src/types/index.ts

@ -1,6 +1,7 @@
import React from 'react' import React from 'react'
import TxBrowser from './tx-browser/tx-browser'
import StepManager from './step-manager/step-manager' import StepManager from './step-manager/step-manager'
import import VmDebugger from './vm-debugger/vm-debugger'
const DebuggerUI = () => { const DebuggerUI = () => {
return ( return (

@ -3,7 +3,7 @@ import DropdownPanel from './dropdown-panel'
/* eslint-disable-next-line */ /* eslint-disable-next-line */
import EventManager from '../../../../../../apps/remix-ide/src/lib/events' import EventManager from '../../../../../../apps/remix-ide/src/lib/events'
export const CodeListView = ({ vmDebuggerLogic, asm }) => { export const CodeListView = ({ asm }) => {
const event = new EventManager() const event = new EventManager()
const [state, setState] = useState({ const [state, setState] = useState({
code: [], code: [],

@ -13,7 +13,7 @@ import EventManager from '../../../../../../apps/remix-ide/src/lib/events'
import copyToClipboard from '../../../../../../apps/remix-ide/src/app/ui/copy-to-clipboard' import copyToClipboard from '../../../../../../apps/remix-ide/src/app/ui/copy-to-clipboard'
export const DropdownPanel = (props: DropdownPanelProps) => { export const DropdownPanel = (props: DropdownPanelProps) => {
const { dropdownName, opts, codeView, index, calldata, header, extractFunc, formatSelfFunc } = props const { dropdownName, dropdownMessage, opts, codeView, index, calldata, header, extractFunc, formatSelfFunc } = props
const data = useExtractData(calldata, extractFunc) const data = useExtractData(calldata, extractFunc)
const event = new EventManager() const event = new EventManager()
const dropdownRawEl = useRef(null) const dropdownRawEl = useRef(null)
@ -45,6 +45,10 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
update(calldata, header) update(calldata, header)
}, [calldata, header]) }, [calldata, header])
useEffect(() => {
message(dropdownMessage)
}, [dropdownMessage])
const handleToggle = () => { const handleToggle = () => {
setState(prevState => { setState(prevState => {
if (prevState.toggleDropdown) event.trigger('hide', []) if (prevState.toggleDropdown) event.trigger('hide', [])

@ -3,7 +3,7 @@ import DropdownPanel from './dropdown-panel'
import { extractData } from '../../utils/solidityTypeFormatter' import { extractData } from '../../utils/solidityTypeFormatter'
import { ExtractData } from '../../types' import { ExtractData } from '../../types'
export const SolidityLocals = () => { export const SolidityLocals = ({ calldata, message }) => {
const formatSelf = (key: string, data: ExtractData) => { const formatSelf = (key: string, data: ExtractData) => {
let color = 'var(--primary)' let color = 'var(--primary)'
@ -36,7 +36,7 @@ export const SolidityLocals = () => {
return ( return (
<div id='soliditylocals' data-id="solidityLocals"> <div id='soliditylocals' data-id="solidityLocals">
<DropdownPanel dropdownName='Solidity Locals' opts={{ json: true }} extractFunc={extractData} formatSelfFunc={formatSelf} /> <DropdownPanel dropdownName='Solidity Locals' dropdownMessage={message} opts={{ json: true }} calldata={calldata} extractFunc={extractData} formatSelfFunc={formatSelf} />
</div> </div>
) )
} }

@ -3,7 +3,7 @@ import DropdownPanel from './dropdown-panel'
import { extractData } from '../../utils/solidityTypeFormatter' import { extractData } from '../../utils/solidityTypeFormatter'
import { ExtractData } from '../../types' import { ExtractData } from '../../types'
export const SolidityState = () => { export const SolidityState = ({ calldata, message }) => {
const formatSelf = (key: string, data: ExtractData) => { const formatSelf = (key: string, data: ExtractData) => {
let color = 'var(--primary)' let color = 'var(--primary)'
if (data.isArray || data.isStruct || data.isMapping) { if (data.isArray || data.isStruct || data.isMapping) {
@ -36,7 +36,7 @@ export const SolidityState = () => {
return ( return (
<div id='soliditylocals' data-id='solidityLocals'> <div id='soliditylocals' data-id='solidityLocals'>
{ {
<DropdownPanel dropdownName='Solidity State' opts={{ json: true }} formatSelfFunc={formatSelf} extractFunc={extractData} /> <DropdownPanel dropdownName='Solidity State' dropdownMessage={message} opts={{ json: true }} calldata={calldata} formatSelfFunc={formatSelf} extractFunc={extractData} />
} }
</div> </div>
) )

@ -2,15 +2,15 @@ import React, { useState, useEffect } from 'react'
import DropdownPanel from './dropdown-panel' import DropdownPanel from './dropdown-panel'
export interface StepDetailProps { export interface StepDetailProps {
resetStep: boolean,
detail: { detail: {
key: string, key: string,
value: string value: string,
reset: boolean
} }
} }
export const StepDetail = (props: StepDetailProps) => { export const StepDetail = (props: StepDetailProps) => {
const { resetStep, detail } = props const { detail } = props
const [state, setState] = useState({ const [state, setState] = useState({
detail: { detail: {
'vm trace step': '-', 'vm trace step': '-',
@ -23,37 +23,33 @@ export const StepDetail = (props: StepDetailProps) => {
}) })
useEffect(() => { useEffect(() => {
reset() updateField(detail.key, detail.value, detail.reset)
}, [resetStep])
useEffect(() => {
updateField(detail.key, detail.value)
}, [detail]) }, [detail])
const reset = () => { const updateField = (key, value, reset) => {
setState(() => { if (reset) {
return { setState(() => {
detail: { return {
'vm trace step': '-', detail: {
'execution step': '-', 'vm trace step': '-',
'add memory': '', 'execution step': '-',
'gas': '', 'add memory': '',
'remaining gas': '-', 'gas': '',
'loaded address': '-' 'remaining gas': '-',
'loaded address': '-'
}
} }
} })
}) } else {
} setState(prevState => {
const { detail } = prevState
const updateField = (key, value) => {
setState(prevState => { detail[key] = value
const { detail } = prevState return {
detail
detail[key] = value }
return { })
detail }
}
})
} }
return ( return (

@ -14,7 +14,20 @@ import DropdownPanel from './dropdown-panel'
import './vm-debugger.css'; import './vm-debugger.css';
export const VmDebugger = ({ vmDebuggerLogic }) => { export const VmDebugger = ({ vmDebuggerLogic }) => {
const [state, setState] = useState({ const [panelVisibility, setPanelVisibility] = useState({
asmCode: true,
stackPanel: true,
functionPanel: true,
storagePanel: true,
memoryPanel: true,
stepDetail: true,
calldataPanel: true,
callstackPanel: true,
solidityState: true,
solidityLocals: true,
solidityPanel: true,
returnValuesPanel: true,
fullStoragesChangesPanel: true
}) })
const [asm, setAsm] = useState({ const [asm, setAsm] = useState({
code: null, code: null,
@ -24,45 +37,128 @@ export const VmDebugger = ({ vmDebuggerLogic }) => {
const [calldataPanel, setCalldataPanel] = useState(null) const [calldataPanel, setCalldataPanel] = useState(null)
const [memoryPanel, setMemoryPanel] = useState(null) const [memoryPanel, setMemoryPanel] = useState(null)
const [callStackPanel, setCallStackPanel] = useState(null) const [callStackPanel, setCallStackPanel] = useState(null)
const [stackPanel, setStackPanel] = useState(null)
const [functionPanel, setFunctionPanel] = useState(null)
const [storagePanel, setStoragePanel] = useState({
calldata: null,
header: null
})
const [stepDetail, setStepDetail] = useState({
key: null,
value: null,
reset: false
})
const [solidityState, setSolidityState] = useState({
calldata: null,
message: null,
})
const [solidityLocals, setSolidityLocals] = useState({
calldata: null,
message: null,
})
const [returnValuesPanel, setReturnValuesPanel] = useState({})
const [fullStoragesChangesPanel, setFullStoragesChangesPanel] = useState(null)
useEffect(() => { useEffect(() => {
vmDebuggerLogic.event.register('codeManagerChanged', updateAsm) vmDebuggerLogic.event.register('codeManagerChanged', (code, address, index) => {
vmDebuggerLogic.event.register('traceUnloaded', resetAsm) setAsm({ code, address, index })
vmDebuggerLogic.event.register('traceManagerCallDataUpdate', updateCalldataPanel)
vmDebuggerLogic.event.register('traceManagerMemoryUpdate', updateMemoryPanel)
vmDebuggerLogic.event.register('traceManagerCallStackUpdate', updateCallStackPanel)
}, [])
const updateAsm = (code, address, index) => {
setAsm({
code,
address,
index
}) })
} vmDebuggerLogic.event.register('traceUnloaded', () => {
setAsm({ code: [], address: '', index: -1 })
const resetAsm = () => {
setAsm({
code: [],
address: '',
index: -1
}) })
} vmDebuggerLogic.event.register('traceManagerCallDataUpdate', (calldata) => {
setCalldataPanel(calldata)
const updateCalldataPanel = (calldata) => { })
setCalldataPanel(calldata) vmDebuggerLogic.event.register('traceManagerMemoryUpdate', (calldata) => {
} setMemoryPanel(calldata)
})
const updateMemoryPanel = (calldata) => { vmDebuggerLogic.event.register('traceManagerCallStackUpdate', (calldata) => {
setMemoryPanel(calldata) setCallStackPanel(calldata)
} })
vmDebuggerLogic.event.register('traceManagerStackUpdate', (calldata) => {
const updateCallStackPanel = (calldata) => { setStackPanel(calldata)
setCallStackPanel(calldata) })
} vmDebuggerLogic.event.register('functionsStackUpdate', (stack) => {
if (stack === null) return
useEffect(() => { const functions = []
vmDebuggerLogic.event.register('codeManagerChanged', )
for (const func of stack) {
functions.push(func.functionDefinition.attributes.name + '(' + func.inputs.join(', ') + ')')
}
setFunctionPanel(functions)
})
vmDebuggerLogic.event.register('traceManagerStorageUpdate', (calldata, header) => {
setStoragePanel({ calldata, header })
})
vmDebuggerLogic.event.register('traceUnloaded', () => {
setStepDetail({ key: null, value: null, reset: true })
})
vmDebuggerLogic.event.register('newTraceLoaded', () => {
setStepDetail({ key: null, value: null, reset: true })
})
vmDebuggerLogic.event.register('traceCurrentStepUpdate', (error, step) => {
setStepDetail({ key: 'execution step', value: (error ? '-' : step), reset: false })
})
vmDebuggerLogic.event.register('traceMemExpandUpdate', (error, addmem) => {
setStepDetail({ key: 'add memory', value: (error ? '-' : addmem), reset: false })
})
vmDebuggerLogic.event.register('traceStepCostUpdate', (error, gas) => {
setStepDetail({ key: 'gas', value: (error ? '-' : gas), reset: false })
})
vmDebuggerLogic.event.register('traceCurrentCalledAddressAtUpdate', (error, address) => {
setStepDetail({ key: 'loaded address', value: (error ? '-' : address), reset: false })
})
vmDebuggerLogic.event.register('traceRemainingGasUpdate', (error, remainingGas) => {
setStepDetail({ key: 'remaining gas', value: (error ? '-' : remainingGas), reset: false })
})
vmDebuggerLogic.event.register('indexUpdate', (index) => {
setStepDetail({ key: 'vm trace step', value: index, reset: false })
})
vmDebuggerLogic.event.register('solidityState', (calldata) => {
setSolidityState({ ...solidityState, calldata })
})
vmDebuggerLogic.event.register('solidityStateMessage', (message) => {
setSolidityState({ ...solidityState, message })
})
vmDebuggerLogic.event.register('solidityLocals', (calldata) => {
setSolidityLocals({ ...solidityState, calldata })
})
vmDebuggerLogic.event.register('solidityLocalsMessage', (message) => {
setSolidityLocals({ ...solidityState, message })
})
vmDebuggerLogic.event.register('traceReturnValueUpdate', (calldata) => {
setReturnValuesPanel(calldata)
})
vmDebuggerLogic.event.register('traceAddressesUpdate', (_addreses) => {
setFullStoragesChangesPanel({})
})
vmDebuggerLogic.event.register('traceStorageUpdate', (calldata) => {
setFullStoragesChangesPanel(calldata)
})
vmDebuggerLogic.event.register('newTrace', () => {
setPanelVisibility({
asmCode: true,
stackPanel: true,
functionPanel: true,
storagePanel: true,
memoryPanel: true,
stepDetail: true,
calldataPanel: true,
callstackPanel: true,
solidityState: true,
solidityLocals: true,
solidityPanel: true,
returnValuesPanel: true,
fullStoragesChangesPanel: true
})
})
vmDebuggerLogic.event.register('newCallTree', () => {
setPanelVisibility({
...panelVisibility,
solidityPanel: false
})
})
vmDebuggerLogic.start()
}, []) }, [])
const renderHead = () => { const renderHead = () => {
@ -70,12 +166,12 @@ export const VmDebugger = ({ vmDebuggerLogic }) => {
<div id="vmheadView" className="mt-1 px-0"> <div id="vmheadView" className="mt-1 px-0">
<div className="d-flex flex-column"> <div className="d-flex flex-column">
<div className="w-100" hidden> <div className="w-100" hidden>
{this.functionPanel.render()} <FunctionPanel calldata={functionPanel} />
{this.solidityLocals.render()} <SolidityLocals calldata={solidityLocals.calldata} message={solidityLocals.message} />
{this.solidityState.render()} <SolidityState calldata={solidityState.calldata} message={solidityState.message} />
</div> </div>
<div className="w-100">{this.asmCode.render()}</div> <div className="w-100"><CodeListView asm={asm} /></div>
<div className="w-100">{this.stepDetail.render()}</div> <div className="w-100"><StepDetail detail={stepDetail} /></div>
</div> </div>
</div> </div>
) )
@ -84,16 +180,16 @@ export const VmDebugger = ({ vmDebuggerLogic }) => {
return ( return (
<div id="vmdebugger" className="px-2"> <div id="vmdebugger" className="px-2">
<div> <div>
{this.stackPanel.render()} <StackPanel calldata={stackPanel} />
{this.memoryPanel.render()} <MemoryPanel calldata={memoryPanel} />
{this.storagePanel.render()} <StoragePanel storage={storagePanel.calldata} header={storagePanel.header} />
{this.callstackPanel.render()} <CallstackPanel calldata={callStackPanel} />
{this.calldataPanel.render()} <CalldataPanel calldata={calldataPanel} />
{this.returnValuesPanel.render()} <DropdownPanel dropdownName='Return Value' opts={{ json: true }} calldata={returnValuesPanel} />
{this.fullStoragesChangesPanel.render()} <FullStoragesChangesPanel storageData={fullStoragesChangesPanel} />
</div> </div>
</div> </div>
); )
}; }
export default VmDebugger; export default VmDebugger;

@ -14,6 +14,7 @@ export type ExtractFunc = (json: any, parent?: any) => ExtractData
export interface DropdownPanelProps { export interface DropdownPanelProps {
dropdownName: string, dropdownName: string,
dropdownMessage?: string,
opts: { opts: {
json: boolean, json: boolean,
displayContentOnly?: boolean, displayContentOnly?: boolean,

Loading…
Cancel
Save