replace react by yoyo

pull/7/head
yann300 9 years ago
parent 6432e80788
commit a690b96448
  1. 10
      package.json
  2. 60
      src/ASMCode.js
  3. 32
      src/BasicPanel.js
  4. 73
      src/ButtonNavigator.js
  5. 43
      src/CalldataPanel.js
  6. 43
      src/CallstackPanel.js
  7. 75
      src/Ethdebugger.js
  8. 36
      src/MemoryPanel.js
  9. 64
      src/Slider.js
  10. 43
      src/StackPanel.js
  11. 129
      src/StepManager.js
  12. 116
      src/Sticker.js
  13. 43
      src/StoragePanel.js
  14. 118
      src/TxBrowser.js
  15. 73
      src/VmDebugger.js
  16. 64
      src/asmCode.js
  17. 25
      src/basicPanel.js
  18. 12
      src/basicStyles.js
  19. 63
      src/buttonNavigator.js
  20. 49
      src/calldataPanel.js
  21. 49
      src/callstackPanel.js
  22. 78
      src/debugger.js
  23. 11
      src/helpers/init.js
  24. 10
      src/helpers/ui.js
  25. 15
      src/index.js
  26. 43
      src/memoryPanel.js
  27. 55
      src/slider.js
  28. 49
      src/stackPanel.js
  29. 139
      src/stepManager.js
  30. 138
      src/sticker.js
  31. 50
      src/storagePanel.js
  32. 97
      src/txBrowser.js
  33. 52
      src/vmDebugger.js
  34. 11
      test/codeManager.js
  35. 6
      test/index.js
  36. 4
      test/traceManager.js

@ -14,13 +14,11 @@
],
"main": "index.js",
"dependencies": {
"react": "^15.0.1",
"react-dom": "^15.0.1",
"web3": "^0.15.3"
"browserify": "^13.0.1",
"web3": "^0.15.3",
"yo-yo": "^1.2.1"
},
"devDependencies": {
"babel-preset-react": "^6.5.0",
"babelify": "^7.2.0",
"nightwatch": "^0.9.4",
"standard": "^7.0.1",
"standard-reporter": "^1.0.5",
@ -28,7 +26,7 @@
},
"scripts": {
"start_node": "eth --rpccorsdomain \"*\" -j -v 0",
"build": "mkdir -p build; browserify -t [ babelify --presets [ react ] ] src/index.js -o build/app.js",
"build": "mkdir -p build; browserify src/index.js -o build/app.js",
"test": "standard && tape ./test/tests.js",
"serve": "http-server ."
},

@ -0,0 +1,60 @@
'use strict'
var style = require('./basicStyles')
var yo = require('yo-yo')
var CodeManager = require('./code/codeManager')
var ui = require('./helpers/ui')
function ASMCode (_parent, _traceManager, _web3) {
this.parent = _parent
this.codeManager = new CodeManager(_web3, _traceManager)
this.code
this.address
this.codeView
this.init()
}
ASMCode.prototype.render = function () {
this.view = (
yo`<select size='10' id='asmitems' ref='itemsList' style=${ui.formatCss(style.instructionsList)}>
${this.codeView}
</select>`
)
return this.view
}
ASMCode.prototype.init = function () {
var self = this
this.codeManager.register('indexChanged', this, this.indexChanged)
this.codeManager.register('codeChanged', this, this.codeChanged)
this.codeManager.register('loadingCode', this, function (address) {})
this.parent.register('indexChanged', this, function (index) {
self.codeManager.resolveStep(index, self.parent.tx)
})
}
ASMCode.prototype.indexChanged = function (index) {
document.getElementById('asmitems').value = index
}
ASMCode.prototype.codeChanged = function (code, address, index) {
this.code = code
this.address = address
this.instructionIndex = index
this.renderAssemblyItems()
yo.update(this.view, this.render())
document.getElementById('asmitems').value = index
}
ASMCode.prototype.renderAssemblyItems = function () {
if (this.code) {
this.codeView = this.code.map(function (item, i) {
return yo`<option key=${i} value=${i}>
${item}
</option>`
})
return this.codeView
}
}
module.exports = ASMCode

@ -0,0 +1,32 @@
'use strict'
var style = require('./basicStyles')
var yo = require('yo-yo')
var ui = require('./helpers/ui')
function BasicPanel (_name) {
this.data
this.name = _name
this.view
}
BasicPanel.prototype.update = function () {
yo.update(this.view, this.render())
}
BasicPanel.prototype.render = function () {
var view = yo`<div style=${ui.formatCss(style.panel.container)}>
<div style=${ui.formatCss(style.panel.title)}>
${this.name}
</div>
<div style=${ui.formatCss(style.panel.tableContainer)}>
<pre style=${ui.formatCss(style.panel.table, style.font)} >${this.data}</pre>
</div>
</div>`
if (!this.view) {
this.view = view
}
return view
}
module.exports = BasicPanel

@ -0,0 +1,73 @@
'use strict'
var util = require('./helpers/global')
var EventManager = require('./lib/eventManager')
var yo = require('yo-yo')
function ButtonNavigator (_traceManager) {
util.extend(this, new EventManager())
this.intoBackDisabled = true
this.overBackDisabled = true
this.intoForwardDisabled = true
this.overForwardDisabled = true
this.nextCallDisabled = true
this.traceManager = _traceManager
this.view
}
module.exports = ButtonNavigator
ButtonNavigator.prototype.render = function () {
var self = this
var view = yo`<div>
<button ref='intoback' onclick=${function () { self.trigger('stepIntoBack') }} disabled=${this.intoBackDisabled} >
Step Into Back
</button>
<button ref='overback' onclick=${function () { self.trigger('stepOverBack') }} disabled=${this.overBackDisabled} >
Step Over Back
</button>
<button ref='overforward' onclick=${function () { self.trigger('stepOverForward') }} disabled=${this.overForwardDisabled} >
Step Over Forward
</button>
<button ref='intoforward' onclick=${function () { self.trigger('stepIntoForward') }} disabled=${this.intoForwardDisabled} >
Step Into Forward
</button>
<button ref='nextcall' onclick=${function () { self.trigger('jumpNextCall') }} disabled=${this.nextCallDisabled} >
Jump Next Call
</button>
</div>`
if (!this.view) {
this.view = view
}
return view
}
ButtonNavigator.prototype.stepChanged = function (step) {
this.intoBackDisabled = step <= 0
this.overBackDisabled = step <= 0
if (!this.traceManager) {
this.intoForwardDisabled = true
this.overForwardDisabled = true
this.NextCallDisabled = true
} else {
var self = this
this.traceManager.getLength(function (error, length) {
if (error) {
self.intoBackDisabled = true
self.overBackDisabled = true
self.intoForwardDisabled = true
self.overForwardDisabled = true
self.NextcallDisabled = true
console.log(error)
} else {
self.intoForwardDisabled = step >= length - 1
self.overForwardDisabled = step >= length - 1
self.NextcallDisabled = step >= length - 1
}
})
}
yo.update(this.view, this.render())
}
module.exports = ButtonNavigator

@ -0,0 +1,43 @@
'use strict'
var BasicPanel = require('./BasicPanel')
var yo = require('yo-yo')
function CalldataPanel (_parent, _traceManager) {
this.parent = _parent
this.traceManager = _traceManager
this.basicPanel = new BasicPanel('Call Data')
this.init()
}
CalldataPanel.prototype.render = function () {
return (
yo`${this.basicPanel.render()}`
)
}
CalldataPanel.prototype.init = function () {
var self = this
this.parent.register('indexChanged', this, function (index) {
if (index < 0) return
if (self.parent.currentStepIndex !== index) return
self.traceManager.getCallDataAt(index, function (error, calldata) {
if (error) {
console.log(error)
} else if (self.parent.currentStepIndex === index) {
self.basicPanel.data = self.format(calldata)
self.basicPanel.update()
}
})
})
}
CalldataPanel.prototype.format = function (calldata) {
var ret = ''
for (var key in calldata) {
ret += calldata[key] + '\n'
}
return ret
}
module.exports = CalldataPanel

@ -0,0 +1,43 @@
'use strict'
var BasicPanel = require('./BasicPanel')
var yo = require('yo-yo')
function CallstackPanel (_parent, _traceManager) {
this.parent = _parent
this.traceManager = _traceManager
this.basicPanel = new BasicPanel('Call Stack')
this.init()
}
CallstackPanel.prototype.render = function () {
return (
yo`${this.basicPanel.render()}`
)
}
CallstackPanel.prototype.init = function () {
var self = this
this.parent.register('indexChanged', this, function (index) {
if (index < 0) return
if (self.parent.currentStepIndex !== index) return
self.traceManager.getCallStackAt(index, function (error, callstack) {
if (error) {
console.log(error)
} else if (self.parent.currentStepIndex === index) {
self.basicPanel.data = self.format(callstack)
self.basicPanel.update()
}
})
})
}
CallstackPanel.prototype.format = function (callstack) {
var ret = ''
for (var key in callstack) {
ret += callstack[key] + '\n'
}
return ret
}
module.exports = CallstackPanel

@ -0,0 +1,75 @@
'use strict'
var TxBrowser = require('./TxBrowser')
var StepManager = require('./StepManager')
var TraceManager = require('./trace/traceManager')
var VmDebugger = require('./VmDebugger')
var style = require('./basicStyles')
var util = require('./helpers/global')
var EventManager = require('./lib/eventManager')
var yo = require('yo-yo')
var init = require('./helpers/init')
var ui = require('./helpers/ui')
function Ethdebugger (_context) {
util.extend(this, new EventManager())
this.context = _context
this.currentStepIndex = -1
this.tx
this.web3 = init.loadWeb3()
this.traceManager = new TraceManager(this.web3)
var self = this
this.txBrowser = new TxBrowser(this.web3)
this.txBrowser.register('newTxRequested', this, function (blockNumber, txIndex, tx) {
self.startDebugging(blockNumber, txIndex, tx)
})
this.stepManager = new StepManager(this, this.traceManager)
this.stepManager.register('stepChanged', this, function (stepIndex) {
self.stepChanged(stepIndex)
})
this.vmDebugger = new VmDebugger(this, this.traceManager, this.web3)
}
Ethdebugger.prototype.render = function () {
var self = this
return (
yo`<div style=${ui.formatCss(style.font)}>
<h1 style=${ui.formatCss(style.container)}>Eth Debugger</h1>
<div onclick=${function () { self.unLoad() }}>X</div>
${this.txBrowser.render()}
${this.stepManager.render()}
${this.vmDebugger.render()}
</div>`
)
}
Ethdebugger.prototype.unLoad = function () {
this.traceManager.init()
this.stepManager.init()
this.trigger('traceUnloaded')
}
Ethdebugger.prototype.stepChanged = function (stepIndex) {
this.currentStepIndex = stepIndex
this.trigger('indexChanged', [stepIndex])
}
Ethdebugger.prototype.startDebugging = function (blockNumber, txIndex, tx) {
if (this.traceManager.isLoading) {
return
}
console.log('loading trace...')
this.tx = tx
var self = this
this.traceManager.resolveTrace(tx, function (success) {
console.log('trace loaded ' + success)
if (success) {
self.trigger('newTraceLoaded')
} else {
console.log('trace not loaded')
}
})
}
module.exports = Ethdebugger

@ -0,0 +1,36 @@
'use strict'
var BasicPanel = require('./BasicPanel')
var util = require('./helpers/ui')
var yo = require('yo-yo')
function MemoryPanel (_parent, _traceManager) {
this.parent = _parent
this.traceManager = _traceManager
this.basicPanel = new BasicPanel('Memory')
this.init()
}
MemoryPanel.prototype.render = function () {
return (
yo`${this.basicPanel.render()}`
)
}
MemoryPanel.prototype.init = function () {
var self = this
this.parent.register('indexChanged', this, function (index) {
if (index < 0) return
if (self.parent.currentStepIndex !== index) return
self.traceManager.getMemoryAt(index, function (error, memory) {
if (error) {
console.log(error)
} else if (self.parent.currentStepIndex === index) {
self.basicPanel.data = util.formatMemory(memory, 16)
self.basicPanel.update()
}
})
})
}
module.exports = MemoryPanel

@ -0,0 +1,64 @@
'use strict'
var style = require('./sliderStyles')
var util = require('./helpers/global')
var EventManager = require('./lib/eventManager')
var yo = require('yo-yo')
var ui = require('./helpers/ui')
function Slider (_traceManager) {
util.extend(this, new EventManager())
this.traceManager = _traceManager
this.max
this.disabled = true
this.view
}
Slider.prototype.render = function () {
var self = this
var view = yo`<div>
<input
ref='rule'
id='slider'
style=${ui.formatCss(style.rule)}
type='range'
min=0
max=${this.max}
onmouseup=${function () { self.onMouseUp() }}
disabled=${this.disabled} />
</div>`
if (!this.view) {
this.view = view
}
return view
}
Slider.prototype.init = function () {
var self = this
this.traceManager.getLength(function (error, length) {
if (error) {
console.log(error)
} else {
self.max = length
self.disabled = length === 0
yo.update(self.view, self.render())
self.setValue(0)
}
})
}
Slider.prototype.onMouseUp = function (event) {
var value = document.getElementById('slider').value
this.trigger('moved', [parseInt(value)])
}
Slider.prototype.setValue = function (value) {
var slider = document.getElementById('slider')
var diff = value - slider.value
if (diff > 0) {
slider.stepUp(diff)
} else {
slider.stepDown(Math.abs(diff))
}
}
module.exports = Slider

@ -0,0 +1,43 @@
'use strict'
var BasicPanel = require('./BasicPanel')
var yo = require('yo-yo')
function StackPanel (_parent, _traceManager) {
this.parent = _parent
this.traceManager = _traceManager
this.basicPanel = new BasicPanel('Stack')
this.init()
}
StackPanel.prototype.render = function () {
return (
yo`${this.basicPanel.render()}`
)
}
StackPanel.prototype.init = function () {
var self = this
this.parent.register('indexChanged', this, function (index) {
if (index < 0) return
if (self.parent.currentStepIndex !== index) return
self.traceManager.getStackAt(index, function (error, stack) {
if (error) {
console.log(error)
} else if (self.parent.currentStepIndex === index) {
self.basicPanel.data = self.format(stack)
self.basicPanel.update()
}
})
})
}
StackPanel.prototype.format = function (stack) {
var ret = ''
for (var key in stack) {
ret += stack[key] + '\n'
}
return ret
}
module.exports = StackPanel

@ -0,0 +1,129 @@
'use strict'
var ButtonNavigator = require('./ButtonNavigator')
var Slider = require('./Slider')
var style = require('./basicStyles')
var util = require('./helpers/global')
var EventManager = require('./lib/eventManager')
var yo = require('yo-yo')
var ui = require('./helpers/ui')
function StepManager (_parent, _traceManager) {
util.extend(this, new EventManager())
this.parent = _parent
this.traceManager = _traceManager
var self = this
this.parent.register('newTraceLoaded', this, function () {
self.traceManager.getLength(function (length) {
self.slider.max = length
self.slider.init()
self.init()
})
})
this.slider = new Slider(this.traceManager)
this.slider.register('moved', this, function (step) {
self.sliderMoved(step)
})
this.buttonNavigator = new ButtonNavigator(this.traceManager)
this.buttonNavigator.register('stepIntoBack', this, function () {
self.stepIntoBack()
})
this.buttonNavigator.register('stepIntoForward', this, function () {
self.stepIntoForward()
})
this.buttonNavigator.register('stepOverBack', this, function () {
self.stepOverBack()
})
this.buttonNavigator.register('stepOverForward', this, function () {
self.stepOverForward()
})
this.buttonNavigator.register('jumpNextCall', this, function () {
self.jumpNextCall()
})
}
StepManager.prototype.render = function () {
return (
yo`<div style=${ui.formatCss(style.container)}>
${this.slider.render()}
${this.buttonNavigator.render()}
</div>`
)
}
StepManager.prototype.init = function () {
this.slider.setValue(0)
this.changeState(0)
}
StepManager.prototype.newTraceAvailable = function () {
this.init()
}
StepManager.prototype.sliderMoved = function (step) {
if (!this.traceManager.inRange(step)) {
return
}
this.changeState(step)
}
StepManager.prototype.stepIntoForward = function () {
if (!this.traceManager.isLoaded()) {
return
}
var step = this.currentStepIndex + 1
if (!this.traceManager.inRange(step)) {
return
}
this.slider.setValue(step)
this.changeState(step)
}
StepManager.prototype.stepIntoBack = function () {
if (!this.traceManager.isLoaded()) {
return
}
var step = this.currentStepIndex - 1
if (!this.traceManager.inRange(step)) {
return
}
this.slider.setValue(step)
this.changeState(step)
}
StepManager.prototype.stepOverForward = function () {
if (!this.traceManager.isLoaded()) {
return
}
var step = this.traceManager.findStepOverForward(this.currentStepIndex)
this.slider.setValue(step)
this.changeState(step)
}
StepManager.prototype.stepOverBack = function () {
if (!this.traceManager.isLoaded()) {
return
}
var step = this.traceManager.findStepOverBack(this.currentStepIndex)
this.slider.setValue(step)
this.changeState(step)
}
StepManager.prototype.jumpNextCall = function () {
if (!this.traceManager.isLoaded()) {
return
}
var step = this.traceManager.findNextCall(this.currentStepIndex)
this.slider.setValue(step)
this.changeState(step)
}
StepManager.prototype.changeState = function (step) {
this.currentStepIndex = step
this.buttonNavigator.stepChanged(step)
this.trigger('stepChanged', [step])
}
module.exports = StepManager

@ -0,0 +1,116 @@
'use strict'
var yo = require('yo-yo')
function Sticker (_parent, _traceManager) {
this.parent = _parent
this.traceManager = _traceManager
this.vmTraceStep
this.step
this.addmemory
this.gas
this.remainingGas
this.view
this.init()
}
Sticker.prototype.render = function () {
var view = yo`<div>
<table>
<tbody>
<tr key='vmtracestep'>
<td>
vmtracestep
</td>
<td>
${this.vmTraceStep}
</td>
</tr>
<tr key='step'>
<td>
step
</td>
<td>
${this.step}
</td>
</tr>
<tr key='addmemory'>
<td>
add memory
</td>
<td>
${this.addmemory}
</td>
</tr>
<tr key='gas'>
<td>
gas
</td>
<td>
${this.gas}
</td>
</tr>
<tr key='remaininggas'>
<td>
remaining gas
</td>
<td>
${this.remainingGas}
</td>
</tr>
</tbody>
</table>
</div>`
if (!this.view) {
this.view = view
}
return view
}
Sticker.prototype.init = function () {
var self = this
this.parent.register('indexChanged', this, function (index) {
if (index < 0) return
self.vmTraceStep = index
self.traceManager.getCurrentStep(index, function (error, step) {
if (error) {
console.log(error)
} else {
self.step = step
yo.update(self.view, self.render())
}
})
self.traceManager.getMemExpand(index, function (error, addmem) {
if (error) {
console.log(error)
} else {
self.addmemory = addmem
yo.update(self.view, self.render())
}
})
self.traceManager.getStepCost(index, function (error, gas) {
if (error) {
console.log(error)
} else {
self.gas = gas
yo.update(self.view, self.render())
}
})
self.traceManager.getRemainingGas(index, function (error, remaingas) {
if (error) {
console.log(error)
} else {
self.remainingGas = remaingas
yo.update(self.view, self.render())
}
})
})
}
module.exports = Sticker

@ -0,0 +1,43 @@
'use strict'
var BasicPanel = require('./BasicPanel')
var yo = require('yo-yo')
function StoragePanel (_parent, _traceManager) {
this.parent = _parent
this.traceManager = _traceManager
this.basicPanel = new BasicPanel('Storage')
this.init()
}
StoragePanel.prototype.render = function () {
return (
yo`${this.basicPanel.render()}`
)
}
StoragePanel.prototype.init = function () {
var self = this
this.parent.register('indexChanged', this, function (index) {
if (index < 0) return
if (self.parent.currentStepIndex !== index) return
self.traceManager.getStorageAt(index, self.parent.tx, function (error, storage) {
if (error) {
console.log(error)
} else if (self.parent.currentStepIndex === index) {
self.basicPanel.data = self.formatStorage(storage)
self.basicPanel.update()
}
})
})
}
StoragePanel.prototype.formatStorage = function (storage) {
var ret = ''
for (var key in storage) {
ret += key + ' ' + storage[key] + '\n'
}
return ret
}
module.exports = StoragePanel

@ -0,0 +1,118 @@
var style = require('./basicStyles')
var util = require('./helpers/global')
var EventManager = require('./lib/eventManager')
var traceHelper = require('./helpers/traceHelper')
var yo = require('yo-yo')
var ui = require('./helpers/ui')
function TxBrowser (_web3) {
util.extend(this, new EventManager())
this.web3 = _web3
this.blockNumber
this.txNumber = '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51'
this.hash
this.from
this.to
this.view
}
/*
getInitialState: function () {
return {blockNumber: '1000110', txNumber: '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51', from: '', to: '', hash: ''}
},
*/
// creation 0xa9619e1d0a35b2c1d686f5b661b3abd87f998d2844e8e9cc905edb57fc9ce349
// invokation 0x71a6d583d16d142c5c3e8903060e8a4ee5a5016348a9448df6c3e63b68076ec4
// test:
// creation: 0x72908de76f99fca476f9e3a3b5d352f350a98cd77d09cebfc59ffe32a6ecaa0b
// invokation: 0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51
TxBrowser.prototype.submit = function () {
if (!this.txNumber) {
return
}
var tx
try {
if (this.txNumber.indexOf('0x') !== -1) {
tx = this.web3.eth.getTransaction(this.txNumber)
} else {
tx = this.web3.eth.getTransactionFromBlock(this.blockNumber, this.txNumber)
}
} catch (e) {
console.log(e)
}
console.log(JSON.stringify(tx))
if (tx) {
if (!tx.to) {
tx.to = traceHelper.contractCreationToken('0')
}
this.from = tx.from
this.to = tx.to
this.hash = tx.hash
yo.update(this.view, this.render())
this.trigger('newTxRequested', [this.blockNumber, this.txNumber, tx])
} else {
console.log('cannot find ' + this.blockNumber + ' ' + this.txNumber)
}
}
TxBrowser.prototype.updateTxhash = function (ev) {
this.hash = ev.target.value
}
TxBrowser.prototype.updateBlockN = function (ev) {
this.blockNumber = ev.target.value
}
TxBrowser.prototype.updateTxN = function (ev) {
this.txNumber = ev.target.value
}
TxBrowser.prototype.render = function () {
var self = this
var view = yo`<div style=${ui.formatCss(style.container)}>
<input onchange=${this.updateBlockN} type='text' placeholder=${'Block number (default 1000110)' + this.blockNumber}></input>
<input onchange=${this.updateTxN} type='text' value=${this.txNumber} placeholder=${'Transaction Number or hash (default 2) ' + this.txNumber}></input>
<button onclick=${function () { self.submit() }}>
Get
</button>
<div style=${ui.formatCss(style.transactionInfo)}>
<table>
<tbody>
<tr>
<td>
Hash:
</td>
<td>
${this.hash}
</td>
</tr>
<tr>
<td>
From:
</td>
<td>
${this.from}
</td>
</tr>
<tr>
<td>
To:
</td>
<td>
${this.to}
</td>
</tr>
</tbody>
</table>
</div>
</div>`
if (!this.view) {
this.view = view
}
return view
}
module.exports = TxBrowser

@ -0,0 +1,73 @@
'use strict'
var Sticker = require('./Sticker')
var style = require('./basicStyles')
var ASMCode = require('./ASMCode')
var CalldataPanel = require('./CalldataPanel')
var MemoryPanel = require('./MemoryPanel')
var CallstackPanel = require('./CallstackPanel')
var StackPanel = require('./StackPanel')
var StoragePanel = require('./StoragePanel')
var yo = require('yo-yo')
var ui = require('./helpers/ui')
function VmDebugger (_parent, _traceManager, _web3) {
this.sticker = new Sticker(_parent, _traceManager, _web3)
this.asmCode = new ASMCode(_parent, _traceManager, _web3)
this.stackPanel = new StackPanel(_parent, _traceManager)
this.storagePanel = new StoragePanel(_parent, _traceManager)
this.memoryPanel = new MemoryPanel(_parent, _traceManager)
this.calldataPanel = new CalldataPanel(_parent, _traceManager)
this.CallstackPanel = new CallstackPanel(_parent, _traceManager)
this.view
var self = this
_parent.register('newTraceLoaded', this, function () {
self.view.style.display = 'block'
})
_parent.register('traceUnloaded', this, function () {
self.view.style.display = 'none'
})
}
VmDebugger.prototype.render = function () {
var view = yo`<div style='display:none'>
<div style=${ui.formatCss(style.container)}>
<table>
<tbody>
<tr>
<td>
${this.asmCode.render()}
<div style=${ui.formatCss(style.inline, style.sticker)}>
${this.sticker.render()}
</div>
</td>
<td>
${this.stackPanel.render()}
</td>
</tr>
<tr>
<td>
${this.storagePanel.render()}
</td>
<td>
${this.memoryPanel.render()}
</td>
</tr>
<tr>
<td>
${this.calldataPanel.render()}
</td>
<td>
${this.CallstackPanel.render()}
</td>
</tr>
</tbody>
</table>
</div>
</div>`
if (!this.view) {
this.view = view
}
return view
}
module.exports = VmDebugger

@ -1,64 +0,0 @@
'use strict'
var React = require('react')
var style = require('./basicStyles')
module.exports = React.createClass({
contextTypes: {
codeManager: React.PropTypes.object,
root: React.PropTypes.object,
tx: React.PropTypes.object
},
getInitialState: function () {
return {
code: '',
address: ''
}
},
render: function () {
return (
<select size='10' ref='itemsList' style={style.instructionsList}>
{this.renderAssemblyItems()}
</select>
)
},
componentDidMount: function () {
var self = this
this.context.codeManager.register('indexChanged', this, this.indexChanged)
this.context.codeManager.register('codeChanged', this, this.codeChanged)
this.context.codeManager.register('loadingCode', this, function (address) {
})
this.context.root.register('indexChanged', this, function (index) {
self.context.codeManager.resolveStep(index, self.context.tx)
})
},
indexChanged: function (index) {
this.refs.itemsList.value = index
},
codeChanged: function (code, address, index) {
this.setState({
code: code,
address: address
})
this.refs.itemsList.value = index
},
shouldComponentUpdate: function (nextProps, nextState) {
if (nextState.address === this.state.address) {
return false
}
return true
},
renderAssemblyItems: function () {
if (this.state && this.state.code) {
return this.state.code.map(function (item, i) {
return <option key={i} value={i}>{item}</option>
})
}
}
})

@ -1,25 +0,0 @@
'use strict'
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>
<div style={style.panel.tableContainer}>
<pre style={Object.assign(style.panel.table, style.font)} >{this.props.data}</pre>
</div>
</div>
)
}
})

@ -1,21 +1,21 @@
'use strict'
module.exports = {
font: {
'fontFamily': 'arial,sans-serif'
'font-family': 'arial,sans-serif'
},
container: {
'margin': '10px',
'padding': '5px'
},
address: {
'fontStyle': 'italic'
'font-style': 'italic'
},
instructionsList: {
'width': '320px',
'height': '300px'
},
transactionInfo: {
'marginTop': '5px'
'margin-top': '5px'
},
panel: {
container: {
@ -24,14 +24,14 @@ module.exports = {
},
tableContainer: {
'height': '300px',
'overflowY': 'auto'
'overflow-y': 'auto'
},
table: {
'padding': '5px'
},
title: {
'padding': '5px',
'fontStyle': 'italic'
'font-style': 'italic'
}
},
hidden: {
@ -41,7 +41,7 @@ module.exports = {
'display': 'block'
},
sticker: {
'verticalAlign': 'top',
'vertical-align': 'top',
'margin': '5px'
},
inline: {

@ -1,63 +0,0 @@
'use strict'
var React = require('react')
module.exports = React.createClass({
contextTypes: {
traceManager: React.PropTypes.object
},
propTypes: {
stepIntoBack: React.PropTypes.func.isRequired,
stepIntoForward: React.PropTypes.func.isRequired,
stepOverBack: React.PropTypes.func.isRequired,
stepOverForward: React.PropTypes.func.isRequired,
jumpNextCall: React.PropTypes.func.isRequired
},
render: function () {
return (
<div>
<button ref='intoback' onClick={this.props.stepIntoBack}>
Step Into Back
</button>
<button ref='overback' onClick={this.props.stepOverBack}>
Step Over Back
</button>
<button ref='overforward' onClick={this.props.stepOverForward}>
Step Over Forward
</button>
<button ref='intoforward' onClick={this.props.stepIntoForward}>
Step Into Forward
</button>
<button ref='nextcall' onClick={this.props.jumpNextCall}>
Jump Next Call
</button>
</div>
)
},
shouldComponentUpdate: function () {
return false
},
stepChanged: function (step) {
this.refs.intoback.disabled = step <= 0
this.refs.overback.disabled = step <= 0
if (!this.context.traceManager) {
this.refs.intoforward.disabled = true
this.refs.overforward.disabled = true
this.refs.nextcall.disabled = true
} else {
var self = this
this.context.traceManager.getLength(function (error, length) {
if (error) {
console.log(error)
} else {
self.refs.intoforward.disabled = step >= length - 1
self.refs.overforward.disabled = step >= length - 1
self.refs.nextcall.disabled = step >= length - 1
}
})
}
}
})

@ -1,49 +0,0 @@
'use strict'
var React = require('react')
var BasicPanel = require('./basicPanel')
module.exports = React.createClass({
contextTypes: {
traceManager: React.PropTypes.object,
codeManager: React.PropTypes.object,
root: React.PropTypes.object
},
getInitialState: function () {
return {
data: null
}
},
render: function () {
return (
<BasicPanel name='CallData' data={this.state.data} />
)
},
componentDidMount: function () {
var self = this
this.context.root.register('indexChanged', this, function (index) {
if (index < 0) return
if (self.context.root.ethDebuggerSelectedItem !== index) return
self.context.traceManager.getCallDataAt(index, function (error, calldata) {
if (error) {
console.log(error)
} else if (self.context.root.ethDebuggerSelectedItem === index) {
self.setState({
data: self.format(calldata)
})
}
})
})
},
format: function (calldata) {
var ret = ''
for (var key in calldata) {
ret += calldata[key] + '\n'
}
return ret
}
})

@ -1,49 +0,0 @@
'use strict'
var React = require('react')
var BasicPanel = require('./basicPanel')
module.exports = React.createClass({
contextTypes: {
traceManager: React.PropTypes.object,
codeManager: React.PropTypes.object,
root: React.PropTypes.object
},
getInitialState: function () {
return {
data: null
}
},
render: function () {
return (
<BasicPanel name='CallStack' data={this.state.data} />
)
},
componentDidMount: function () {
var self = this
this.context.root.register('indexChanged', this, function (index) {
if (index < 0) return
if (self.context.root.ethDebuggerSelectedItem !== index) return
self.context.traceManager.getCallStackAt(index, function (error, callstack) {
if (error) {
console.log(error)
} else if (self.context.root.ethDebuggerSelectedItem === index) {
self.setState({
data: self.format(callstack)
})
}
})
})
},
format: function (callstack) {
var ret = ''
for (var key in callstack) {
ret += callstack[key] + '\n'
}
return ret
}
})

@ -1,78 +0,0 @@
'use strict'
var React = require('react')
var TxBrowser = require('./txBrowser')
var StepManager = require('./stepManager')
var VmDebugger = require('./vmDebugger')
var style = require('./basicStyles')
var util = require('./helpers/global')
var EventManager = require('./lib/eventManager')
module.exports = React.createClass({
ethDebuggerSelectedItem: -1,
getInitialState: function () {
return {
currentStepIndex: -1, // index of the selected item in the vmtrace
tx: null
}
},
childContextTypes: {
web3: React.PropTypes.object,
traceManager: React.PropTypes.object,
codeManager: React.PropTypes.object,
root: React.PropTypes.object,
tx: React.PropTypes.object
},
getChildContext: function () {
return {
web3: this.props.context.web3,
traceManager: this.props.context.traceManager,
codeManager: this.props.context.codeManager,
root: this,
tx: this.state.tx
}
},
render: function () {
return (
<div style={style.font}>
<h1 style={style.container}>Eth Debugger</h1>
<TxBrowser onNewTxRequested={this.startDebugging} />
<StepManager ref='stepManager' onStepChanged={this.stepChanged} />
<VmDebugger ref='assemblyitemsbrowser' currentStepIndex={this.state.currentStepIndex} />
</div>
)
},
stepChanged: function (stepIndex) {
this.trigger('indexChanged', [stepIndex])
this.setState({
currentStepIndex: stepIndex
})
},
componentWillMount: function () {
util.extend(this, new EventManager())
},
startDebugging: function (blockNumber, txIndex, tx) {
if (this.props.context.traceManager.isLoading) {
return
}
console.log('loading trace...')
this.setState({
tx: tx
})
var self = this
this.props.context.traceManager.resolveTrace(tx, function (success) {
console.log('trace loaded ' + success)
if (success) {
self.trigger('newTraceLoaded')
} else {
console.log('trace not loaded')
}
})
}
})

@ -1,19 +1,12 @@
'use strict'
var Web3 = require('web3')
var Web3Admin = require('../util/web3Admin')
var TraceManager = require('../trace/traceManager')
var CodeManager = require('../code/codeManager')
module.exports = {
loadContext: function () {
loadWeb3: function () {
var web3 = new Web3()
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'))
Web3Admin.extend(web3)
var traceManager = new TraceManager(web3)
return {
web3: web3,
traceManager: traceManager,
codeManager: new CodeManager(web3, traceManager)
}
return web3
}
}

@ -31,5 +31,15 @@ module.exports = {
ret.raw += ' ' + raw
}
return ret
},
formatCss: function (css1, css2) {
var ret = ''
for (var arg in arguments) {
for (var k in arguments[arg]) {
ret += k + ':' + arguments[arg][k] + ';'
}
}
return ret
}
}

@ -1,10 +1,9 @@
'use strict'
var ReactDOM = require('react-dom')
var React = require('react')
var util = require('./helpers/init')
var Debugger = require('./debugger')
var Debugger = require('./Ethdebugger')
ReactDOM.render(
<Debugger context={util.loadContext()} />,
document.getElementById('app')
)
function init () {
var ethdebugger = new Debugger()
document.getElementById('app').appendChild(ethdebugger.render())
}
init()

@ -1,43 +0,0 @@
'use strict'
var React = require('react')
var BasicPanel = require('./basicPanel')
var util = require('./helpers/ui')
module.exports = React.createClass({
contextTypes: {
traceManager: React.PropTypes.object,
web3: React.PropTypes.object,
codeManager: React.PropTypes.object,
root: React.PropTypes.object
},
getInitialState: function () {
return {
data: null
}
},
render: function () {
return (
<BasicPanel name='Memory' data={this.state.data} />
)
},
componentDidMount: function () {
var self = this
this.context.root.register('indexChanged', this, function (index) {
if (index < 0) return
if (self.context.root.ethDebuggerSelectedItem !== index) return
self.context.traceManager.getMemoryAt(index, function (error, memory) {
if (error) {
console.log(error)
} else if (self.context.root.ethDebuggerSelectedItem === index) {
self.setState({
data: util.formatMemory(memory, 16)
})
}
})
})
}
})

@ -1,55 +0,0 @@
'use strict'
var React = require('react')
var style = require('./sliderStyles')
module.exports = React.createClass({
contextTypes: {
traceManager: React.PropTypes.object
},
propTypes: {
onChange: React.PropTypes.func.isRequired
},
getDefaultProps: function () {
return {
min: 0,
max: 1
}
},
render: function () {
return (
<div>
<input
ref='rule'
style={style.rule}
type='range'
min={this.props.min}
max={this.props.max}
onMouseUp={this.onMouseUp} />
</div>
)
},
shouldComponentUpdate: function (nextProps, nextState) {
return (nextProps.max !== this.props.max || nextProps.min !== this.props.min)
},
componentDidMount: function () {
this.setValue(0)
},
onMouseUp: function (event) {
this.props.onChange(parseInt(this.refs.rule.value))
},
setValue: function (value) {
var diff = value - this.refs.rule.value
if (diff > 0) {
this.refs.rule.stepUp(diff)
} else {
this.refs.rule.stepDown(Math.abs(diff))
}
}
})

@ -1,49 +0,0 @@
'use strict'
var React = require('react')
var BasicPanel = require('./basicPanel')
module.exports = React.createClass({
contextTypes: {
traceManager: React.PropTypes.object,
codeManager: React.PropTypes.object,
root: React.PropTypes.object
},
getInitialState: function () {
return {
data: null
}
},
render: function () {
return (
<BasicPanel name='Stack' data={this.state.data} />
)
},
componentDidMount: function () {
var self = this
this.context.root.register('indexChanged', this, function (index) {
if (index < 0) return
if (self.context.root.ethDebuggerSelectedItem !== index) return
self.context.traceManager.getStackAt(index, function (error, stack) {
if (error) {
console.log(error)
} else if (self.context.root.ethDebuggerSelectedItem === index) {
self.setState({
data: self.format(stack)
})
}
})
})
},
format: function (stack) {
var ret = ''
for (var key in stack) {
ret += stack[key] + '\n'
}
return ret
}
})

@ -1,139 +0,0 @@
'use strict'
var React = require('react')
var ButtonNavigator = require('./buttonNavigator')
var Slider = require('./slider')
var style = require('./basicStyles')
module.exports = React.createClass({
propTypes: {
onStepChanged: React.PropTypes.func.isRequired
},
contextTypes: {
traceManager: React.PropTypes.object,
root: React.PropTypes.object
},
getInitialState: function () {
return {
currentStepIndex: 0,
traceLength: 0
}
},
render: function () {
return (
<div style={style.container}>
<Slider
ref='slider'
onChange={this.sliderMoved}
min='0'
max={this.state.traceLength} />
<ButtonNavigator
ref='buttons'
stepIntoBack={this.stepIntoBack}
stepIntoForward={this.stepIntoForward}
stepOverBack={this.stepOverBack}
stepOverForward={this.stepOverForward}
jumpNextCall={this.jumpToNextCall}
max={this.state.traceLength} />
</div>
)
},
componentDidMount: function () {
var self = this
this.context.root.register('newTraceLoaded', this, function () {
self.newTraceAvailable()
})
this.changeState(-1)
},
updateGlobalSelectedItem: function (value) {
this.context.root.ethDebuggerSelectedItem = value
},
init: function () {
this.refs.slider.setValue(0)
this.changeState(0)
},
newTraceAvailable: function () {
this.init()
var self = this
this.context.traceManager.getLength(function (error, length) {
if (error) {
console.log(error)
} else {
self.setState({ traceLength: length })
}
})
},
sliderMoved: function (step) {
if (!this.context.traceManager.inRange(step)) {
return
}
this.changeState(step)
},
stepIntoForward: function () {
if (!this.context.traceManager.isLoaded()) {
return
}
var step = this.state.currentStepIndex + 1
if (!this.context.traceManager.inRange(step)) {
return
}
this.refs.slider.setValue(step)
this.changeState(step)
},
stepIntoBack: function () {
if (!this.context.traceManager.isLoaded()) {
return
}
var step = this.state.currentStepIndex - 1
if (!this.context.traceManager.inRange(step)) {
return
}
this.refs.slider.setValue(step)
this.changeState(step)
},
stepOverForward: function () {
if (!this.context.traceManager.isLoaded()) {
return
}
var step = this.context.traceManager.findStepOverForward(this.state.currentStepIndex)
this.refs.slider.setValue(step)
this.changeState(step)
},
stepOverBack: function () {
if (!this.context.traceManager.isLoaded()) {
return
}
var step = this.context.traceManager.findStepOverBack(this.state.currentStepIndex)
this.refs.slider.setValue(step)
this.changeState(step)
},
jumpToNextCall: function () {
if (!this.context.traceManager.isLoaded()) {
return
}
var step = this.context.traceManager.findNextCall(this.state.currentStepIndex)
this.refs.slider.setValue(step)
this.changeState(step)
},
changeState: function (step) {
this.updateGlobalSelectedItem(step)
this.setState({
currentStepIndex: step
})
this.refs.buttons.stepChanged(step)
this.props.onStepChanged(step)
}
})

@ -1,138 +0,0 @@
'use strict'
var React = require('react')
module.exports = React.createClass({
contextTypes: {
traceManager: React.PropTypes.object,
codeManager: React.PropTypes.object,
root: React.PropTypes.object
},
getInitialState: function () {
return {
vmTraceStep: '',
step: '',
addmemory: '',
gas: '',
remainingGas: ''
}
},
render: function () {
return (
<div>
<table>
<tbody>
<tr key='vmtracestep'>
<td>
vmtracestep
</td>
<td>
{this.state.vmTraceStep}
</td>
</tr>
<tr key='step'>
<td>
step
</td>
<td>
{this.state.step}
</td>
</tr>
<tr key='addmemory'>
<td>
add memory
</td>
<td>
{this.state.addmemory}
</td>
</tr>
<tr key='gas'>
<td>
gas
</td>
<td>
{this.state.gas}
</td>
</tr>
<tr key='remaininggas'>
<td>
remaining gas
</td>
<td>
{this.state.remainingGas}
</td>
</tr>
</tbody>
</table>
</div>
)
},
renderItems: function () {
if (this.state.data) {
var ret = []
for (var key in this.state.data) {
ret.push(
<tr key={key}>
<td>
{this.props.data[key]}
</td>
</tr>)
}
return ret
}
return null
},
componentDidMount: function () {
var self = this
this.context.root.register('indexChanged', this, function (index) {
if (index < 0) return
self.setState({
vmTraceStep: index
})
self.context.traceManager.getCurrentStep(index, function (error, step) {
if (error) {
console.log(error)
} else {
self.setState({
step: step
})
}
})
self.context.traceManager.getMemExpand(index, function (error, addmem) {
if (error) {
console.log(error)
} else {
self.setState({
addmemory: addmem
})
}
})
self.context.traceManager.getStepCost(index, function (error, gas) {
if (error) {
console.log(error)
} else {
self.setState({
gas: gas
})
}
})
self.context.traceManager.getRemainingGas(index, function (error, remaingas) {
if (error) {
console.log(error)
} else {
self.setState({
remainingGas: remaingas
})
}
})
})
}
})

@ -1,50 +0,0 @@
'use strict'
var React = require('react')
var BasicPanel = require('./basicPanel')
module.exports = React.createClass({
contextTypes: {
traceManager: React.PropTypes.object,
tx: React.PropTypes.object,
codeManager: React.PropTypes.object,
root: React.PropTypes.object
},
getInitialState: function () {
return {
data: null
}
},
render: function () {
return (
<BasicPanel name='Storage' data={this.state.data} />
)
},
componentDidMount: function () {
var self = this
this.context.root.register('indexChanged', this, function (index) {
if (index < 0) return
if (self.context.root.ethDebuggerSelectedItem !== index) return
self.context.traceManager.getStorageAt(index, self.context.tx, function (error, storage) {
if (error) {
console.log(error)
} else if (self.context.root.ethDebuggerSelectedItem === index) {
self.setState({
data: self.formatStorage(storage)
})
}
})
})
},
formatStorage: function (storage) {
var ret = ''
for (var key in storage) {
ret += key + ' ' + storage[key] + '\n'
}
return ret
}
})

@ -1,97 +0,0 @@
'use strict'
var React = require('react')
var style = require('./basicStyles')
var traceHelper = require('./helpers/traceHelper')
module.exports = React.createClass({
contextTypes: {
web3: React.PropTypes.object
},
propTypes: {
onNewTxRequested: React.PropTypes.func.isRequired
},
getInitialState: function () {
return {blockNumber: '1000110', txNumber: '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51', from: '', to: '', hash: ''}
},
// creation 0xa9619e1d0a35b2c1d686f5b661b3abd87f998d2844e8e9cc905edb57fc9ce349
// invokation 0x71a6d583d16d142c5c3e8903060e8a4ee5a5016348a9448df6c3e63b68076ec4
// test:
// creation: 0x72908de76f99fca476f9e3a3b5d352f350a98cd77d09cebfc59ffe32a6ecaa0b
// invokation: 0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51
submit: function () {
var tx
if (this.state.txNumber.indexOf('0x') !== -1) {
tx = this.context.web3.eth.getTransaction(this.state.txNumber)
} else {
tx = this.context.web3.eth.getTransactionFromBlock(this.state.blockNumber, this.state.txNumber)
}
console.log(JSON.stringify(tx))
if (tx) {
if (!tx.to) {
tx.to = traceHelper.contractCreationToken('0')
}
this.setState({from: tx.from, to: tx.to, hash: tx.hash})
this.props.onNewTxRequested(this.state.blockNumber, parseInt(this.state.txNumber), tx)
} else {
console.log('cannot find ' + this.state.blockNumber + ' ' + this.state.txNumber)
}
},
updateTxhash: function (ev) {
this.state.hash = ev.target.value
},
updateBlockN: function (ev) {
this.state.blockNumber = ev.target.value
},
updateTxN: function (ev) {
this.state.txNumber = ev.target.value
},
render: function () {
return (
<div style={style.container}>
<input onChange={this.updateBlockN} type='text' placeholder={'Block number (default 1000110)' + this.state.blockNumber}></input>
<input onChange={this.updateTxN} type='text' placeholder={'Transaction Number or hash (default 2) ' + this.state.txNumber}></input>
<button onClick={this.submit}>
Get
</button>
<div style={style.transactionInfo}>
<table>
<tbody>
<tr>
<td>
Hash:
</td>
<td>
{this.state.hash}
</td>
</tr>
<tr>
<td>
From:
</td>
<td>
{this.state.from}
</td>
</tr>
<tr>
<td>
To:
</td>
<td>
{this.state.to}
</td>
</tr>
</tbody>
</table>
</div>
</div>
)
}
})

@ -1,52 +0,0 @@
'use strict'
var React = require('react')
var Sticker = require('./sticker')
var style = require('./basicStyles')
var ASMCode = require('./asmCode')
var CalldataPanel = require('./calldataPanel')
var MemoryPanel = require('./memoryPanel')
var CallstackPanel = require('./callstackPanel')
var StackPanel = require('./stackPanel')
var StoragePanel = require('./storagePanel')
module.exports = React.createClass({
render: function () {
return (
<div style={this.props.vmTrace === null ? style.hidden : style.display}>
<div style={style.container}>
<table>
<tbody>
<tr>
<td>
<ASMCode />
<div style={Object.assign(style.inline, style.sticker)}>
<Sticker />
</div>
</td>
<td>
<StackPanel />
</td>
</tr>
<tr>
<td>
<StoragePanel />
</td>
<td>
<MemoryPanel />
</td>
</tr>
<tr>
<td>
<CalldataPanel />
</td>
<td>
<CallstackPanel />
</td>
</tr>
</tbody>
</table>
</div>
</div>
)
}
})

@ -4,14 +4,17 @@ var init = require('../src/helpers/init')
var txInvokation = require('./resources/contractInvokationTx')
var TestTraceRetriever = require('./TestTraceRetriever')
var contractCode = require('./resources/contractInvokationCode')
var TraceManager = require('../src/trace/traceManager')
var CodeManager = require('../src/code/codeManager')
tape('CodeManager', function (t) {
var codeManager
var context = init.loadContext()
codeManager = context.codeManager
context.traceManager.traceRetriever = new TestTraceRetriever()
var web3 = init.loadWeb3()
var traceManager = new TraceManager(web3)
traceManager.traceRetriever = new TestTraceRetriever()
codeManager = new CodeManager(web3, traceManager)
codeManager.codeResolver.cacheExecutingCode('0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5', contractCode) // so a call to web3 is not necessary
context.traceManager.resolveTrace(txInvokation, function (success) {
traceManager.resolveTrace(txInvokation, function (success) {
if (!success) {
t.fail(' - traceManager.resolveTrace - failed')
} else {

@ -3,9 +3,9 @@ var tape = require('tape')
var init = require('../src/helpers/init')
tape('index', function (t) {
t.test('loadContext - web3', function (st) {
var context = init.loadContext()
st.notEqual(context.web3, undefined)
st.notEqual(context.web3, null)
var web3 = init.loadWeb3()
st.notEqual(web3, undefined)
st.notEqual(web3, null)
st.end()
})
})

@ -9,8 +9,8 @@ tape('TraceManager', function (t) {
var traceManager
t.test('TraceManager.init', function (st) {
var context = init.loadContext()
traceManager = new TraceManager(context.web3)
var web3 = init.loadWeb3()
traceManager = new TraceManager(web3)
traceManager.traceRetriever = new TestTraceRetriever()
st.end()
})

Loading…
Cancel
Save