Merge pull request #2781 from ethereum/grid_debugger_2

Grid debugger 2
pull/1527/head
bunsenstraat 2 years ago committed by GitHub
commit c0df79feea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      apps/debugger/src/app/debugger-api.ts
  2. 4
      apps/debugger/src/app/debugger.ts
  3. 4
      apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts
  4. 1
      apps/remix-ide-e2e/src/tests/debugger.test.ts
  5. 1
      apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts
  6. 2
      apps/remix-ide/src/app/components/side-panel.tsx
  7. 24
      apps/remix-ide/src/app/panels/layout.ts
  8. 11
      libs/remix-debug/src/debugger/stepManager.ts
  9. 21
      libs/remix-ui/app/src/lib/remix-app/components/dragbar/dragbar.tsx
  10. 16
      libs/remix-ui/app/src/lib/remix-app/remix-app.tsx
  11. 3
      libs/remix-ui/app/src/lib/remix-app/style/remix-app.css
  12. 6
      libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
  13. 4
      libs/remix-ui/debugger-ui/src/lib/idebugger-api.ts
  14. 5
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx
  15. 4
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/calldata-panel.tsx
  16. 4
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/callstack-panel.tsx
  17. 4
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/code-list-view.tsx
  18. 10
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx
  19. 4
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/full-storages-changes.tsx
  20. 4
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/function-panel.tsx
  21. 4
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/global-variables.tsx
  22. 6
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/memory-panel.tsx
  23. 4
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/solidity-locals.tsx
  24. 4
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/solidity-state.tsx
  25. 4
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/stack-panel.tsx
  26. 6
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/step-detail.tsx
  27. 4
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/storage-panel.tsx
  28. 18
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/vm-debugger-head.tsx
  29. 22
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/vm-debugger.tsx
  30. 1
      libs/remix-ui/debugger-ui/src/types/index.ts

@ -8,8 +8,6 @@ export const DebuggerApiMixin = (Base) => class extends Base {
initialWeb3
initDebuggerApi () {
this.debugHash = null
const self = this
this.web3Provider = {
sendAsync (payload, callback) {
@ -132,7 +130,6 @@ export const DebuggerApiMixin = (Base) => class extends Base {
} catch (e) {
console.error(e)
}
this.debugHash = hash
if (web3) this._web3 = web3
else this._web3 = this.initialWeb3
remixDebug.init.extendWeb3(this._web3)
@ -154,6 +151,14 @@ export const DebuggerApiMixin = (Base) => class extends Base {
}
showMessage (title: string, message: string) {}
onStartDebugging () {
this.call('layout', 'maximiseSidePanel')
}
onStopDebugging () {
this.call('layout', 'resetSidePanel')
}
}
export class CompilerAbstract implements CompilationOutput { // this is a subset of /remix-ide/src/app/compiler/compiler-abstract.js

@ -12,8 +12,6 @@ export class DebuggerClientApi extends DebuggerApiMixin(PluginClient) {
}
offsetToLineColumnConverter: IDebuggerApi['offsetToLineColumnConverter']
debugHash: string
debugHashRequest: number
removeHighlights: boolean
onBreakpointCleared: (listener: onBreakpointClearedListener) => void
onBreakpointAdded: (listener: onBreakpointAddedListener) => void
@ -26,5 +24,7 @@ export class DebuggerClientApi extends DebuggerApiMixin(PluginClient) {
setFile: (path: string, content: string) => Promise<void>
getDebugWeb3: () => any // returns an instance of web3.js, if applicable (mainet, goerli, ...) it returns a reference to a node from devops (so we are sure debug endpoint is available)
web3: () => any // returns an instance of web3.js
onStartDebugging: () => void // called when debug starts
onStopDebugging: () => void // called when debug stops
}

@ -10,7 +10,9 @@ class GoToVmTraceStep extends EventEmitter {
}
function goToVMtraceStep (browser: NightwatchBrowser, step: number, incr: number, done: VoidFunction) {
browser.execute(function (step) { (document.getElementById('slider') as HTMLInputElement).value = (step - 1).toString() }, [step])
browser.waitForElementVisible('*[data-id="slider"]')
.waitForElementVisible('#stepdetail')
.execute(function (step) { (document.getElementById('slider') as HTMLInputElement).value = (step - 1).toString() }, [step])
.setValue('*[data-id="slider"]', new Array(1).fill(browser.Keys.RIGHT_ARROW))
.execute((step) => {
(document.querySelector('*[data-id="slider"]') as any).internal_onmouseup({ target: { value: step }})

@ -241,6 +241,7 @@ module.exports = {
.clickInstance(0)
.clickFunction('callA - transact (not payable)')
.debugTransaction(1)
.pause(4000)
.goToVMTraceStep(79)
.waitForElementVisible('*[data-id="debugGoToRevert"]', 60000)
.click('*[data-id="debugGoToRevert"]')

@ -287,7 +287,6 @@ module.exports = {
.waitForElementContainsText('*[data-id="sidePanelSwapitTitle"]', 'DEBUGGER', 60000)
.waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalFailed()', 60000)
.waitForElementVisible('*[data-id="dropdownPanelSolidityLocals"]').pause(1000)
.click('*[data-id="dropdownPanelSolidityLocals"]')
.waitForElementContainsText('*[data-id="solidityLocals"]', 'no locals', 60000)
.goToVMTraceStep(316)
.waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalFailed()', 60000)

@ -12,7 +12,7 @@ const sidePanel = {
displayName: 'Side Panel',
description: 'Remix IDE side panel',
version: packageJson.version,
methods: ['addView', 'removeView']
methods: ['addView', 'removeView', 'currentFocus']
}
export class SidePanel extends AbstractPanel {

@ -6,7 +6,7 @@ import { QueryParams } from '@remix-project/remix-lib'
const profile: Profile = {
name: 'layout',
description: 'layout',
methods: ['minimize']
methods: ['minimize', 'maximiseSidePanel', 'resetSidePanel']
}
interface panelState {
@ -30,8 +30,10 @@ export type PanelConfiguration = {
export class Layout extends Plugin {
event: any
panels: panels
maximised: { [key: string]: boolean }
constructor () {
super(profile)
this.maximised = {}
this.event = new EventEmitter()
}
@ -64,6 +66,14 @@ export class Layout extends Plugin {
break
}
})
this.on('sidePanel', 'focusChanged', async (name) => {
const current = await this.call('sidePanel', 'currentFocus')
if (this.maximised[current]) {
this.event.emit('maximisesidepanel')
} else {
this.event.emit('resetsidepanel')
}
})
document.addEventListener('keypress', e => {
if (e.shiftKey && e.ctrlKey) {
if (e.code === 'KeyF') {
@ -92,4 +102,16 @@ export class Layout extends Plugin {
this.panels[name].minimized = minimized
this.event.emit('change', null)
}
async maximiseSidePanel () {
this.event.emit('maximisesidepanel')
const current = await this.call('sidePanel', 'currentFocus')
this.maximised[current] = true
}
async resetSidePanel () {
this.event.emit('resetsidepanel')
const current = await this.call('sidePanel', 'currentFocus')
this.maximised[current] = false
}
}

@ -15,7 +15,7 @@ export class DebuggerStepManager {
this.event = new EventManager()
this.debugger = _debugger
this.traceManager = traceManager
this.currentStepIndex = 0
this.currentStepIndex = -1
this.traceLength = 0
this.codeTraceLength = 0
this.revertionPoint = null
@ -34,13 +34,18 @@ export class DebuggerStepManager {
this.traceLength = newLength
this.codeTraceLength = this.calculateCodeLength()
}
this.jumpTo(0)
setTimeout(() => {
this.jumpTo(0) // wait for the ui to render
}, 500)
})
})
this.debugger.callTree.event.register('callTreeReady', () => {
if (this.debugger.callTree.functionCallStack.length) {
this.jumpTo(this.debugger.callTree.functionCallStack[0])
setTimeout(() => {
this.jumpTo(this.debugger.callTree.functionCallStack[0]) // wait for the ui to be render
}, 500)
}
})

@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react'
import React, { useEffect, useState, useRef } from 'react'
import Draggable from 'react-draggable'
import './dragbar.css'
@ -7,18 +7,37 @@ interface IRemixDragBarUi {
setHideStatus: (hide: boolean) => void;
hidden: boolean
minWidth: number
maximiseTrigger: number
resetTrigger: number
}
const DragBar = (props: IRemixDragBarUi) => {
const [dragState, setDragState] = useState<boolean>(false)
const [dragBarPosX, setDragBarPosX] = useState<number>(0)
const [offset, setOffSet] = useState<number>(0)
const initialWidth = useRef<number>(props.minWidth)
const nodeRef = React.useRef(null) // fix for strictmode
useEffect(() => {
setDragBarPosX(offset + (props.hidden ? 0 : props.refObject.current.offsetWidth))
}, [props.hidden, offset])
useEffect(() => {
initialWidth.current = props.refObject.current.clientWidth
if (props.maximiseTrigger > 0) {
const width = 0.4 * window.innerWidth
props.refObject.current.style.width = width + 'px'
setDragBarPosX(offset + width)
}
}, [props.maximiseTrigger])
useEffect(() => {
if (props.maximiseTrigger > 0) {
props.refObject.current.style.width = initialWidth.current + 'px'
setDragBarPosX(offset + initialWidth.current)
}
}, [props.resetTrigger])
const handleResize = () => {
setOffSet(props.refObject.current.offsetLeft)
setDragBarPosX(props.refObject.current.offsetLeft + props.refObject.current.offsetWidth)

@ -17,6 +17,8 @@ interface IRemixAppUi {
const RemixApp = (props: IRemixAppUi) => {
const [appReady, setAppReady] = useState<boolean>(false)
const [hideSidePanel, setHideSidePanel] = useState<boolean>(false)
const [maximiseTrigger, setMaximiseTrigger] = useState<number>(0)
const [resetTrigger, setResetTrigger] = useState<number>(0)
const sidePanelRef = useRef(null)
useEffect(() => {
@ -48,6 +50,18 @@ const RemixApp = (props: IRemixAppUi) => {
setHideSidePanel(true)
}, 1000)
})
props.app.layout.event.on('maximisesidepanel', () => {
setMaximiseTrigger(prev => {
return prev + 1
})
})
props.app.layout.event.on('resetsidepanel', () => {
setResetTrigger(prev => {
return prev + 1
})
})
}
const value = {
@ -66,7 +80,7 @@ const RemixApp = (props: IRemixAppUi) => {
<div className={`remixIDE ${appReady ? '' : 'd-none'}`} data-id="remixIDE">
<div id="icon-panel" data-id="remixIdeIconPanel" className="iconpanel bg-light">{props.app.menuicons.render()}</div>
<div ref={sidePanelRef} id="side-panel" data-id="remixIdeSidePanel" className={`sidepanel border-right border-left ${hideSidePanel ? 'd-none' : ''}`}>{props.app.sidePanel.render()}</div>
<DragBar minWidth={250} refObject={sidePanelRef} hidden={hideSidePanel} setHideStatus={setHideSidePanel}></DragBar>
<DragBar resetTrigger={resetTrigger} maximiseTrigger={maximiseTrigger} minWidth={250} refObject={sidePanelRef} hidden={hideSidePanel} setHideStatus={setHideSidePanel}></DragBar>
<div id="main-panel" data-id="remixIdeMainPanel" className='mainpanel'>
<RemixUIMainPanel Context={AppContext}></RemixUIMainPanel>
</div>

@ -31,7 +31,8 @@ pre {
.sidepanel {
display : flex;
flex-direction : row-reverse;
width: 320px;
width : 320px;
transition : width 1s;
}
.highlightcode {

@ -57,7 +57,6 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
return () => window.removeEventListener('resize', handleResize)
}, [state.debugging, state.isActive])
useEffect(() => {
return unLoad()
}, [])
@ -191,6 +190,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
}
const unLoad = () => {
debuggerModule.onStopDebugging()
if (state.debugger) state.debugger.unload()
setState(prevState => {
return {
@ -282,6 +282,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
})
setTimeout(async() => {
debuggerModule.onStartDebugging()
try {
await debuggerInstance.debug(blockNumber, txNumber, tx, () => {
listenToEvents(debuggerInstance, currentReceipt)
@ -349,7 +350,8 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
<Toaster message={state.toastMessage} />
<div className="px-2" ref={debuggerTopRef}>
<div>
<div className="mb-2 debuggerConfig custom-control custom-checkbox" title="Using Generated Sources lets you step into compiler outputs while debugging.">
<p className="my-2 debuggerLabel">Debugger Configuration</p>
<div className="mt-2 mb-2 debuggerConfig custom-control custom-checkbox">
<input className="custom-control-input" id="debugGeneratedSourcesInput" onChange={({ target: { checked } }) => {
setState(prevState => {
return { ...prevState, opt: { ...prevState.opt, debugWithGeneratedSources: checked } }

@ -46,8 +46,6 @@ export type onEnvChangedListener = (provider: string) => void
export interface IDebuggerApi {
offsetToLineColumnConverter: { offsetToLineColumn: (sourceLocation: RawLocation, file: number, contents: Sources, asts: Asts) => Promise<LineColumnLocation> }
debugHash: string
debugHashRequest: number
removeHighlights: boolean
onRemoveHighlights: (listener: VoidFunction) => void
onDebugRequested: (listener: onDebugRequested) => void
@ -63,6 +61,8 @@ export interface IDebuggerApi {
getDebugWeb3: () => any // returns an instance of web3.js, if applicable (mainet, goerli, ...) it returns a reference to a node from devops (so we are sure debug endpoint is available)
web3: () => any // returns an instance of web3.js
showMessage (title: string, message: string): void
onStartDebugging (): void // called when debug starts
onStopDebugging (): void // called when debug stops
}
export interface DebuggerUIProps {

@ -122,9 +122,10 @@ export const AssemblyItems = ({ registerEvent }) => {
}
return (
<div className="border rounded px-1 mt-1 bg-light">
<div className="h-100 border rounded px-1 mt-1 bg-light">
<div className='dropdownpanel'>
<div className='dropdowncontent'>
<div className='dropdowncontent pb-2'>
{ assemblyItems.display.length == 0 && <div>No data available</div> }
<div className="pl-2 my-1 small instructions" data-id="asmitems" id='asmitems' ref={asmItemsRef}>
{
assemblyItems.display.map((item, i) => {

@ -1,9 +1,9 @@
import React from 'react' // eslint-disable-line
import DropdownPanel from './dropdown-panel' // eslint-disable-line
export const CalldataPanel = ({ calldata }) => {
export const CalldataPanel = ({ calldata, className = "" }) => {
return (
<div id='calldatapanel'>
<div id='calldatapanel' className={className}>
<DropdownPanel dropdownName='Call Data' calldata={calldata || {}} />
</div>
)

@ -1,9 +1,9 @@
import React from 'react' // eslint-disable-line
import DropdownPanel from './dropdown-panel' // eslint-disable-line
export const CallstackPanel = ({ calldata }) => {
export const CallstackPanel = ({ calldata, className }) => {
return (
<div id='callstackpanel'>
<div id='callstackpanel' className={className}>
<DropdownPanel dropdownName='Call Stack' calldata={calldata || {}} />
</div>
)

@ -1,9 +1,9 @@
import React, { useState, useEffect } from 'react' // eslint-disable-line
import AssemblyItems from './assembly-items' // eslint-disable-line
export const CodeListView = ({ registerEvent }) => {
export const CodeListView = ({ registerEvent, className = ""}) => {
return (
<div id='asmcodes'>
<div className={className} id='asmcodes'>
<AssemblyItems registerEvent={registerEvent} />
</div>
)

@ -7,7 +7,7 @@ import './styles/dropdown-panel.css'
export const DropdownPanel = (props: DropdownPanelProps) => {
const [calldataObj, dispatch] = useReducer(reducer, initialState)
const { dropdownName, dropdownMessage, calldata, header, loading, extractFunc, formatSelfFunc, registerEvent, triggerEvent, loadMoreEvent, loadMoreCompletedEvent, headStyle, bodyStyle, hexHighlight } = props
const { dropdownName, className, dropdownMessage, calldata, header, loading, extractFunc, formatSelfFunc, registerEvent, triggerEvent, loadMoreEvent, loadMoreCompletedEvent, headStyle, bodyStyle, hexHighlight } = props
const extractDataDefault: ExtractFunc = (item, parent?) => {
const ret: ExtractData = {}
@ -54,7 +54,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
}
const [state, setState] = useState({
header: '',
toggleDropdown: false,
toggleDropdown: true,
message: {
innerText: 'No data available.',
display: 'block'
@ -163,7 +163,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
display: isEmpty ? 'block' : 'none'
},
updating: false,
toggleDropdown: !isEmpty,
toggleDropdown: true,
data: calldata
}
})
@ -194,7 +194,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
const uniquePanelName = dropdownName.split(' ').join('')
return (
<div className="border rounded px-1 mt-1 bg-light">
<div className={className + " border rounded px-1 mt-1 bg-light"}>
<div className="py-0 px-1 title" style={headStyle}>
<div className={state.toggleDropdown ? 'icon fas fa-caret-down' : 'icon fas fa-caret-right'} onClick={handleToggle}></div>
<div className="name" data-id={`dropdownPanel${uniquePanelName}`} onClick={handleToggle}>{dropdownName}</div><span className="nameDetail" onClick={handleToggle}>{header}</span>
@ -202,7 +202,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
</div>
<div className='dropdownpanel' style={{ display: state.toggleDropdown ? 'block' : 'none' }}>
<i className="refresh fas fa-sync" style={{ display: state.updating ? 'inline-block' : 'none' }} aria-hidden="true"></i>
<div className='dropdowncontent' style={{ display: state.dropdownContent.display, ...bodyStyle }}>
<div className='dropdowncontent pb-2' style={{ display: state.dropdownContent.display, ...bodyStyle }}>
{
state.data &&
<TreeView id="treeView">

@ -1,9 +1,9 @@
import React from 'react' // eslint-disable-line
import { DropdownPanel } from './dropdown-panel' // eslint-disable-line
export const FullStoragesChanges = ({ calldata }) => {
export const FullStoragesChanges = ({ calldata, className = "" }) => {
return (
<div id='fullstorageschangespanel'>
<div className={className} id='fullstorageschangespanel'>
<DropdownPanel dropdownName='Full Storage Changes' calldata={ calldata || {}} />
</div>
)

@ -2,7 +2,7 @@ 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 }) => {
export const FunctionPanel = ({ data, className }) => {
const [calldata, setCalldata] = useState(null)
useEffect(() => {
@ -10,7 +10,7 @@ export const FunctionPanel = ({ data }) => {
}, [data])
return (
<div id='FunctionPanel' data-id='functionPanel'>
<div id='FunctionPanel' className={className} data-id='functionPanel'>
<DropdownPanel dropdownName='Function Stack' calldata={calldata || {}} />
</div>
)

@ -3,7 +3,7 @@ import DropdownPanel from './dropdown-panel' // eslint-disable-line
import { BN } from 'ethereumjs-util'
import Web3 from 'web3'
export const GlobalVariables = ({ block, receipt, tx }) => {
export const GlobalVariables = ({ block, receipt, tx, className }) => {
// see https://docs.soliditylang.org/en/latest/units-and-global-variables.html#block-and-transaction-properties
const globals = {
'block.chainid': tx.chainId,
@ -22,7 +22,7 @@ export const GlobalVariables = ({ block, receipt, tx }) => {
}
return (
<div id='globalvariable' data-id='globalvariable'>
<div id='globalvariable' data-id='globalvariable' className={className}>
<DropdownPanel hexHighlight={false} bodyStyle={{ fontFamily: 'monospace' }} dropdownName='Global Variables' calldata={globals || {}} />
</div>
)

@ -1,9 +1,11 @@
import React from 'react' // eslint-disable-line
import DropdownPanel from './dropdown-panel' // eslint-disable-line
export const MemoryPanel = ({ calldata }) => {
export const MemoryPanel = ({ calldata, className}) => {
return (
<DropdownPanel hexHighlight={true} bodyStyle={{ fontFamily: 'monospace' }} dropdownName='Memory' calldata={calldata || {}} />
<div className={className} >
<DropdownPanel hexHighlight={true} bodyStyle={{ fontFamily: 'monospace' }} dropdownName='Memory' calldata={calldata || {}} />
</div>
)
}

@ -3,7 +3,7 @@ import DropdownPanel from './dropdown-panel' // eslint-disable-line
import { extractData } from '../../utils/solidityTypeFormatter' // eslint-disable-line
import { ExtractData } from '../../types' // eslint-disable-line
export const SolidityLocals = ({ data, message, registerEvent, triggerEvent }) => {
export const SolidityLocals = ({ data, message, registerEvent, triggerEvent, className = "" }) => {
const [calldata, setCalldata] = useState(null)
useEffect(() => {
@ -43,7 +43,7 @@ export const SolidityLocals = ({ data, message, registerEvent, triggerEvent }) =
}
return (
<div id='soliditylocals' data-id="solidityLocals">
<div className={className} id='soliditylocals' data-id="solidityLocals">
<DropdownPanel
dropdownName='Solidity Locals'
dropdownMessage={message}

@ -3,7 +3,7 @@ import DropdownPanel from './dropdown-panel' // eslint-disable-line
import { extractData } from '../../utils/solidityTypeFormatter'
import { ExtractData } from '../../types' // eslint-disable-line
export const SolidityState = ({ calldata, message }) => {
export const SolidityState = ({ calldata, message, className }) => {
const formatSelf = (key: string, data: ExtractData) => {
try {
let color = 'var(--primary)'
@ -38,7 +38,7 @@ export const SolidityState = ({ calldata, message }) => {
}
return (
<div id='soliditystate' data-id='soliditystate'>
<div id='soliditystate' data-id='soliditystate' className={className}>
{
<DropdownPanel dropdownName='Solidity State' calldata={calldata || {}} formatSelfFunc={formatSelf} extractFunc={extractData} />
}

@ -1,9 +1,9 @@
import React from 'react' // eslint-disable-line
import DropdownPanel from './dropdown-panel' // eslint-disable-line
export const StackPanel = ({ calldata }) => {
export const StackPanel = ({ calldata, className }) => {
return (
<div id='stackpanel'>
<div id='stackpanel' className={className}>
<DropdownPanel hexHighlight={true} bodyStyle={{ fontFamily: 'monospace' }} dropdownName='Stack' calldata={calldata || {}} />
</div>
)

@ -1,10 +1,10 @@
import React from 'react' // eslint-disable-line
import DropdownPanel from './dropdown-panel' // eslint-disable-line
export const StepDetail = ({ stepDetail }) => {
export const StepDetail = ({ stepDetail, className = "" }) => {
return (
<div id='stepdetail' data-id='stepdetail'>
<DropdownPanel hexHighlight={false} dropdownName='Step details' calldata={stepDetail || {}} />
<div className={className} id='stepdetail' data-id='stepdetail'>
<DropdownPanel className={className} hexHighlight={false} dropdownName='Step details' calldata={stepDetail || {}} />
</div>
)
}

@ -1,9 +1,9 @@
import React from 'react' // eslint-disable-line
import DropdownPanel from './dropdown-panel' // eslint-disable-line
export const StoragePanel = ({ calldata, header }) => {
export const StoragePanel = ({ calldata, header, className }) => {
return (
<div id='storagepanel'>
<div id='storagepanel' className={className}>
<DropdownPanel dropdownName='Storage' calldata={calldata || {}} header={header} />
</div>
)

@ -98,15 +98,15 @@ export const VmDebuggerHead = ({ vmDebugger: { registerEvent, triggerEvent } })
}, [registerEvent])
return (
<div id='vmheadView' className="mt-1 px-2">
<div className='d-flex flex-column'>
<div className='w-100'>
<FunctionPanel data={functionPanel} />
<SolidityLocals data={solidityLocals.calldata} message={solidityLocals.message} registerEvent={registerEvent} triggerEvent={triggerEvent} />
<SolidityState calldata={solidityState.calldata} message={solidityState.message} />
</div>
<div className='w-100'><CodeListView registerEvent={registerEvent} /></div>
<div className='w-100'><StepDetail stepDetail={stepDetail} /></div>
<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} />
<SolidityLocals className="pb-1" data={solidityLocals.calldata} message={solidityLocals.message} registerEvent={registerEvent} triggerEvent={triggerEvent} />
<CodeListView className="pb-2 flex-grow-1" registerEvent={registerEvent} />
</div>
<div className='d-flex flex-column pl-2' style={{ flex:1 }}>
<SolidityState className="pb-1" calldata={solidityState.calldata} message={solidityState.message} />
<StepDetail className="pb-1 pb-2 h-100 flex-grow-1" stepDetail={stepDetail} />
</div>
</div>
)

@ -52,16 +52,18 @@ export const VmDebugger = ({ vmDebugger: { registerEvent }, currentBlock, curren
}, [registerEvent])
return (
<div id='vmdebugger' className="px-2">
<div>
<StackPanel calldata={stackPanel} />
<MemoryPanel calldata={memoryPanel} />
<StoragePanel calldata={storagePanel.calldata} header={storagePanel.header} />
<CallstackPanel calldata={callStackPanel} />
<CalldataPanel calldata={calldataPanel} />
<GlobalVariables block={currentBlock} receipt={currentReceipt} tx={currentTransaction} />
<ReturnValuesPanel dropdownName='Return Value' calldata={returnValuesPanel || {}} />
<FullStoragesChangesPanel calldata={fullStoragesChangesPanel} />
<div id='vmdebugger' className="d-flex">
<div className='d-flex flex-column px-2 pr-2' style={{ flex: 1 }}>
<CallstackPanel className="pb-1" calldata={callStackPanel} />
<StackPanel className="pb-1" calldata={stackPanel} />
<MemoryPanel className="pb-1" calldata={memoryPanel} />
<StoragePanel className="pb-1" calldata={storagePanel.calldata} header={storagePanel.header} />
<ReturnValuesPanel className="pb-1" dropdownName='Return Value' calldata={returnValuesPanel || {}} />
<GlobalVariables className="pb-1" block={currentBlock} receipt={currentReceipt} tx={currentTransaction} />
</div>
<div className='d-flex flex-column px-2 pl-2' style={{ flex: 1 }}>
<FullStoragesChangesPanel className="pb-1" calldata={fullStoragesChangesPanel} />
<CalldataPanel className="pb-1" calldata={calldataPanel} />
</div>
</div>
)

@ -20,6 +20,7 @@ export type RegisterEventType = (type: string, listener: any) => void // listene
export type TriggerEventType = (type: string, payload: Array<any>) => void
export interface DropdownPanelProps {
dropdownName: string,
className?: string,
dropdownMessage?: string,
calldata?: {
[key: string]: string

Loading…
Cancel
Save