remix-project mirror
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
remix-project/remix-debugger/src/ui/Ethdebugger.js

185 lines
5.8 KiB

'use strict'
var TxBrowser = require('./TxBrowser')
var StepManager = require('./StepManager')
var remixCore = require('remix-core')
var TraceManager = remixCore.trace.TraceManager
var VmDebugger = require('./VmDebugger')
var remixLib = require('remix-lib')
var global = remixLib.global
var init = remixLib.init
var executionContext = remixLib.execution.executionContext
var EventManager = remixLib.EventManager
var yo = require('yo-yo')
var csjs = require('csjs-inject')
var Web3Providers = remixLib.vm.Web3Providers
var DummyProvider = remixLib.vm.DummyProvider
var CodeManager = remixCore.code.CodeManager
var remixSolidity = require('remix-solidity')
var SolidityProxy = remixSolidity.SolidityProxy
var InternalCallTree = remixSolidity.InternalCallTree
var css = csjs`
.statusMessage {
margin-left: 15px;
}
.innerShift {
padding: 2px;
margin-left: 10px;
}
`
function Ethdebugger (opts) {
this.opts = opts || {}
if (!this.opts.compilationResult) this.opts.compilationResult = () => { return null }
var self = this
this.event = new EventManager()
this.currentStepIndex = -1
this.tx
this.statusMessage = ''
this.view
this.web3Providers = new Web3Providers()
this.addProvider('DUMMYWEB3', new DummyProvider())
this.switchProvider('DUMMYWEB3')
this.traceManager = new TraceManager()
this.codeManager = new CodeManager(this.traceManager)
this.solidityProxy = new SolidityProxy(this.traceManager, this.codeManager)
var callTree = new InternalCallTree(this.event, this.traceManager, this.solidityProxy, this.codeManager, { includeLocalVariables: true })
this.callTree = callTree // TODO: currently used by browser solidity, we should improve the API
this.event.register('indexChanged', this, function (index) {
self.codeManager.resolveStep(index, self.tx)
})
this.txBrowser = new TxBrowser(this)
this.txBrowser.event.register('newTxLoading', this, function () {
self.unLoad()
})
this.txBrowser.event.register('newTraceRequested', this, function (blockNumber, txIndex, tx) {
self.startDebugging(blockNumber, txIndex, tx)
})
this.txBrowser.event.register('unloadRequested', this, function (blockNumber, txIndex, tx) {
self.unLoad()
})
this.stepManager = new StepManager(this, this.traceManager)
this.stepManager.event.register('stepChanged', this, function (stepIndex) {
self.stepChanged(stepIndex)
})
this.vmDebugger = new VmDebugger(this, this.traceManager, this.codeManager, this.solidityProxy, callTree)
this.codeManager.event.register('changed', this, (code, address, instIndex) => {
this.callTree.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, this.currentStepIndex, this.solidityProxy.contracts, (error, sourceLocation) => {
if (!error) {
this.event.trigger('sourceLocationChanged', [sourceLocation])
}
})
})
}
Ethdebugger.prototype.setBreakpointManager = function (breakpointManager) {
this.breakpointManager = breakpointManager
}
Ethdebugger.prototype.web3 = function () {
return global.web3
}
Ethdebugger.prototype.addProvider = function (type, obj) {
this.web3Providers.addProvider(type, obj)
this.event.trigger('providerAdded', [type])
}
Ethdebugger.prototype.switchProvider = function (type) {
var self = this
this.web3Providers.get(type, function (error, obj) {
if (error) {
console.log('provider ' + type + ' not defined')
} else {
global.web3 = obj
executionContext.detectNetwork((error, network) => {
if (error || !network) {
global.web3Debug = obj
} else {
var webDebugNode = init.web3DebugNode(network.name)
global.web3Debug = !webDebugNode ? obj : webDebugNode
}
})
self.event.trigger('providerChanged', [type])
}
})
}
Ethdebugger.prototype.setCompilationResult = function (compilationResult) {
if (compilationResult && compilationResult.sources && compilationResult.contracts) {
this.solidityProxy.reset(compilationResult)
} else {
this.solidityProxy.reset({})
}
}
Ethdebugger.prototype.debug = function (tx) {
this.setCompilationResult(this.opts.compilationResult())
if (tx instanceof Object) {
this.txBrowser.load(tx.hash)
} else if (tx instanceof String) {
this.txBrowser.load(tx)
}
}
Ethdebugger.prototype.render = function () {
var view = yo`<div>
<div class="${css.innerShift}">
${this.txBrowser.render()}
${this.stepManager.render()}
</div>
<div class="${css.statusMessage}" >${this.statusMessage}</div>
${this.vmDebugger.render()}
</div>`
if (!this.view) {
this.view = view
}
return view
}
Ethdebugger.prototype.unLoad = function () {
this.traceManager.init()
this.codeManager.clear()
this.stepManager.reset()
this.event.trigger('traceUnloaded')
}
Ethdebugger.prototype.stepChanged = function (stepIndex) {
this.currentStepIndex = stepIndex
this.event.trigger('indexChanged', [stepIndex])
}
Ethdebugger.prototype.startDebugging = function (blockNumber, txIndex, tx) {
if (this.traceManager.isLoading) {
return
}
this.setCompilationResult(this.opts.compilationResult())
this.statusMessage = 'Loading trace...'
yo.update(this.view, this.render())
console.log('loading trace...')
this.tx = tx
var self = this
this.traceManager.resolveTrace(tx, function (error, result) {
console.log('trace loaded ' + result)
if (result) {
self.statusMessage = ''
yo.update(self.view, self.render())
self.event.trigger('newTraceLoaded', [self.traceManager.trace])
if (self.breakpointManager && self.breakpointManager.hasBreakpoint()) {
self.breakpointManager.jumpNextBreakpoint(false)
}
} else {
self.statusMessage = error ? error.message : 'Trace not loaded'
yo.update(self.view, self.render())
}
})
}
module.exports = Ethdebugger