diff --git a/src/app/debugger/debuggerUI.js b/src/app/debugger/debuggerUI.js
index 98f1d118c0..b5713aa225 100644
--- a/src/app/debugger/debuggerUI.js
+++ b/src/app/debugger/debuggerUI.js
@@ -2,6 +2,7 @@ var OldEthdebuggerUI = require('./remix-debugger/src/ui/EthdebuggerUI')
var Debugger = require('../debugger/debugger')
var SourceHighlighter = require('../editor/sourceHighlighter')
var TxBrowser = require('./debuggerUI/TxBrowser')
+var StepManager = require('./debuggerUI/StepManager')
var remixLib = require('remix-lib')
var executionContext = remixLib.execution.executionContext
var traceHelper = remixLib.helpers.trace
@@ -17,6 +18,8 @@ class DebuggerUI {
})
this.startTxBrowser()
+ // this.startStepManager()
+ this.stepManager = null
container.appendChild(this.debugger_ui.render())
@@ -30,7 +33,7 @@ class DebuggerUI {
})
this.transactionDebugger.event.register('breakpointStep', function (step) {
- self.debugger_ui.stepManager.jumpTo(step)
+ self.stepManager.jumpTo(step)
})
this.debugger_ui.event.register('indexChanged', function (index) {
@@ -38,6 +41,10 @@ class DebuggerUI {
})
}
+ // startStepManager () {
+ // this.stepManager = null
+ // }
+
startTxBrowser () {
const self = this
let web3 = executionContext.web3()
@@ -52,7 +59,7 @@ class DebuggerUI {
if (!tx.to) {
tx.to = traceHelper.contractCreationToken('0')
}
- return self.debugger_ui.startDebugging(blockNumber, txNumber, tx)
+ return self.startDebugging(blockNumber, txNumber, tx)
}
try {
@@ -60,13 +67,13 @@ class DebuggerUI {
return web3.eth.getTransaction(txNumber, function (error, result) {
let tx = result
txBrowser.update(error, result)
- self.debugger_ui.startDebugging(blockNumber, txNumber, tx)
+ self.startDebugging(blockNumber, txNumber, tx)
})
}
web3.eth.getTransactionFromBlock(blockNumber, txNumber, function (error, result) {
let tx = result
txBrowser.update(error, result)
- self.debugger_ui.startDebugging(blockNumber, txNumber, tx)
+ self.startDebugging(blockNumber, txNumber, tx)
})
} catch (e) {
self.update(e.message)
@@ -92,6 +99,22 @@ class DebuggerUI {
return this.isActive
}
+ startDebugging (blockNumber, txNumber, tx) {
+ const self = this
+ let shouldOpenDebugger = this.debugger_ui.startDebugging(blockNumber, txNumber, tx)
+ if (!shouldOpenDebugger) return
+
+ this.stepManager = new StepManager(this.debugger_ui, this.transactionDebugger.debugger.traceManager)
+ this.stepManager.event.register('stepChanged', this, function (stepIndex) {
+ self.debugger_ui.stepChanged(stepIndex)
+ })
+
+ this.debugger_ui.stepManager = this.stepManager
+
+ this.debugger_ui.createAndAddVmDebugger()
+ this.transactionDebugger.debugger.debug(tx)
+ }
+
debug (txHash) {
const self = this
this.transactionDebugger.debug(txHash, (error, tx) => {
diff --git a/src/app/debugger/debuggerUI/ButtonNavigator.js b/src/app/debugger/debuggerUI/ButtonNavigator.js
new file mode 100644
index 0000000000..12c9e4fa54
--- /dev/null
+++ b/src/app/debugger/debuggerUI/ButtonNavigator.js
@@ -0,0 +1,184 @@
+'use strict'
+var remixLib = require('remix-lib')
+var EventManager = remixLib.EventManager
+var yo = require('yo-yo')
+
+var csjs = require('csjs-inject')
+var styleGuide = require('../../ui/styles-guide/theme-chooser')
+var styles = styleGuide.chooser()
+
+var css = csjs`
+ .buttons {
+ display: flex;
+ flex-wrap: wrap;
+ }
+ .stepButtons {
+ width: 100%;
+ display: flex;
+ justify-content: center;
+ }
+ .stepButton {
+ ${styles.rightPanel.debuggerTab.button_Debugger}
+ }
+ .jumpButtons {
+ width: 100%;
+ display: flex;
+ justify-content: center;
+ }
+ .jumpButton {
+ ${styles.rightPanel.debuggerTab.button_Debugger}
+ }
+ .navigator {
+ color: ${styles.rightPanel.debuggerTab.text_Primary};
+ }
+ .navigator:hover {
+ color: ${styles.rightPanel.debuggerTab.button_Debugger_icon_HoverColor};
+ }
+`
+
+function ButtonNavigator (_parent, _traceManager) {
+ this.event = new EventManager()
+ this.intoBackDisabled = true
+ this.overBackDisabled = true
+ this.intoForwardDisabled = true
+ this.overForwardDisabled = true
+ this.jumpOutDisabled = true
+ this.jumpNextBreakpointDisabled = true
+ this.jumpPreviousBreakpointDisabled = true
+
+ this.traceManager = _traceManager
+ this.currentCall = null
+ this.revertionPoint = null
+
+ _parent.event.register('indexChanged', this, (index) => {
+ if (!this.view) return
+ if (index < 0) return
+ if (_parent.currentStepIndex !== index) return
+
+ this.traceManager.buildCallPath(index, (error, callsPath) => {
+ if (error) {
+ console.log(error)
+ resetWarning(this)
+ } else {
+ this.currentCall = callsPath[callsPath.length - 1]
+ if (this.currentCall.reverted) {
+ this.revertionPoint = this.currentCall.return
+ this.view.querySelector('#reverted').style.display = 'block'
+ this.view.querySelector('#reverted #outofgas').style.display = this.currentCall.outOfGas ? 'inline' : 'none'
+ this.view.querySelector('#reverted #parenthasthrown').style.display = 'none'
+ } else {
+ var k = callsPath.length - 2
+ while (k >= 0) {
+ var parent = callsPath[k]
+ if (parent.reverted) {
+ this.revertionPoint = parent.return
+ this.view.querySelector('#reverted').style.display = 'block'
+ this.view.querySelector('#reverted #parenthasthrown').style.display = parent ? 'inline' : 'none'
+ this.view.querySelector('#reverted #outofgas').style.display = 'none'
+ return
+ }
+ k--
+ }
+ resetWarning(this)
+ }
+ }
+ })
+ })
+
+ this.view
+}
+
+module.exports = ButtonNavigator
+
+ButtonNavigator.prototype.render = function () {
+ var self = this
+ var view = yo`
`
+ if (!this.view) {
+ this.view = view
+ }
+ return view
+}
+
+ButtonNavigator.prototype.reset = function () {
+ this.intoBackDisabled = true
+ this.overBackDisabled = true
+ this.intoForwardDisabled = true
+ this.overForwardDisabled = true
+ this.jumpOutDisabled = true
+ this.jumpNextBreakpointDisabled = true
+ this.jumpPreviousBreakpointDisabled = true
+ resetWarning(this)
+}
+
+ButtonNavigator.prototype.stepChanged = function (step) {
+ this.intoBackDisabled = step <= 0
+ this.overBackDisabled = step <= 0
+ if (!this.traceManager) {
+ this.intoForwardDisabled = true
+ this.overForwardDisabled = true
+ } else {
+ var self = this
+ this.traceManager.getLength(function (error, length) {
+ if (error) {
+ self.reset()
+ console.log(error)
+ } else {
+ self.jumpNextBreakpointDisabled = step >= length - 1
+ self.jumpPreviousBreakpointDisabled = step <= 0
+ self.intoForwardDisabled = step >= length - 1
+ self.overForwardDisabled = step >= length - 1
+ var stepOut = self.traceManager.findStepOut(step)
+ self.jumpOutDisabled = stepOut === step
+ }
+ self.updateAll()
+ })
+ }
+ this.updateAll()
+}
+
+ButtonNavigator.prototype.updateAll = function () {
+ this.updateDisabled('intoback', this.intoBackDisabled)
+ this.updateDisabled('overback', this.overBackDisabled)
+ this.updateDisabled('overforward', this.overForwardDisabled)
+ this.updateDisabled('intoforward', this.intoForwardDisabled)
+ this.updateDisabled('jumpout', this.jumpOutDisabled)
+ this.updateDisabled('jumptoexception', this.jumpOutDisabled)
+ this.updateDisabled('jumpnextbreakpoint', this.jumpNextBreakpointDisabled)
+ this.updateDisabled('jumppreviousbreakpoint', this.jumpPreviousBreakpointDisabled)
+}
+
+ButtonNavigator.prototype.updateDisabled = function (id, disabled) {
+ if (disabled) {
+ document.getElementById(id).setAttribute('disabled', true)
+ } else {
+ document.getElementById(id).removeAttribute('disabled')
+ }
+}
+
+function resetWarning (self) {
+ self.view.querySelector('#reverted #outofgas').style.display = 'none'
+ self.view.querySelector('#reverted #parenthasthrown').style.display = 'none'
+ self.view.querySelector('#reverted').style.display = 'none'
+}
+
+module.exports = ButtonNavigator
diff --git a/src/app/debugger/debuggerUI/Slider.js b/src/app/debugger/debuggerUI/Slider.js
new file mode 100644
index 0000000000..10ca255d81
--- /dev/null
+++ b/src/app/debugger/debuggerUI/Slider.js
@@ -0,0 +1,75 @@
+'use strict'
+var remixLib = require('remix-lib')
+var EventManager = remixLib.EventManager
+var yo = require('yo-yo')
+
+class Slider {
+ constructor (_traceManager, _stepOverride) {
+ this.event = new EventManager()
+ this.traceManager = _traceManager
+ this.max
+ this.disabled = true
+ this.view
+ this.solidityMode = false
+ this.stepOverride = _stepOverride
+
+ this.previousValue = null
+ }
+
+ render () {
+ var self = this
+ var view = yo`
+
+
`
+ if (!this.view) {
+ this.view = view
+ }
+ return view
+ }
+
+ init (length) {
+ var slider = this.view.querySelector('#slider')
+ slider.setAttribute('max', length - 1)
+ this.max = length - 1
+ this.updateDisabled(length === 0)
+ this.disabled = length === 0
+ this.setValue(0)
+ }
+
+ onChange (event) {
+ var value = parseInt(this.view.querySelector('#slider').value)
+ if (this.stepOverride) {
+ var correctedValue = this.stepOverride(value)
+ if (correctedValue !== value) {
+ this.setValue(correctedValue)
+ value = correctedValue
+ }
+ }
+ if (value === this.previousValue) return
+ this.previousValue = value
+ this.event.trigger('moved', [value])
+ }
+
+ setValue (value) {
+ this.view.querySelector('#slider').value = value
+ }
+
+ updateDisabled (disabled) {
+ if (disabled) {
+ this.view.querySelector('#slider').setAttribute('disabled', true)
+ } else {
+ this.view.querySelector('#slider').removeAttribute('disabled')
+ }
+ }
+}
+
+module.exports = Slider
diff --git a/src/app/debugger/debuggerUI/StepManager.js b/src/app/debugger/debuggerUI/StepManager.js
new file mode 100644
index 0000000000..d464b292cc
--- /dev/null
+++ b/src/app/debugger/debuggerUI/StepManager.js
@@ -0,0 +1,205 @@
+'use strict'
+var ButtonNavigator = require('./ButtonNavigator')
+var Slider = require('./Slider')
+var remixLib = require('remix-lib')
+var EventManager = remixLib.EventManager
+var yo = require('yo-yo')
+var util = remixLib.util
+
+function StepManager (_parent, _traceManager) {
+ this.event = new EventManager()
+ this.parent = _parent.debugger
+ this.traceManager = _traceManager
+ this.sourceMapByAddress = {}
+ this.solidityMode = false
+
+ var self = this
+ this.parent.event.register('newTraceLoaded', this, function () {
+ if (!this.slider) return
+ self.traceManager.getLength(function (error, length) {
+ if (error) {
+ console.log(error)
+ } else {
+ self.slider.init(length)
+ self.init()
+ }
+ })
+ })
+
+ this.slider = new Slider(this.traceManager, (step) => {
+ return this.solidityMode ? this.resolveToReducedTrace(step, 0) : step
+ })
+ this.slider.event.register('moved', this, function (step) {
+ self.sliderMoved(step)
+ })
+
+ this.parent.callTree.event.register('callTreeReady', () => {
+ if (!this.slider) return
+ if (this.parent.callTree.functionCallStack.length) {
+ this.jumpTo(this.parent.callTree.functionCallStack[0])
+ }
+ })
+
+ this.buttonNavigator = new ButtonNavigator(_parent, this.traceManager)
+ this.buttonNavigator.event.register('stepIntoBack', this, function () {
+ self.stepIntoBack()
+ })
+ this.buttonNavigator.event.register('stepIntoForward', this, function () {
+ self.stepIntoForward()
+ })
+ this.buttonNavigator.event.register('stepOverBack', this, function () {
+ self.stepOverBack()
+ })
+ this.buttonNavigator.event.register('stepOverForward', this, function () {
+ self.stepOverForward()
+ })
+ this.buttonNavigator.event.register('jumpOut', this, function () {
+ self.jumpOut()
+ })
+ this.buttonNavigator.event.register('jumpToException', this, function (exceptionIndex) {
+ self.jumpTo(exceptionIndex)
+ })
+ this.buttonNavigator.event.register('jumpNextBreakpoint', (exceptionIndex) => {
+ self.parent.breakpointManager.jumpNextBreakpoint(_parent.currentStepIndex, true)
+ })
+ this.buttonNavigator.event.register('jumpPreviousBreakpoint', (exceptionIndex) => {
+ self.parent.breakpointManager.jumpPreviousBreakpoint(_parent.currentStepIndex, true)
+ })
+}
+
+StepManager.prototype.remove = function () {
+ // used to stop listenning on event. bad and should be "refactored"
+ this.slider.view = null
+ this.slider = null
+ this.buttonNavigator.view = null
+ this.buttonNavigator = null
+}
+
+StepManager.prototype.resolveToReducedTrace = function (value, incr) {
+ if (this.parent.callTree.reducedTrace.length) {
+ var nextSource = util.findClosestIndex(value, this.parent.callTree.reducedTrace)
+ nextSource = nextSource + incr
+ if (nextSource <= 0) {
+ nextSource = 0
+ } else if (nextSource > this.parent.callTree.reducedTrace.length) {
+ nextSource = this.parent.callTree.reducedTrace.length - 1
+ }
+ return this.parent.callTree.reducedTrace[nextSource]
+ }
+ return value
+}
+
+StepManager.prototype.render = function () {
+ return yo`
+ ${this.slider.render()}
+ ${this.buttonNavigator.render()}
+
`
+}
+
+StepManager.prototype.reset = function () {
+ this.slider.setValue(0)
+ this.currentStepIndex = 0
+ this.buttonNavigator.reset()
+}
+
+StepManager.prototype.init = function () {
+ this.slider.setValue(0)
+ this.changeState(0)
+}
+
+StepManager.prototype.newTraceAvailable = function () {
+ this.init()
+}
+
+StepManager.prototype.jumpTo = function (step) {
+ if (!this.traceManager.inRange(step)) {
+ return
+ }
+ this.slider.setValue(step)
+ this.changeState(step)
+}
+
+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
+ if (this.solidityMode) {
+ step = this.resolveToReducedTrace(step, 1)
+ } else {
+ step += 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
+ if (this.solidityMode) {
+ step = this.resolveToReducedTrace(step, -1)
+ } else {
+ step -= 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)
+ if (this.solidityMode) {
+ step = this.resolveToReducedTrace(step, 1)
+ }
+ this.slider.setValue(step)
+ this.changeState(step)
+}
+
+StepManager.prototype.stepOverBack = function () {
+ if (!this.traceManager.isLoaded()) {
+ return
+ }
+ var step = this.traceManager.findStepOverBack(this.currentStepIndex)
+ if (this.solidityMode) {
+ step = this.resolveToReducedTrace(step, -1)
+ }
+ this.slider.setValue(step)
+ this.changeState(step)
+}
+
+StepManager.prototype.jumpOut = function () {
+ if (!this.traceManager.isLoaded()) {
+ return
+ }
+ var step = this.traceManager.findStepOut(this.currentStepIndex)
+ if (this.solidityMode) {
+ step = this.resolveToReducedTrace(step, 0)
+ }
+ this.slider.setValue(step)
+ this.changeState(step)
+}
+
+StepManager.prototype.changeState = function (step) {
+ this.currentStepIndex = step
+ this.buttonNavigator.stepChanged(step)
+ this.event.trigger('stepChanged', [step])
+}
+
+module.exports = StepManager
diff --git a/src/app/debugger/remix-debugger/src/ui/EthdebuggerUI.js b/src/app/debugger/remix-debugger/src/ui/EthdebuggerUI.js
index 26c258edd9..7988addddf 100644
--- a/src/app/debugger/remix-debugger/src/ui/EthdebuggerUI.js
+++ b/src/app/debugger/remix-debugger/src/ui/EthdebuggerUI.js
@@ -1,6 +1,6 @@
'use strict'
// var TxBrowser = require('./TxBrowser')
-var StepManager = require('./StepManager')
+// var StepManager = require('./StepManager')
var VmDebugger = require('./VmDebugger')
var yo = require('yo-yo')
@@ -91,16 +91,11 @@ EthdebuggerUI.prototype.stepChanged = function (stepIndex) {
EthdebuggerUI.prototype.startDebugging = function (blockNumber, txIndex, tx) {
const self = this
if (this.debugger.traceManager.isLoading) {
- return
+ return false
}
this.tx = tx
- this.stepManager = new StepManager(this, this.debugger.traceManager)
- this.stepManager.event.register('stepChanged', this, function (stepIndex) {
- self.stepChanged(stepIndex)
- })
-
this.debugger.codeManager.event.register('changed', this, (code, address, instIndex) => {
self.debugger.callTree.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, this.currentStepIndex, this.debugger.solidityProxy.contracts, (error, sourceLocation) => {
if (!error) {
@@ -109,12 +104,14 @@ EthdebuggerUI.prototype.startDebugging = function (blockNumber, txIndex, tx) {
})
})
+ return true
+}
+
+EthdebuggerUI.prototype.createAndAddVmDebugger = function () {
this.vmDebugger = new VmDebugger(this, this.debugger.traceManager, this.debugger.codeManager, this.debugger.solidityProxy, this.debugger.callTree)
yo.update(this.debuggerHeadPanelsView, this.vmDebugger.renderHead())
yo.update(this.debuggerPanelsView, this.vmDebugger.render())
yo.update(this.stepManagerView, this.stepManager.render())
-
- this.debugger.debug(tx)
}
module.exports = EthdebuggerUI