parent
b8fa1a4e8a
commit
73385468ec
@ -1,184 +0,0 @@ |
|||||||
'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 |
|
@ -1,33 +0,0 @@ |
|||||||
'use strict' |
|
||||||
var DropdownPanel = require('./DropdownPanel') |
|
||||||
var yo = require('yo-yo') |
|
||||||
|
|
||||||
function CalldataPanel (_parentUI, _traceManager) { |
|
||||||
this._parentUI = _parentUI |
|
||||||
this.traceManager = _traceManager |
|
||||||
this.basicPanel = new DropdownPanel('Call Data', {json: true}) |
|
||||||
this.init() |
|
||||||
} |
|
||||||
|
|
||||||
CalldataPanel.prototype.render = function () { |
|
||||||
return yo`<div id='calldatapanel' >${this.basicPanel.render()}</div>` |
|
||||||
} |
|
||||||
|
|
||||||
CalldataPanel.prototype.init = function () { |
|
||||||
var self = this |
|
||||||
this._parentUI.event.register('indexChanged', this, function (index) { |
|
||||||
if (index < 0) return |
|
||||||
if (self._parentUI.currentStepIndex !== index) return |
|
||||||
|
|
||||||
self.traceManager.getCallDataAt(index, function (error, calldata) { |
|
||||||
if (error) { |
|
||||||
self.basicPanel.update({}) |
|
||||||
console.log(error) |
|
||||||
} else if (self._parentUI.currentStepIndex === index) { |
|
||||||
self.basicPanel.update(calldata) |
|
||||||
} |
|
||||||
}) |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = CalldataPanel |
|
@ -1,33 +0,0 @@ |
|||||||
'use strict' |
|
||||||
var DropdownPanel = require('./DropdownPanel') |
|
||||||
var yo = require('yo-yo') |
|
||||||
|
|
||||||
function CallstackPanel (_parent, _traceManager) { |
|
||||||
this.parent = _parent |
|
||||||
this.traceManager = _traceManager |
|
||||||
this.basicPanel = new DropdownPanel('Call Stack', {json: true}) |
|
||||||
this.init() |
|
||||||
} |
|
||||||
|
|
||||||
CallstackPanel.prototype.render = function () { |
|
||||||
return yo`<div id='callstackpanel' >${this.basicPanel.render()}</div>` |
|
||||||
} |
|
||||||
|
|
||||||
CallstackPanel.prototype.init = function () { |
|
||||||
var self = this |
|
||||||
this.parent.event.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) |
|
||||||
self.basicPanel.update({}) |
|
||||||
} else if (self.parent.currentStepIndex === index) { |
|
||||||
self.basicPanel.update(callstack) |
|
||||||
} |
|
||||||
}) |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = CallstackPanel |
|
@ -1,88 +0,0 @@ |
|||||||
'use strict' |
|
||||||
var style = require('./styles/basicStyles') |
|
||||||
var yo = require('yo-yo') |
|
||||||
var remixLib = require('remix-lib') |
|
||||||
var DropdownPanel = require('./DropdownPanel') |
|
||||||
var EventManager = remixLib.EventManager |
|
||||||
var csjs = require('csjs-inject') |
|
||||||
var styleGuide = require('../../../../ui/styles-guide/theme-chooser') |
|
||||||
var styles = styleGuide.chooser() |
|
||||||
|
|
||||||
var css = csjs` |
|
||||||
.instructions { |
|
||||||
${styles.rightPanel.debuggerTab.box_Debugger} |
|
||||||
overflow-y: scroll; |
|
||||||
max-height: 150px; |
|
||||||
} |
|
||||||
` |
|
||||||
function CodeListView (_parent, _codeManager) { |
|
||||||
this.event = new EventManager() |
|
||||||
this.parent = _parent |
|
||||||
this.codeManager = _codeManager |
|
||||||
this.code |
|
||||||
this.address |
|
||||||
this.codeView |
|
||||||
this.itemSelected |
|
||||||
this.basicPanel = new DropdownPanel('Instructions', {json: false, displayContentOnly: true}) |
|
||||||
this.basicPanel.event.register('hide', () => { |
|
||||||
this.event.trigger('hide', []) |
|
||||||
}) |
|
||||||
this.basicPanel.event.register('show', () => { |
|
||||||
this.event.trigger('show', []) |
|
||||||
}) |
|
||||||
this.init() |
|
||||||
} |
|
||||||
|
|
||||||
CodeListView.prototype.render = function () { |
|
||||||
return yo`<div id='asmcodes' >${this.basicPanel.render({height: style.instructionsList.height})}</div>` |
|
||||||
} |
|
||||||
|
|
||||||
CodeListView.prototype.init = function () { |
|
||||||
var self = this |
|
||||||
this.codeManager.event.register('changed', this, this.changed) |
|
||||||
this.parent.event.register('traceUnloaded', this, function () { |
|
||||||
self.changed([], '', -1) |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
CodeListView.prototype.indexChanged = function (index) { |
|
||||||
if (index >= 0) { |
|
||||||
if (this.itemSelected) { |
|
||||||
this.itemSelected.removeAttribute('selected') |
|
||||||
this.itemSelected.removeAttribute('style') |
|
||||||
if (this.itemSelected.firstChild) { |
|
||||||
this.itemSelected.firstChild.removeAttribute('style') |
|
||||||
} |
|
||||||
} |
|
||||||
this.itemSelected = this.codeView.children[index] |
|
||||||
this.itemSelected.setAttribute('style', 'background-color: ' + styles.rightPanel.debuggerTab.text_BgHighlight) |
|
||||||
this.itemSelected.setAttribute('selected', 'selected') |
|
||||||
if (this.itemSelected.firstChild) { |
|
||||||
this.itemSelected.firstChild.setAttribute('style', 'margin-left: 2px') |
|
||||||
} |
|
||||||
this.codeView.scrollTop = this.itemSelected.offsetTop - parseInt(this.codeView.offsetTop) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
CodeListView.prototype.changed = function (code, address, index) { |
|
||||||
if (this.address !== address) { |
|
||||||
this.code = code |
|
||||||
this.address = address |
|
||||||
this.codeView = this.renderAssemblyItems() |
|
||||||
this.basicPanel.setContent(this.codeView) |
|
||||||
} |
|
||||||
this.indexChanged(index) |
|
||||||
} |
|
||||||
|
|
||||||
CodeListView.prototype.renderAssemblyItems = function () { |
|
||||||
if (this.code) { |
|
||||||
var codeView = this.code.map(function (item, i) { |
|
||||||
return yo`<div key=${i} value=${i}><span>${item}</span></div>` |
|
||||||
}) |
|
||||||
return yo`<div class=${css.instructions} id='asmitems' ref='itemsList'>
|
|
||||||
${codeView} |
|
||||||
</div>` |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = CodeListView |
|
@ -1,208 +0,0 @@ |
|||||||
'use strict' |
|
||||||
var yo = require('yo-yo') |
|
||||||
const copy = require('clipboard-copy') |
|
||||||
var remixLib = require('remix-lib') |
|
||||||
var TreeView = require('../../../../ui/TreeView') // TODO setup a direct reference to the UI components
|
|
||||||
var EventManager = remixLib.EventManager |
|
||||||
|
|
||||||
var csjs = require('csjs-inject') |
|
||||||
var styleGuide = require('../../../../ui/styles-guide/theme-chooser') |
|
||||||
var styles = styleGuide.chooser() |
|
||||||
|
|
||||||
var css = csjs` |
|
||||||
.title { |
|
||||||
margin-top: 10px; |
|
||||||
${styles.rightPanel.debuggerTab.dropdown_Debugger}; |
|
||||||
display: flex; |
|
||||||
align-items: center; |
|
||||||
} |
|
||||||
.name { |
|
||||||
font-weight: bold; |
|
||||||
} |
|
||||||
.nameDetail { |
|
||||||
font-weight: bold; |
|
||||||
margin-left: 3px; |
|
||||||
} |
|
||||||
.icon { |
|
||||||
color: ${styles.rightPanel.debuggerTab.button_Debugger_icon_Color}; |
|
||||||
margin-right: 5%; |
|
||||||
} |
|
||||||
.eyeButton { |
|
||||||
margin: 3px; |
|
||||||
} |
|
||||||
.eyeButton:hover { |
|
||||||
color: ${styles.rightPanel.debuggerTab.button_Debugger_icon_HoverColor}; |
|
||||||
} |
|
||||||
.dropdownpanel { |
|
||||||
${styles.rightPanel.debuggerTab.dropdown_Debugger}; |
|
||||||
width: 100%; |
|
||||||
} |
|
||||||
.dropdownrawcontent { |
|
||||||
padding: 2px; |
|
||||||
word-break: break-all; |
|
||||||
} |
|
||||||
.message { |
|
||||||
padding: 2px; |
|
||||||
word-break: break-all; |
|
||||||
} |
|
||||||
.refresh { |
|
||||||
display: none; |
|
||||||
margin-left: 4px; |
|
||||||
margin-top: 4px;
|
|
||||||
animation: spin 2s linear infinite; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
function DropdownPanel (_name, _opts) { |
|
||||||
this.event = new EventManager() |
|
||||||
if (!_opts) { |
|
||||||
_opts = {} |
|
||||||
} |
|
||||||
this.name = _name |
|
||||||
this.header = '' |
|
||||||
this.json = _opts.json |
|
||||||
this.displayContentOnly = _opts.displayContentOnly |
|
||||||
if (this.json) { |
|
||||||
this.treeView = new TreeView(_opts) |
|
||||||
} |
|
||||||
this.view |
|
||||||
} |
|
||||||
|
|
||||||
DropdownPanel.prototype.setMessage = function (message) { |
|
||||||
if (this.view) { |
|
||||||
this.view.querySelector('.dropdownpanel .dropdownrawcontent').style.display = 'none' |
|
||||||
this.view.querySelector('.dropdownpanel .dropdowncontent').style.display = 'none' |
|
||||||
this.view.querySelector('.dropdownpanel .fa-refresh').style.display = 'none' |
|
||||||
this.message(message) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
DropdownPanel.prototype.setLoading = function () { |
|
||||||
if (this.view) { |
|
||||||
this.view.querySelector('.dropdownpanel .dropdownrawcontent').style.display = 'none' |
|
||||||
this.view.querySelector('.dropdownpanel .dropdowncontent').style.display = 'none' |
|
||||||
this.view.querySelector('.dropdownpanel .fa-refresh').style.display = 'inline-block' |
|
||||||
this.message('') |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
DropdownPanel.prototype.setUpdating = function () { |
|
||||||
if (this.view) { |
|
||||||
this.view.querySelector('.dropdownpanel .dropdowncontent').style.color = styles.appProperties.greyedText_color |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
DropdownPanel.prototype.update = function (_data, _header) { |
|
||||||
if (this.view) { |
|
||||||
this.view.querySelector('.dropdownpanel .fa-refresh').style.display = 'none' |
|
||||||
this.view.querySelector('.dropdownpanel .dropdowncontent').style.display = 'block' |
|
||||||
this.view.querySelector('.dropdownpanel .dropdowncontent').style.color = styles.appProperties.mainText_Color |
|
||||||
this.view.querySelector('.dropdownpanel .dropdownrawcontent').innerText = JSON.stringify(_data, null, '\t') |
|
||||||
if (!this.displayContentOnly) { |
|
||||||
this.view.querySelector('.title div.btn').style.display = 'block' |
|
||||||
this.view.querySelector('.title span').innerText = _header || ' ' |
|
||||||
} |
|
||||||
this.message('') |
|
||||||
if (this.json) { |
|
||||||
this.treeView.update(_data) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
DropdownPanel.prototype.setContent = function (node) { |
|
||||||
if (this.view) { |
|
||||||
var parent = this.view.querySelector('.dropdownpanel div.dropdowncontent') |
|
||||||
parent.replaceChild(node, parent.firstElementChild) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
DropdownPanel.prototype.render = function (overridestyle) { |
|
||||||
var content = yo`<div>Empty</div>` |
|
||||||
if (this.json) { |
|
||||||
content = this.treeView.render({}) |
|
||||||
} |
|
||||||
overridestyle === undefined ? {} : overridestyle |
|
||||||
var self = this |
|
||||||
var title = !self.displayContentOnly ? yo`<div class="${css.title} title">
|
|
||||||
<div class="${css.icon} fa fa-caret-right" onclick=${function () { self.toggle() }} ></div> |
|
||||||
<div class="${css.name}" onclick=${function () { self.toggle() }} >${this.name}</div><span class="${css.nameDetail}" onclick=${function () { self.toggle() }} ></span> |
|
||||||
<div onclick=${function () { self.copyClipboard() }} title='raw' class="${css.eyeButton} btn fa fa-clipboard"></div> |
|
||||||
</div>` : yo`<div></div>` |
|
||||||
|
|
||||||
var contentNode = yo`<div class='dropdownpanel' style='display:none'>
|
|
||||||
<i class="${css.refresh} fa fa-refresh" aria-hidden="true"></i> |
|
||||||
<div class='dropdowncontent'>${content}</div> |
|
||||||
<div class='dropdownrawcontent' style='display:none'></div> |
|
||||||
<div class='message' style='display:none'></div> |
|
||||||
</div>` |
|
||||||
var view = yo` |
|
||||||
<div> |
|
||||||
<style> |
|
||||||
@-moz-keyframes spin { |
|
||||||
to { -moz-transform: rotate(359deg); } |
|
||||||
} |
|
||||||
@-webkit-keyframes spin { |
|
||||||
to { -webkit-transform: rotate(359deg); } |
|
||||||
} |
|
||||||
@keyframes spin { |
|
||||||
to {transform:rotate(359deg);} |
|
||||||
} |
|
||||||
</style> |
|
||||||
${title} |
|
||||||
${contentNode} |
|
||||||
</div>` |
|
||||||
if (!this.view) { |
|
||||||
this.view = view |
|
||||||
} |
|
||||||
if (self.displayContentOnly) contentNode.style.display = 'block' |
|
||||||
return view |
|
||||||
} |
|
||||||
|
|
||||||
DropdownPanel.prototype.copyClipboard = function () { |
|
||||||
var content = this.view.querySelector('.dropdownpanel .dropdownrawcontent') |
|
||||||
if (content) copy(content.innerText ? content.innerText : content.textContent) |
|
||||||
} |
|
||||||
|
|
||||||
DropdownPanel.prototype.toggle = function () { |
|
||||||
var el = this.view.querySelector('.dropdownpanel') |
|
||||||
var caret = this.view.querySelector('.title').firstElementChild |
|
||||||
if (el.style.display === '') { |
|
||||||
el.style.display = 'none' |
|
||||||
caret.className = `${css.icon} fa fa-caret-right` |
|
||||||
this.event.trigger('hide', []) |
|
||||||
} else { |
|
||||||
el.style.display = '' |
|
||||||
caret.className = `${css.icon} fa fa-caret-down` |
|
||||||
this.event.trigger('show', []) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
DropdownPanel.prototype.hide = function () { |
|
||||||
if (this.view && !this.displayContentOnly) { |
|
||||||
var caret = this.view.querySelector('.title').firstElementChild |
|
||||||
var el = this.view.querySelector('.dropdownpanel') |
|
||||||
el.style.display = 'none' |
|
||||||
caret.className = `${css.icon} fa fa-caret-right` |
|
||||||
this.event.trigger('hide', []) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
DropdownPanel.prototype.show = function () { |
|
||||||
if (this.view && !this.displayContentOnly) { |
|
||||||
var caret = this.view.querySelector('.title').firstElementChild |
|
||||||
var el = this.view.querySelector('.dropdownpanel') |
|
||||||
el.style.display = '' |
|
||||||
caret.className = `${css.icon} fa fa-caret-down` |
|
||||||
this.event.trigger('show', []) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
DropdownPanel.prototype.message = function (message) { |
|
||||||
if (this.view) { |
|
||||||
var mes = this.view.querySelector('.dropdownpanel .message') |
|
||||||
mes.innerText = message |
|
||||||
mes.style.display = (message === '') ? 'none' : 'block' |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = DropdownPanel |
|
@ -1,210 +0,0 @@ |
|||||||
'use strict' |
|
||||||
var TxBrowser = require('./TxBrowser') |
|
||||||
var StepManager = require('./StepManager') |
|
||||||
var remixLib = require('remix-lib') |
|
||||||
var TraceManager = remixLib.trace.TraceManager |
|
||||||
var VmDebugger = require('./VmDebugger') |
|
||||||
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 = remixLib.code.CodeManager |
|
||||||
var remixDebug = require('remix-debug') |
|
||||||
var SolidityProxy = remixDebug.SolidityDecoder.SolidityProxy |
|
||||||
var InternalCallTree = remixDebug.SolidityDecoder.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) { |
|
||||||
console.dir('newTraceRequestd') |
|
||||||
console.dir(arguments) |
|
||||||
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.setManagers = function () { |
|
||||||
this.traceManager = new TraceManager({web3: this.web3}) |
|
||||||
this.codeManager = new CodeManager(this.traceManager) |
|
||||||
this.solidityProxy = new SolidityProxy(this.traceManager, this.codeManager) |
|
||||||
this.storageResolver = null |
|
||||||
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.vmDebugger = new VmDebugger(this, this.traceManager, this.codeManager, this.solidityProxy, callTree) |
|
||||||
|
|
||||||
this.callTree = new InternalCallTree(this.event, this.traceManager, this.solidityProxy, this.codeManager, { includeLocalVariables: true }) |
|
||||||
} |
|
||||||
|
|
||||||
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.updateWeb3Reference = function () { |
|
||||||
if (!this.txBrowser) return |
|
||||||
this.txBrowser.web3 = this.web3 |
|
||||||
} |
|
||||||
|
|
||||||
Ethdebugger.prototype.switchProvider = function (type) { |
|
||||||
var self = this |
|
||||||
this.web3Providers.get(type, function (error, obj) { |
|
||||||
if (error) { |
|
||||||
console.log('provider ' + type + ' not defined') |
|
||||||
} else { |
|
||||||
self.web3 = obj |
|
||||||
self.setManagers() |
|
||||||
self.updateWeb3Reference() |
|
||||||
executionContext.detectNetwork((error, network) => { |
|
||||||
if (error || !network) { |
|
||||||
global.web3Debug = obj |
|
||||||
} else { |
|
||||||
var webDebugNode = init.web3DebugNode(network.name) |
|
||||||
global.web3Debug = !webDebugNode ? obj : webDebugNode |
|
||||||
} |
|
||||||
self.updateWeb3Reference() |
|
||||||
}) |
|
||||||
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.vmDebugger.renderHead()} |
|
||||||
${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) { |
|
||||||
console.dir('startDebugging') |
|
||||||
console.dir(arguments) |
|
||||||
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 |
|
||||||
console.dir('resolving a trace with tx: ') |
|
||||||
console.dir(tx) |
|
||||||
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(0, false) |
|
||||||
} |
|
||||||
} else { |
|
||||||
self.statusMessage = error ? error.message : 'Trace not loaded' |
|
||||||
yo.update(self.view, self.render()) |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = Ethdebugger |
|
@ -1,72 +0,0 @@ |
|||||||
'use strict' |
|
||||||
var DropdownPanel = require('./DropdownPanel') |
|
||||||
var remixDebug = require('remix-debug') |
|
||||||
var StorageViewer = remixDebug.storage.StorageViewer |
|
||||||
var yo = require('yo-yo') |
|
||||||
|
|
||||||
function FullStoragesChanges (_parent, _traceManager) { |
|
||||||
this.storageResolver = null |
|
||||||
this.parent = _parent |
|
||||||
this.debugger = _parent.debugger |
|
||||||
this.traceManager = _traceManager |
|
||||||
this.addresses = [] |
|
||||||
this.view |
|
||||||
this.traceLength |
|
||||||
this.basicPanel = new DropdownPanel('Full Storages Changes', {json: true}) |
|
||||||
this.init() |
|
||||||
} |
|
||||||
|
|
||||||
FullStoragesChanges.prototype.render = function () { |
|
||||||
var view = yo`<div id='fullstorageschangespanel' >${this.basicPanel.render()}</div>` |
|
||||||
if (!this.view) { |
|
||||||
this.view = view |
|
||||||
} |
|
||||||
return view |
|
||||||
} |
|
||||||
|
|
||||||
FullStoragesChanges.prototype.init = function () { |
|
||||||
var self = this |
|
||||||
this.debugger.event.register('newTraceLoaded', this, function (length) { |
|
||||||
self.panels = [] |
|
||||||
self.traceManager.getAddresses(function (error, addresses) { |
|
||||||
if (!error) { |
|
||||||
self.addresses = addresses |
|
||||||
self.basicPanel.update({}) |
|
||||||
} |
|
||||||
}) |
|
||||||
|
|
||||||
self.traceManager.getLength(function (error, length) { |
|
||||||
if (!error) { |
|
||||||
self.traceLength = length |
|
||||||
} |
|
||||||
}) |
|
||||||
}) |
|
||||||
|
|
||||||
this.debugger.event.register('indexChanged', this, function (index) { |
|
||||||
if (index < 0) return |
|
||||||
if (self.parent.currentStepIndex !== index) return |
|
||||||
if (!self.storageResolver) return |
|
||||||
|
|
||||||
if (index === self.traceLength - 1) { |
|
||||||
var storageJSON = {} |
|
||||||
for (var k in self.addresses) { |
|
||||||
var address = self.addresses[k] |
|
||||||
var storageViewer = new StorageViewer({ |
|
||||||
stepIndex: self.parent.currentStepIndex, |
|
||||||
tx: self.parent.tx, |
|
||||||
address: address |
|
||||||
}, self.storageResolver, self.traceManager) |
|
||||||
storageViewer.storageRange(function (error, result) { |
|
||||||
if (!error) { |
|
||||||
storageJSON[address] = result |
|
||||||
self.basicPanel.update(storageJSON) |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
} else { |
|
||||||
self.basicPanel.update({}) |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = FullStoragesChanges |
|
@ -1,39 +0,0 @@ |
|||||||
'use strict' |
|
||||||
var DropdownPanel = require('./DropdownPanel') |
|
||||||
var remixLib = require('remix-lib') |
|
||||||
var ui = remixLib.helpers.ui |
|
||||||
var yo = require('yo-yo') |
|
||||||
|
|
||||||
function MemoryPanel (_parent, _traceManager) { |
|
||||||
this.parent = _parent |
|
||||||
this.traceManager = _traceManager |
|
||||||
this.basicPanel = new DropdownPanel('Memory', { |
|
||||||
json: true, |
|
||||||
css: { |
|
||||||
'font-family': 'monospace' |
|
||||||
}}) |
|
||||||
this.init() |
|
||||||
} |
|
||||||
|
|
||||||
MemoryPanel.prototype.render = function () { |
|
||||||
return yo`<div id='memorypanel' >${this.basicPanel.render()}</div>` |
|
||||||
} |
|
||||||
|
|
||||||
MemoryPanel.prototype.init = function () { |
|
||||||
var self = this |
|
||||||
this.parent.event.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) |
|
||||||
self.basicPanel.update({}) |
|
||||||
} else if (self.parent.currentStepIndex === index) { |
|
||||||
self.basicPanel.update(ui.formatMemory(memory, 16)) |
|
||||||
} |
|
||||||
}) |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = MemoryPanel |
|
@ -1,75 +0,0 @@ |
|||||||
'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 |
|
@ -1,83 +0,0 @@ |
|||||||
'use strict' |
|
||||||
var DropdownPanel = require('./DropdownPanel') |
|
||||||
var remixDebug = require('remix-debug') |
|
||||||
var localDecoder = remixDebug.SolidityDecoder.localDecoder |
|
||||||
var solidityTypeFormatter = require('./SolidityTypeFormatter') |
|
||||||
var StorageViewer = remixDebug.storage.StorageViewer |
|
||||||
var yo = require('yo-yo') |
|
||||||
|
|
||||||
class SolidityLocals { |
|
||||||
|
|
||||||
constructor (_parent, _traceManager, _internalTreeCall) { |
|
||||||
this.parent = _parent |
|
||||||
this.internalTreeCall = _internalTreeCall |
|
||||||
this.storageResolver = null |
|
||||||
this.traceManager = _traceManager |
|
||||||
this.basicPanel = new DropdownPanel('Solidity Locals', { |
|
||||||
json: true, |
|
||||||
formatSelf: solidityTypeFormatter.formatSelf, |
|
||||||
extractData: solidityTypeFormatter.extractData |
|
||||||
}) |
|
||||||
this.init() |
|
||||||
this.view |
|
||||||
} |
|
||||||
|
|
||||||
render () { |
|
||||||
this.view = yo`<div id='soliditylocals' >
|
|
||||||
${this.basicPanel.render()} |
|
||||||
</div>` |
|
||||||
return this.view |
|
||||||
} |
|
||||||
|
|
||||||
init () { |
|
||||||
var decodeTimeout = null |
|
||||||
this.parent.event.register('sourceLocationChanged', this, (sourceLocation) => { |
|
||||||
if (!this.storageResolver) { |
|
||||||
this.basicPanel.setMessage('storage not ready') |
|
||||||
return |
|
||||||
} |
|
||||||
if (decodeTimeout) { |
|
||||||
window.clearTimeout(decodeTimeout) |
|
||||||
} |
|
||||||
this.basicPanel.setUpdating() |
|
||||||
decodeTimeout = setTimeout(() => { |
|
||||||
decode(this, sourceLocation) |
|
||||||
}, 500) |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
function decode (self, sourceLocation) { |
|
||||||
self.basicPanel.setMessage('') |
|
||||||
self.traceManager.waterfall([ |
|
||||||
self.traceManager.getStackAt, |
|
||||||
self.traceManager.getMemoryAt, |
|
||||||
self.traceManager.getCurrentCalledAddressAt], |
|
||||||
self.parent.currentStepIndex, |
|
||||||
(error, result) => { |
|
||||||
if (!error) { |
|
||||||
var stack = result[0].value |
|
||||||
var memory = result[1].value |
|
||||||
try { |
|
||||||
var storageViewer = new StorageViewer({ |
|
||||||
stepIndex: self.parent.currentStepIndex, |
|
||||||
tx: self.parent.tx, |
|
||||||
address: result[2].value |
|
||||||
}, self.storageResolver, self.traceManager) |
|
||||||
localDecoder.solidityLocals(self.parent.currentStepIndex, self.internalTreeCall, stack, memory, storageViewer, sourceLocation).then((locals) => { |
|
||||||
if (!locals.error) { |
|
||||||
self.basicPanel.update(locals) |
|
||||||
} |
|
||||||
if (!Object.keys(locals).length) { |
|
||||||
self.basicPanel.setMessage('no locals') |
|
||||||
} |
|
||||||
}) |
|
||||||
} catch (e) { |
|
||||||
self.basicPanel.setMessage(e.message) |
|
||||||
} |
|
||||||
} else { |
|
||||||
console.log(error) |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
module.exports = SolidityLocals |
|
@ -1,103 +0,0 @@ |
|||||||
'use strict' |
|
||||||
var DropdownPanel = require('./DropdownPanel') |
|
||||||
var remixDebug = require('remix-debug') |
|
||||||
var stateDecoder = remixDebug.SolidityDecoder.stateDecoder |
|
||||||
var solidityTypeFormatter = require('./SolidityTypeFormatter') |
|
||||||
var StorageViewer = remixDebug.storage.StorageViewer |
|
||||||
var yo = require('yo-yo') |
|
||||||
|
|
||||||
function SolidityState (_parent, _traceManager, _codeManager, _solidityProxy) { |
|
||||||
this.storageResolver = null |
|
||||||
this.parent = _parent |
|
||||||
this.traceManager = _traceManager |
|
||||||
this.codeManager = _codeManager |
|
||||||
this.solidityProxy = _solidityProxy |
|
||||||
this.basicPanel = new DropdownPanel('Solidity State', { |
|
||||||
json: true, |
|
||||||
formatSelf: solidityTypeFormatter.formatSelf, |
|
||||||
extractData: solidityTypeFormatter.extractData |
|
||||||
}) |
|
||||||
this.init() |
|
||||||
this.view |
|
||||||
this.stateVariablesByAddresses = {} |
|
||||||
_parent.event.register('traceUnloaded', () => { this.stateVariablesByAddresses = {} }) |
|
||||||
_parent.event.register('newTraceLoaded', () => { this.stateVariablesByAddresses = {} }) |
|
||||||
} |
|
||||||
|
|
||||||
SolidityState.prototype.render = function () { |
|
||||||
if (!this.view) { |
|
||||||
this.view = yo`<div id='soliditystate' >
|
|
||||||
${this.basicPanel.render()} |
|
||||||
</div>` |
|
||||||
} |
|
||||||
return this.view |
|
||||||
} |
|
||||||
|
|
||||||
SolidityState.prototype.init = function () { |
|
||||||
var self = this |
|
||||||
var decodeTimeout = null |
|
||||||
this.parent.event.register('indexChanged', this, function (index) { |
|
||||||
if (index < 0) { |
|
||||||
self.basicPanel.setMessage('invalid step index') |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
if (self.parent.currentStepIndex !== index) return |
|
||||||
if (!self.solidityProxy.loaded()) { |
|
||||||
self.basicPanel.setMessage('no source has been specified') |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
if (!self.storageResolver) { |
|
||||||
return |
|
||||||
} |
|
||||||
if (decodeTimeout) { |
|
||||||
window.clearTimeout(decodeTimeout) |
|
||||||
} |
|
||||||
self.basicPanel.setUpdating() |
|
||||||
decodeTimeout = setTimeout(() => { |
|
||||||
decode(self, index) |
|
||||||
}, 500) |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
function decode (self, index) { |
|
||||||
self.traceManager.getCurrentCalledAddressAt(self.parent.currentStepIndex, (error, address) => { |
|
||||||
if (error) { |
|
||||||
self.basicPanel.update({}) |
|
||||||
console.log(error) |
|
||||||
} else { |
|
||||||
if (self.stateVariablesByAddresses[address]) { |
|
||||||
extractStateVariables(self, self.stateVariablesByAddresses[address], address) |
|
||||||
} else { |
|
||||||
self.solidityProxy.extractStateVariablesAt(index, function (error, stateVars) { |
|
||||||
if (error) { |
|
||||||
self.basicPanel.update({}) |
|
||||||
console.log(error) |
|
||||||
} else { |
|
||||||
self.stateVariablesByAddresses[address] = stateVars |
|
||||||
extractStateVariables(self, stateVars, address) |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
function extractStateVariables (self, stateVars, address) { |
|
||||||
var storageViewer = new StorageViewer({ |
|
||||||
stepIndex: self.parent.currentStepIndex, |
|
||||||
tx: self.parent.tx, |
|
||||||
address: address |
|
||||||
}, self.storageResolver, self.traceManager) |
|
||||||
stateDecoder.decodeState(stateVars, storageViewer).then((result) => { |
|
||||||
self.basicPanel.setMessage('') |
|
||||||
if (!result.error) { |
|
||||||
self.basicPanel.update(result) |
|
||||||
} else { |
|
||||||
self.basicPanel.setMessage(result.error) |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = SolidityState |
|
@ -1,71 +0,0 @@ |
|||||||
'use strict' |
|
||||||
var yo = require('yo-yo') |
|
||||||
var BN = require('ethereumjs-util').BN |
|
||||||
|
|
||||||
module.exports = { |
|
||||||
formatSelf: formatSelf, |
|
||||||
extractData: extractData |
|
||||||
} |
|
||||||
|
|
||||||
function formatSelf (key, data) { |
|
||||||
var style = fontColor(data) |
|
||||||
var keyStyle = data.isProperty ? 'color:#847979' : '' |
|
||||||
if (data.type === 'string') { |
|
||||||
data.self = JSON.stringify(data.self) |
|
||||||
} |
|
||||||
return yo`<label style=${keyStyle}>${key}: <label style=${style}>${data.self}</label><label style='font-style:italic'> ${data.isProperty || !data.type ? '' : ' ' + data.type}</label></label>` |
|
||||||
} |
|
||||||
|
|
||||||
function extractData (item, parent, key) { |
|
||||||
var ret = {} |
|
||||||
if (item.isProperty) { |
|
||||||
return item |
|
||||||
} |
|
||||||
if (item.type.lastIndexOf(']') === item.type.length - 1) { |
|
||||||
ret.children = (item.value || []).map(function (item, index) { |
|
||||||
return {key: index, value: item} |
|
||||||
}) |
|
||||||
ret.children.unshift({ |
|
||||||
key: 'length', |
|
||||||
value: { |
|
||||||
self: (new BN(item.length.replace('0x', ''), 16)).toString(10), |
|
||||||
type: 'uint', |
|
||||||
isProperty: true |
|
||||||
} |
|
||||||
}) |
|
||||||
ret.isArray = true |
|
||||||
ret.self = parent.isArray ? '' : item.type |
|
||||||
} else if (item.type.indexOf('struct') === 0) { |
|
||||||
ret.children = Object.keys((item.value || {})).map(function (key) { |
|
||||||
return {key: key, value: item.value[key]} |
|
||||||
}) |
|
||||||
ret.self = item.type |
|
||||||
ret.isStruct = true |
|
||||||
} else if (item.type.indexOf('mapping') === 0) { |
|
||||||
ret.children = Object.keys((item.value || {})).map(function (key) { |
|
||||||
return {key: key, value: item.value[key]} |
|
||||||
}) |
|
||||||
ret.isMapping = true |
|
||||||
ret.self = item.type |
|
||||||
} else { |
|
||||||
ret.children = null |
|
||||||
ret.self = item.value |
|
||||||
ret.type = item.type |
|
||||||
} |
|
||||||
return ret |
|
||||||
} |
|
||||||
|
|
||||||
function fontColor (data) { |
|
||||||
var color = '#124B46' |
|
||||||
if (data.isArray || data.isStruct || data.isMapping) { |
|
||||||
color = '#847979' |
|
||||||
} else if (data.type.indexOf('uint') === 0 || |
|
||||||
data.type.indexOf('int') === 0 || |
|
||||||
data.type.indexOf('bool') === 0 || |
|
||||||
data.type.indexOf('enum') === 0) { |
|
||||||
color = '#0F0CE9' |
|
||||||
} else if (data.type === 'string') { |
|
||||||
color = '#E91E0C' |
|
||||||
} |
|
||||||
return 'color:' + color |
|
||||||
} |
|
@ -1,33 +0,0 @@ |
|||||||
'use strict' |
|
||||||
var DropdownPanel = require('./DropdownPanel') |
|
||||||
var yo = require('yo-yo') |
|
||||||
|
|
||||||
function StackPanel (_parent, _traceManager) { |
|
||||||
this.parent = _parent |
|
||||||
this.traceManager = _traceManager |
|
||||||
this.basicPanel = new DropdownPanel('Stack', {json: true, displayContentOnly: false}) |
|
||||||
this.init() |
|
||||||
} |
|
||||||
|
|
||||||
StackPanel.prototype.render = function () { |
|
||||||
return yo`<div id='stackpanel' >${this.basicPanel.render()}</div>` |
|
||||||
} |
|
||||||
|
|
||||||
StackPanel.prototype.init = function () { |
|
||||||
var self = this |
|
||||||
this.parent.event.register('indexChanged', this, function (index) { |
|
||||||
if (index < 0) return |
|
||||||
if (self.parent.currentStepIndex !== index) return |
|
||||||
|
|
||||||
self.traceManager.getStackAt(index, function (error, stack) { |
|
||||||
if (error) { |
|
||||||
self.basicPanel.update({}) |
|
||||||
console.log(error) |
|
||||||
} else if (self.parent.currentStepIndex === index) { |
|
||||||
self.basicPanel.update(stack) |
|
||||||
} |
|
||||||
}) |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = StackPanel |
|
@ -1,101 +0,0 @@ |
|||||||
'use strict' |
|
||||||
var yo = require('yo-yo') |
|
||||||
var DropdownPanel = require('./DropdownPanel') |
|
||||||
|
|
||||||
function StepDetail (_parentUI, _traceManager) { |
|
||||||
this.debugger = _parentUI.debugger |
|
||||||
this.parentUI = _parentUI |
|
||||||
this.traceManager = _traceManager |
|
||||||
|
|
||||||
this.basicPanel = new DropdownPanel('Step detail', {json: true, displayContentOnly: true}) |
|
||||||
|
|
||||||
this.detail = initDetail() |
|
||||||
this.view |
|
||||||
this.init() |
|
||||||
} |
|
||||||
|
|
||||||
StepDetail.prototype.render = function () { |
|
||||||
return yo`<div id='stepdetail' >${this.basicPanel.render()}</div>` |
|
||||||
} |
|
||||||
|
|
||||||
StepDetail.prototype.init = function () { |
|
||||||
var self = this |
|
||||||
this.debugger.event.register('traceUnloaded', this, function () { |
|
||||||
self.detail = initDetail() |
|
||||||
self.basicPanel.update(self.detail) |
|
||||||
}) |
|
||||||
|
|
||||||
this.debugger.event.register('newTraceLoaded', this, function () { |
|
||||||
self.detail = initDetail() |
|
||||||
self.basicPanel.update(self.detail) |
|
||||||
}) |
|
||||||
|
|
||||||
this.parentUI.event.register('indexChanged', this, function (index) { |
|
||||||
if (index < 0) return |
|
||||||
|
|
||||||
self.detail['vm trace step'] = index |
|
||||||
|
|
||||||
self.traceManager.getCurrentStep(index, function (error, step) { |
|
||||||
if (error) { |
|
||||||
console.log(error) |
|
||||||
self.detail['execution step'] = '-' |
|
||||||
} else { |
|
||||||
self.detail['execution step'] = step |
|
||||||
} |
|
||||||
self.basicPanel.update(self.detail) |
|
||||||
}) |
|
||||||
|
|
||||||
self.traceManager.getMemExpand(index, function (error, addmem) { |
|
||||||
if (error) { |
|
||||||
console.log(error) |
|
||||||
self.detail['add memory'] = '-' |
|
||||||
} else { |
|
||||||
self.detail['add memory'] = addmem |
|
||||||
} |
|
||||||
self.basicPanel.update(self.detail) |
|
||||||
}) |
|
||||||
|
|
||||||
self.traceManager.getStepCost(index, function (error, gas) { |
|
||||||
if (error) { |
|
||||||
console.log(error) |
|
||||||
self.detail.gas = '-' |
|
||||||
} else { |
|
||||||
self.detail.gas = gas |
|
||||||
} |
|
||||||
self.basicPanel.update(self.detail) |
|
||||||
}) |
|
||||||
|
|
||||||
self.traceManager.getCurrentCalledAddressAt(index, function (error, address) { |
|
||||||
if (error) { |
|
||||||
console.log(error) |
|
||||||
self.detail['loaded address'] = '-' |
|
||||||
} else { |
|
||||||
self.detail['loaded address'] = address |
|
||||||
} |
|
||||||
self.basicPanel.update(self.detail) |
|
||||||
}) |
|
||||||
|
|
||||||
self.traceManager.getRemainingGas(index, function (error, remaingas) { |
|
||||||
if (error) { |
|
||||||
console.log(error) |
|
||||||
self.detail['remaining gas'] = '-' |
|
||||||
} else { |
|
||||||
self.detail['remaining gas'] = remaingas |
|
||||||
} |
|
||||||
self.basicPanel.update(self.detail) |
|
||||||
}) |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = StepDetail |
|
||||||
|
|
||||||
function initDetail () { |
|
||||||
return { |
|
||||||
'vm trace step': '-', |
|
||||||
'execution step': '-', |
|
||||||
'add memory': '', |
|
||||||
'gas': '', |
|
||||||
'remaining gas': '-', |
|
||||||
'loaded address': '-' |
|
||||||
} |
|
||||||
} |
|
@ -1,205 +0,0 @@ |
|||||||
'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 |
|
@ -1,50 +0,0 @@ |
|||||||
'use strict' |
|
||||||
var DropdownPanel = require('./DropdownPanel') |
|
||||||
var remixDebug = require('remix-debug') |
|
||||||
var StorageViewer = remixDebug.storage.StorageViewer |
|
||||||
var yo = require('yo-yo') |
|
||||||
|
|
||||||
function StoragePanel (_parent, _traceManager) { |
|
||||||
this.parent = _parent |
|
||||||
this.storageResolver = null |
|
||||||
this.traceManager = _traceManager |
|
||||||
this.basicPanel = new DropdownPanel('Storage', {json: true}) |
|
||||||
this.init() |
|
||||||
this.disabled = false |
|
||||||
} |
|
||||||
|
|
||||||
StoragePanel.prototype.render = function () { |
|
||||||
return yo`<div id='storagepanel' >${this.basicPanel.render()}</div>` |
|
||||||
} |
|
||||||
|
|
||||||
StoragePanel.prototype.init = function () { |
|
||||||
var self = this |
|
||||||
this.parent.event.register('indexChanged', this, function (index) { |
|
||||||
if (self.disabled) return |
|
||||||
if (index < 0) return |
|
||||||
if (self.parent.currentStepIndex !== index) return |
|
||||||
if (!self.storageResolver) return |
|
||||||
|
|
||||||
this.traceManager.getCurrentCalledAddressAt(index, (error, address) => { |
|
||||||
if (!error) { |
|
||||||
var storageViewer = new StorageViewer({ |
|
||||||
stepIndex: self.parent.currentStepIndex, |
|
||||||
tx: self.parent.tx, |
|
||||||
address: address |
|
||||||
}, self.storageResolver, self.traceManager) |
|
||||||
|
|
||||||
storageViewer.storageRange((error, storage) => { |
|
||||||
if (error) { |
|
||||||
console.log(error) |
|
||||||
self.basicPanel.update({}) |
|
||||||
} else if (self.parent.currentStepIndex === index) { |
|
||||||
var header = storageViewer.isComplete(address) ? 'completely loaded' : 'partially loaded...' |
|
||||||
self.basicPanel.update(storage, header) |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
}) |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = StoragePanel |
|
@ -1,206 +0,0 @@ |
|||||||
var remixLib = require('remix-lib') |
|
||||||
var EventManager = remixLib.EventManager |
|
||||||
var traceHelper = remixLib.helpers.trace |
|
||||||
var yo = require('yo-yo') |
|
||||||
var init = remixLib.init |
|
||||||
var csjs = require('csjs-inject') |
|
||||||
var styleGuide = require('../../../../ui/styles-guide/theme-chooser') |
|
||||||
var styles = styleGuide.chooser() |
|
||||||
|
|
||||||
var css = csjs` |
|
||||||
.container { |
|
||||||
display: flex; |
|
||||||
flex-direction: column; |
|
||||||
} |
|
||||||
.txContainer { |
|
||||||
display: flex; |
|
||||||
flex-direction: column; |
|
||||||
} |
|
||||||
.txinputs { |
|
||||||
width: 100%; |
|
||||||
display: flex; |
|
||||||
justify-content: center; |
|
||||||
} |
|
||||||
.txinput { |
|
||||||
${styles.rightPanel.debuggerTab.input_Debugger} |
|
||||||
margin: 3px; |
|
||||||
width: inherit; |
|
||||||
} |
|
||||||
.txbuttons { |
|
||||||
width: 100%; |
|
||||||
display: flex; |
|
||||||
justify-content: center; |
|
||||||
} |
|
||||||
.txbutton { |
|
||||||
${styles.rightPanel.debuggerTab.button_Debugger} |
|
||||||
width: inherit; |
|
||||||
} |
|
||||||
.txbuttonstart { |
|
||||||
${styles.rightPanel.debuggerTab.button_Debugger} |
|
||||||
} |
|
||||||
.txbutton:hover { |
|
||||||
color: ${styles.rightPanel.debuggerTab.button_Debugger_icon_HoverColor}; |
|
||||||
} |
|
||||||
.vmargin { |
|
||||||
margin-top: 10px; |
|
||||||
margin-bottom: 10px; |
|
||||||
} |
|
||||||
` |
|
||||||
function TxBrowser (_parent, opts) { |
|
||||||
this.event = new EventManager() |
|
||||||
|
|
||||||
this.blockNumber |
|
||||||
this.txNumber |
|
||||||
this.view |
|
||||||
this.displayConnectionSetting = opts.displayConnectionSetting |
|
||||||
this.web3 = opts.web3 |
|
||||||
var self = this |
|
||||||
_parent.event.register('providerChanged', this, function (provider) { |
|
||||||
self.setDefaultValues() |
|
||||||
if (self.view) { |
|
||||||
yo.update(self.view, self.render()) |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
// creation 0xa9619e1d0a35b2c1d686f5b661b3abd87f998d2844e8e9cc905edb57fc9ce349
|
|
||||||
// invokation 0x71a6d583d16d142c5c3e8903060e8a4ee5a5016348a9448df6c3e63b68076ec4 0xcda2b2835add61af54cf83bd076664d98d7908c6cd98d86423b3b48d8b8e51ff
|
|
||||||
// test:
|
|
||||||
// creation: 0x72908de76f99fca476f9e3a3b5d352f350a98cd77d09cebfc59ffe32a6ecaa0b
|
|
||||||
// invokation: 0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51
|
|
||||||
|
|
||||||
TxBrowser.prototype.setDefaultValues = function () { |
|
||||||
this.connectInfo = '' |
|
||||||
if (this.view) { |
|
||||||
yo.update(this.view, this.render()) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
TxBrowser.prototype.submit = function (tx) { |
|
||||||
var self = this |
|
||||||
self.event.trigger('newTxLoading', [this.blockNumber, this.txNumber]) |
|
||||||
if (tx) { |
|
||||||
return self.update(null, tx) |
|
||||||
} |
|
||||||
if (!this.txNumber) { |
|
||||||
self.update('no tx index or tx hash to look for') |
|
||||||
return |
|
||||||
} |
|
||||||
try { |
|
||||||
if (this.txNumber.indexOf('0x') !== -1) { |
|
||||||
self.web3.eth.getTransaction(this.txNumber, function (error, result) { |
|
||||||
self.update(error, result) |
|
||||||
}) |
|
||||||
} else { |
|
||||||
self.web3.eth.getTransactionFromBlock(this.blockNumber, this.txNumber, function (error, result) { |
|
||||||
self.update(error, result) |
|
||||||
}) |
|
||||||
} |
|
||||||
} catch (e) { |
|
||||||
self.update(e.message) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
TxBrowser.prototype.update = function (error, tx) { |
|
||||||
var info = {} |
|
||||||
if (error) { |
|
||||||
this.view.querySelector('#error').innerHTML = error |
|
||||||
} else { |
|
||||||
if (tx) { |
|
||||||
this.view.querySelector('#error').innerHTML = '' |
|
||||||
if (!tx.to) { |
|
||||||
tx.to = traceHelper.contractCreationToken('0') |
|
||||||
} |
|
||||||
info.from = tx.from |
|
||||||
info.to = tx.to |
|
||||||
info.hash = tx.hash |
|
||||||
this.event.trigger('newTraceRequested', [this.blockNumber, this.txNumber, tx]) |
|
||||||
} else { |
|
||||||
var mes = '<not found>' |
|
||||||
info.from = mes |
|
||||||
info.to = mes |
|
||||||
info.hash = mes |
|
||||||
this.view.querySelector('#error').innerHTML = 'Cannot find transaction with reference. Block number: ' + this.blockNumber + '. Transaction index/hash: ' + this.txNumber |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
TxBrowser.prototype.updateWeb3Url = function (newhost) { |
|
||||||
init.setProvider(global.web3, newhost) |
|
||||||
var self = this |
|
||||||
this.checkWeb3(function (error, block) { |
|
||||||
if (!error) { |
|
||||||
self.connectInfo = 'Connected to ' + global.web3.currentProvider.host + '. Current block number: ' + block |
|
||||||
} else { |
|
||||||
self.connectInfo = 'Unable to connect to ' + global.web3.currentProvider.host + '. ' + error.message |
|
||||||
} |
|
||||||
yo.update(self.view, self.render()) |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
TxBrowser.prototype.checkWeb3 = function (callback) { |
|
||||||
try { |
|
||||||
global.web3.eth.getBlockNumber(function (error, block) { |
|
||||||
callback(error, block) |
|
||||||
}) |
|
||||||
} catch (e) { |
|
||||||
console.log(e) |
|
||||||
callback(e.message, null) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
TxBrowser.prototype.updateBlockN = function (ev) { |
|
||||||
this.blockNumber = ev.target.value |
|
||||||
} |
|
||||||
|
|
||||||
TxBrowser.prototype.updateTxN = function (ev) { |
|
||||||
this.txNumber = ev.target.value |
|
||||||
} |
|
||||||
|
|
||||||
TxBrowser.prototype.load = function (txHash, tx) { |
|
||||||
this.txNumber = txHash |
|
||||||
this.submit(tx) |
|
||||||
} |
|
||||||
|
|
||||||
TxBrowser.prototype.unload = function (txHash) { |
|
||||||
this.event.trigger('unloadRequested') |
|
||||||
this.init() |
|
||||||
} |
|
||||||
|
|
||||||
TxBrowser.prototype.init = function (ev) { |
|
||||||
this.setDefaultValues() |
|
||||||
} |
|
||||||
|
|
||||||
TxBrowser.prototype.connectionSetting = function () { |
|
||||||
if (this.displayConnectionSetting) { |
|
||||||
var self = this |
|
||||||
return yo`<div class="${css.vmargin}"><span>Node URL: </span><input onkeyup=${function () { self.updateWeb3Url(arguments[0].target.value) }} value=${global.web3.currentProvider ? global.web3.currentProvider.host : ' - none - '} type='text' />
|
|
||||||
<span>${this.connectInfo}</span></div>` |
|
||||||
} else { |
|
||||||
return '' |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
TxBrowser.prototype.render = function () { |
|
||||||
var self = this |
|
||||||
var view = yo`<div class="${css.container}">
|
|
||||||
${this.connectionSetting()} |
|
||||||
<div class="${css.txContainer}"> |
|
||||||
<div class="${css.txinputs}"> |
|
||||||
<input class="${css.txinput}" onkeyup=${function () { self.updateBlockN(arguments[0]) }} type='text' placeholder=${'Block number'} /> |
|
||||||
<input class="${css.txinput}" id='txinput' onkeyup=${function () { self.updateTxN(arguments[0]) }} type='text' placeholder=${'Transaction index or hash'} /> |
|
||||||
</div> |
|
||||||
<div class="${css.txbuttons}"> |
|
||||||
<button id='load' class='${css.txbutton}' title='start debugging' onclick=${function () { self.submit() }}>Start debugging</button> |
|
||||||
<button id='unload' class='${css.txbutton}' title='stop debugging' onclick=${function () { self.unload() }}>Stop</button> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<span id='error'></span> |
|
||||||
</div>` |
|
||||||
if (!this.view) { |
|
||||||
this.view = view |
|
||||||
} |
|
||||||
return view |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = TxBrowser |
|
@ -1,126 +0,0 @@ |
|||||||
'use strict' |
|
||||||
var csjs = require('csjs-inject') |
|
||||||
var CodeListView = require('./CodeListView') |
|
||||||
var CalldataPanel = require('./CalldataPanel') |
|
||||||
var MemoryPanel = require('./MemoryPanel') |
|
||||||
var CallstackPanel = require('./CallstackPanel') |
|
||||||
var StackPanel = require('./StackPanel') |
|
||||||
var StoragePanel = require('./StoragePanel') |
|
||||||
var FullStoragesChangesPanel = require('./FullStoragesChanges') |
|
||||||
var StepDetail = require('./StepDetail') |
|
||||||
var DropdownPanel = require('./DropdownPanel') |
|
||||||
var SolidityState = require('./SolidityState') |
|
||||||
var SolidityLocals = require('./SolidityLocals') |
|
||||||
var remixDebug = require('remix-debug') |
|
||||||
var StorageResolver = remixDebug.storage.StorageResolver |
|
||||||
var yo = require('yo-yo') |
|
||||||
|
|
||||||
var css = csjs` |
|
||||||
.asmCode { |
|
||||||
float: left; |
|
||||||
width: 50%; |
|
||||||
} |
|
||||||
.stepDetail { |
|
||||||
} |
|
||||||
.vmheadView { |
|
||||||
margin-top:10px; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
function VmDebugger (_parentUI, _traceManager, _codeManager, _solidityProxy, _callTree) { |
|
||||||
let _parent = _parentUI.debugger |
|
||||||
var self = this |
|
||||||
this.view |
|
||||||
this.asmCode = new CodeListView(_parent, _codeManager) |
|
||||||
this.stackPanel = new StackPanel(_parentUI, _traceManager) |
|
||||||
this.storagePanel = new StoragePanel(_parentUI, _traceManager) |
|
||||||
this.memoryPanel = new MemoryPanel(_parentUI, _traceManager) |
|
||||||
this.calldataPanel = new CalldataPanel(_parentUI, _traceManager) |
|
||||||
this.callstackPanel = new CallstackPanel(_parentUI, _traceManager) |
|
||||||
this.stepDetail = new StepDetail(_parentUI, _traceManager) |
|
||||||
this.solidityState = new SolidityState(_parentUI, _traceManager, _codeManager, _solidityProxy) |
|
||||||
this.solidityLocals = new SolidityLocals(_parentUI, _traceManager, _callTree) |
|
||||||
|
|
||||||
/* Return values - */ |
|
||||||
this.returnValuesPanel = new DropdownPanel('Return Value', {json: true}) |
|
||||||
this.returnValuesPanel.data = {} |
|
||||||
_parentUI.event.register('indexChanged', this.returnValuesPanel, function (index) { |
|
||||||
if (!self.view) return |
|
||||||
var innerself = this |
|
||||||
_traceManager.getReturnValue(index, function (error, returnValue) { |
|
||||||
if (error) { |
|
||||||
innerself.update([error]) |
|
||||||
} else if (_parentUI.currentStepIndex === index) { |
|
||||||
innerself.update([returnValue]) |
|
||||||
} |
|
||||||
}) |
|
||||||
}) |
|
||||||
/* Return values - */ |
|
||||||
|
|
||||||
this.fullStoragesChangesPanel = new FullStoragesChangesPanel(_parentUI, _traceManager) |
|
||||||
|
|
||||||
_parent.event.register('newTraceLoaded', this, function () { |
|
||||||
if (!self.view) return |
|
||||||
var storageResolver = new StorageResolver({web3: _parent.web3}) |
|
||||||
self.storagePanel.storageResolver = storageResolver |
|
||||||
self.solidityState.storageResolver = storageResolver |
|
||||||
self.solidityLocals.storageResolver = storageResolver |
|
||||||
self.fullStoragesChangesPanel.storageResolver = storageResolver |
|
||||||
self.asmCode.basicPanel.show() |
|
||||||
self.stackPanel.basicPanel.show() |
|
||||||
self.storagePanel.basicPanel.show() |
|
||||||
self.memoryPanel.basicPanel.show() |
|
||||||
self.calldataPanel.basicPanel.show() |
|
||||||
self.callstackPanel.basicPanel.show() |
|
||||||
}) |
|
||||||
_parent.event.register('traceUnloaded', this, function () { |
|
||||||
if (!self.view) return |
|
||||||
}) |
|
||||||
_parent.callTree.event.register('callTreeReady', () => { |
|
||||||
if (!self.view) return |
|
||||||
if (_parent.callTree.reducedTrace.length) { |
|
||||||
self.solidityLocals.basicPanel.show() |
|
||||||
self.solidityState.basicPanel.show() |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
VmDebugger.prototype.renderHead = function () { |
|
||||||
var headView = yo`<div id='vmheadView' class=${css.vmheadView}>
|
|
||||||
<div> |
|
||||||
<div class=${css.asmCode}>${this.asmCode.render()}</div> |
|
||||||
<div class=${css.stepDetail}>${this.stepDetail.render()}</div> |
|
||||||
</div> |
|
||||||
</div>` |
|
||||||
if (!this.headView) { |
|
||||||
this.headView = headView |
|
||||||
} |
|
||||||
return headView |
|
||||||
} |
|
||||||
|
|
||||||
VmDebugger.prototype.remove = function () { |
|
||||||
// used to stop listenning on event. bad and should be "refactored"
|
|
||||||
this.view = null |
|
||||||
} |
|
||||||
|
|
||||||
VmDebugger.prototype.render = function () { |
|
||||||
var view = yo`<div id='vmdebugger'>
|
|
||||||
<div> |
|
||||||
${this.solidityLocals.render()} |
|
||||||
${this.solidityState.render()} |
|
||||||
${this.stackPanel.render()} |
|
||||||
${this.memoryPanel.render()} |
|
||||||
${this.storagePanel.render()} |
|
||||||
${this.callstackPanel.render()} |
|
||||||
${this.calldataPanel.render()} |
|
||||||
${this.returnValuesPanel.render()} |
|
||||||
${this.fullStoragesChangesPanel.render()} |
|
||||||
</div> |
|
||||||
</div>` |
|
||||||
if (!this.view) { |
|
||||||
this.view = view |
|
||||||
} |
|
||||||
return view |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = VmDebugger |
|
Loading…
Reference in new issue