add debugger panels

pull/7/head
yann300 9 years ago
parent e1da5e6b7d
commit dcba42f184
  1. 182
      src/assemblyItemsBrowser.js
  2. 38
      src/basicPanel.js
  3. 32
      src/basicStyles.js
  4. 3
      src/debugger.js
  5. 3
      src/txBrowser.js

@ -1,12 +1,24 @@
var React = require('react'); var React = require('react');
var BasicPanel = require('./basicPanel');
var style = require('./basicStyles')
module.exports = React.createClass({ module.exports = React.createClass({
getInitialState: function() getInitialState: function()
{ {
return { return {
currentSelected: null, currentSelected: 0,
currentAddress: null currentAddress: null,
currentStack: null,
currentLevels: null,
currentStorage: null,
currentMemory: null,
currentCallData: null,
selectedInst: 0,
lastLevels: null,
lastStorage: null,
lastMemory: null,
lastCallData: null
}; };
}, },
@ -19,39 +31,115 @@ module.exports = React.createClass({
render: function() render: function()
{ {
if (!this.props.vmTrace || !this.props.vmTrace.vmtrace || this.props.vmTrace.vmtrace.length === 0)
return null;
this.state.currentAddress = this.props.vmTrace.vmtrace[0].address
this.state.currentSelected = this.props.vmTrace.codesmap[this.state.currentAddress][this.props.vmTrace.vmtrace[0].pc]
return ( return (
<div> <div style={this.props.vmTrace === null ? style.hidden : style.display} >
<div id="action" > <div style={style.container}>
<button onClick={this.stepIntoBack} >stepIntoBack</button> <button onClick={this.stepIntoBack} disabled={ this.checkButtonState(-1) } >stepIntoBack</button>
<button onClick={this.stepOverBack} >stepOverBack</button> <button onClick={this.stepOverBack} disabled={ this.checkButtonState(-1) } >stepOverBack</button>
<button onClick={this.stepOverForward} >stepOverForward</button> <button onClick={this.stepOverForward} disabled={ this.checkButtonState(1) } >stepOverForward</button>
<button onClick={this.stepIntoForward} >stepIntoForward</button> <button onClick={this.stepIntoForward} disabled={ this.checkButtonState(1) } >stepIntoForward</button>
</div> </div>
<div> <div style={style.container}>
<select size="10" ref='itemsList' value={this.state.currentSelected}> <select size="10" ref='itemsList' value={this.state.selectedInst}>
{ this.renderAssemblyItems() } { this.renderAssemblyItems() }
</select> </select>
</div> </div>
<div>
<BasicPanel name="Stack" data={this.state.currentStack} />
<BasicPanel name="CallStack" data={this.state.currentCallStack} />
<BasicPanel name="Storage" data={this.state.currentStorage} />
<BasicPanel name="Memory" data={this.state.currentMemory} />
<BasicPanel name="CallData" data={this.state.currentCallData} />
</div>
</div> </div>
); );
}, },
checkButtonState: function(incr)
{
if (!this.props.vmTrace)
return "disabled"
if (incr === -1)
return this.state.currentSelected === 0 ? "disabled" : ""
else if (incr === 1)
return this.state.currentSelected >= this.props.vmTrace.vmtrace.length - 1 ? "disabled" : ""
},
renderAssemblyItems: function() renderAssemblyItems: function()
{ {
if (this.props.vmTrace) if (this.props.vmTrace && this.props.vmTrace.vmtrace)
{ {
var selectedItem = this.state.currentSelected
return this.props.vmTrace.vmtrace.map(function(item, i) return this.props.vmTrace.vmtrace.map(function(item, i)
{ {
return <option key={i} value={i} >{item.instname}</option>; return <option key={i} value={i} >{i} {item.instname}</option>;
}); });
} }
}, },
componentWillReceiveProps: function (nextProps) {
this.updateState(nextProps, 0)
},
updateState: function(props, vmTraceIndex)
{
var previousState = this.state.currentSelected
this.setState({ currentSelected: vmTraceIndex })
this.state.currentAddress = props.vmTrace.vmtrace[0].address
this.state.selectedInst = props.vmTrace.codesmap[this.state.currentAddress][props.vmTrace.vmtrace[vmTraceIndex].pc]
if (props.vmTrace.vmtrace[vmTraceIndex].stack)
{
var stack = props.vmTrace.vmtrace[vmTraceIndex].stack
stack.reverse()
this.setState({ currentStack: stack })
}
if (props.vmTrace.vmtrace[vmTraceIndex].levels)
{
var levels = props.vmTrace.vmtrace[vmTraceIndex].levels
var callStack = []
for (var k in levels)
callStack.push(props.vmTrace.vmtrace[levels[k]].address)
this.setState({ currentCallStack: callStack })
lastCallStack = callStack
}
var storageIndex = vmTraceIndex
if (vmTraceIndex < previousState)
storageIndex = this.retrieveLastSeenProperty(vmTraceIndex, "storage", props.vmTrace.vmtrace)
if (props.vmTrace.vmtrace[storageIndex].storage || storageIndex === 0)
{
this.setState({ currentStorage: props.vmTrace.vmtrace[storageIndex].storage })
lastStorage = props.vmTrace.vmtrace[storageIndex].storage
}
var memoryIndex = vmTraceIndex
if (vmTraceIndex < previousState)
memoryIndex = this.retrieveLastSeenProperty(vmTraceIndex, "memory", props.vmTrace.vmtrace)
if (props.vmTrace.vmtrace[memoryIndex].memory || memoryIndex === 0)
{
this.setState({ currentMemory: this.formatMemory(props.vmTrace.vmtrace[memoryIndex].memory) })
lastMemory = this.formatMemory(props.vmTrace.vmtrace[memoryIndex].memory)
}
if (props.vmTrace.vmtrace[vmTraceIndex].calldata)
{
this.setState({ currentCallData: props.vmTrace.vmtrace[vmTraceIndex].calldata })
lastCallData = props.vmTrace.vmtrace[vmTraceIndex].calldata
}
},
retrieveLastSeenProperty: function(currentIndex, propertyName, vmTrace)
{
var index = currentIndex
while (index > 0)
{
if (vmTrace[index][propertyName])
break
index--
}
return index
},
stepIntoBack: function () stepIntoBack: function ()
{ {
@ -111,29 +199,37 @@ module.exports = React.createClass({
{ {
var i = this.state.currentSelected - 1; var i = this.state.currentSelected - 1;
var depth = 0; var depth = 0;
while (--i >= 0) { while (--i >= 0)
{
if (this.isCallInstruction(i)) if (this.isCallInstruction(i))
{
if (depth == 0) if (depth == 0)
break; break;
else depth--; else
depth--;
}
else if (this.isReturnInstruction(i)) else if (this.isReturnInstruction(i))
depth++; depth++;
} }
this.selectState(i); this.selectState(i);
}, },
stepOutForward: function() stepOutForward: function()
{ {
var i = this.state.currentSelected; var i = this.state.currentSelected
var depth = 0; var depth = 0
while (++i < this.props.vmTrace.vmtrace.length) { while (++i < this.props.vmTrace.vmtrace.length)
{
if (this.isReturnInstruction(i)) if (this.isReturnInstruction(i))
{
if (depth == 0) if (depth == 0)
break; break
else else
depth--; depth--
}
else if (this.isCallInstruction(i)) else if (this.isCallInstruction(i))
depth++; depth++
} }
this.selectState(i + 1); this.selectState(i + 1);
}, },
@ -145,10 +241,40 @@ module.exports = React.createClass({
selectState: function(index) selectState: function(index)
{ {
var newIndex = this.props.vmTrace.codesmap[this.state.currentAddress][this.props.vmTrace.vmtrace[index].pc] var selectedInst = this.props.vmTrace.codesmap[this.state.currentAddress][this.props.vmTrace.vmtrace[index].pc]
this.state.currentSelected = index this.updateState(this.props, index)
this.refs.itemsList.value = this.state.currentSelected this.refs.itemsList.value = selectedInst
if (this.props.vmTrace.vmtrace[index].address && this.state.currentAddress !== this.props.vmTrace.vmtrace[index].address) if (this.props.vmTrace.vmtrace[index].address && this.state.currentAddress !== this.props.vmTrace.vmtrace[index].address)
this.state.currentAddress = this.props.vmTrace.vmtrace[index].address this.state.currentAddress = this.props.vmTrace.vmtrace[index].address
}, },
formatMemory: function(mem, width)
{
var ret = []
for (var k = 0; k < mem.length; k += (width * 2))
{
var memory = mem.substr(k, width * 2)
ret.push({
address: web3.toHex(k),
content: this.tryAsciiFormat(memory)
})
}
return ret
},
tryAsciiFormat: function(memorySlot)
{
var ret = { ascii: "", raw: "" }
for (var k = 0; k < memorySlot.length; k += 2)
{
var raw = memorySlot.substr(k, 2)
var dec = web3.toDecimal("0x" + raw)
if (dec >= 32 && dec < 127)
ret.ascii += web3.toAscii(raw)
else
ret.ascii += "?"
ret.raw += " " + raw
}
return ret
}
}) })

@ -0,0 +1,38 @@
var React = require('react');
var style = require('./basicStyles')
module.exports = React.createClass({
getDefaultProps: function()
{
return {
data: null,
name: null
};
},
render: function()
{
return (
<div style={style.panel.container}>
<div style={style.panel.title} >{this.props.name}</div>
<table style={style.panel.table}>
<tbody>
{ this.renderItems() }
</tbody>
</table>
</div>
);
},
renderItems: function()
{
var ret = []
if (this.props.data)
{
for (var key in this.props.data)
ret.push(<tr key={key} ><td>{JSON.stringify(this.props.data[key])}</td></tr>)
}
return ret
}
})

@ -0,0 +1,32 @@
module.exports = {
container:
{
margin: '10px',
padding: '5px'
},
panel:
{
container:
{
margin: '10px',
border: '1px solid',
width: '625px'
},
table:
{
padding: '5px'
},
title:
{
padding: '5px'
}
},
hidden:
{
display: 'none'
},
display:
{
display: 'block'
}
}

@ -2,6 +2,7 @@ var React = require('react');
var TxBrowser = require('./txBrowser'); var TxBrowser = require('./txBrowser');
var VmTraceManager = require('./vmTraceManager'); var VmTraceManager = require('./vmTraceManager');
var VmTraceBrowser = require('./vmTraceBrowser'); var VmTraceBrowser = require('./vmTraceBrowser');
var style = require('./basicStyles')
module.exports = React.createClass({ module.exports = React.createClass({
getInitialState: function() { getInitialState: function() {
@ -11,7 +12,7 @@ module.exports = React.createClass({
render: function() { render: function() {
return ( return (
<div> <div>
<h1>Debugger</h1> <h1 style={style.container} >Debugger</h1>
<TxBrowser onNewTxRequested={this.retrieveVmTrace} /> <TxBrowser onNewTxRequested={this.retrieveVmTrace} />
<VmTraceBrowser vmTrace={this.state.vmTrace} /> <VmTraceBrowser vmTrace={this.state.vmTrace} />
</div> </div>

@ -1,4 +1,5 @@
var React = require('react'); var React = require('react');
var style = require('./basicStyles')
module.exports = React.createClass({ module.exports = React.createClass({
propTypes: { propTypes: {
@ -24,7 +25,7 @@ module.exports = React.createClass({
render: function() { render: function() {
return ( return (
<div> <div style={style.container} >
<div><h3>Transaction details</h3></div> <div><h3>Transaction details</h3></div>
<input onChange={this.updateBlockN} type="text" placeholder= {"Block number e.g. : " + this.state.blockNumber}></input> <input onChange={this.updateBlockN} type="text" placeholder= {"Block number e.g. : " + this.state.blockNumber}></input>
<input onChange={this.updateTxN} type="text" placeholder={"Transaction Number e.g. : " + this.state.txNumber}></input> <input onChange={this.updateTxN} type="text" placeholder={"Transaction Number e.g. : " + this.state.txNumber}></input>

Loading…
Cancel
Save