parent
a47d7e824f
commit
9546b78ffa
@ -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`<div class="${css.buttons}">
|
||||
<div class="${css.stepButtons}"> |
||||
<button id='overback' title='Step over back' class='${css.navigator} ${css.stepButton} fa fa-reply' onclick=${function () { self.event.trigger('stepOverBack') }} disabled=${this.overBackDisabled} ></button> |
||||
<button id='intoback' title='Step back' class='${css.navigator} ${css.stepButton} fa fa-level-up' onclick=${function () { self.event.trigger('stepIntoBack') }} disabled=${this.intoBackDisabled} ></button> |
||||
<button id='intoforward' title='Step into' class='${css.navigator} ${css.stepButton} fa fa-level-down' onclick=${function () { self.event.trigger('stepIntoForward') }} disabled=${this.intoForwardDisabled} ></button> |
||||
<button id='overforward' title='Step over forward' class='${css.navigator} ${css.stepButton} fa fa-share' onclick=${function () { self.event.trigger('stepOverForward') }} disabled=${this.overForwardDisabled} ></button> |
||||
</div> |
||||
|
||||
<div class="${css.jumpButtons}"> |
||||
<button id='jumppreviousbreakpoint' title='Jump to the previous breakpoint' class='${css.navigator} ${css.jumpButton} fa fa-step-backward' onclick=${function () { self.event.trigger('jumpPreviousBreakpoint') }} disabled=${this.jumpPreviousBreakpointDisabled} ></button> |
||||
<button id='jumpout' title='Jump out' class='${css.navigator} ${css.jumpButton} fa fa-eject' onclick=${function () { self.event.trigger('jumpOut') }} disabled=${this.jumpOutDisabled} ></button> |
||||
<button id='jumpnextbreakpoint' title='Jump to the next breakpoint' class='${css.navigator} ${css.jumpButton} fa fa-step-forward' onclick=${function () { self.event.trigger('jumpNextBreakpoint') }} disabled=${this.jumpNextBreakpointDisabled} ></button> |
||||
</div> |
||||
<div id='reverted' style="display:none"> |
||||
<button id='jumptoexception' title='Jump to exception' class='${css.navigator} ${css.button} fa fa-exclamation-triangle' onclick=${function () { self.event.trigger('jumpToException', [self.revertionPoint]) }} disabled=${this.jumpOutDisabled} > |
||||
</button> |
||||
<span>State changes made during this call will be reverted.</span> |
||||
<span id='outofgas' style="display:none">This call will run out of gas.</span> |
||||
<span id='parenthasthrown' style="display:none">The parent call will throw an exception</span> |
||||
</div> |
||||
</div>` |
||||
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 |
@ -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`<div>
|
||||
<input |
||||
id='slider' |
||||
style='width: 100%' |
||||
type='range' |
||||
min=0 |
||||
max=${this.max} |
||||
value=0 |
||||
onchange=${function () { self.onChange() }} |
||||
oninput=${function () { self.onChange() }} |
||||
disabled=${this.disabled} /> |
||||
</div>` |
||||
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 |
@ -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`<div>
|
||||
${this.slider.render()} |
||||
${this.buttonNavigator.render()} |
||||
</div>` |
||||
} |
||||
|
||||
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 |
Loading…
Reference in new issue