Commit 7a434782 authored by chriseth's avatar chriseth Committed by GitHub

Merge pull request #179 from ethereum/treeView

Treeview - Add solidity type
parents 0de74536 3da44a87
...@@ -181,7 +181,7 @@ function struct (type, stateDefinitions, contractName, location) { ...@@ -181,7 +181,7 @@ function struct (type, stateDefinitions, contractName, location) {
} }
var memberDetails = getStructMembers(match[1], stateDefinitions, contractName, location) // type is used to extract the ast struct definition var memberDetails = getStructMembers(match[1], stateDefinitions, contractName, location) // type is used to extract the ast struct definition
if (!memberDetails) return null if (!memberDetails) return null
return new StructType(memberDetails, location) return new StructType(memberDetails, location, match[1])
} else { } else {
return null return null
} }
......
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
function solidityLocals (vmtraceIndex, internalTreeCall, stack, memory) { function solidityLocals (vmtraceIndex, internalTreeCall, stack, memory) {
var scope = internalTreeCall.findScope(vmtraceIndex) var scope = internalTreeCall.findScope(vmtraceIndex)
if (!scope) { if (!scope) {
return { 'error': 'Can\'t display locals. reason: compilation result might not have been provided' } var error = { 'message': 'Can\'t display locals. reason: compilation result might not have been provided' }
throw error
} }
var locals = {} var locals = {}
memory = formatMemory(memory) memory = formatMemory(memory)
......
...@@ -17,7 +17,8 @@ class ArrayType extends RefType { ...@@ -17,7 +17,8 @@ class ArrayType extends RefType {
storageSlots = arraySize * underlyingType.storageSlots storageSlots = arraySize * underlyingType.storageSlots
} }
} }
super(storageSlots, 32, 'array', location) var size = arraySize !== 'dynamic' ? arraySize : ''
super(storageSlots, 32, underlyingType.typeName + '[' + size + ']', location)
this.underlyingType = underlyingType this.underlyingType = underlyingType
this.arraySize = arraySize this.arraySize = arraySize
} }
...@@ -52,7 +53,8 @@ class ArrayType extends RefType { ...@@ -52,7 +53,8 @@ class ArrayType extends RefType {
} }
return { return {
value: ret, value: ret,
length: '0x' + size.toString(16) length: '0x' + size.toString(16),
type: this.typeName
} }
} }
...@@ -69,7 +71,11 @@ class ArrayType extends RefType { ...@@ -69,7 +71,11 @@ class ArrayType extends RefType {
ret.push(this.underlyingType.decodeFromMemory(contentOffset, memory)) ret.push(this.underlyingType.decodeFromMemory(contentOffset, memory))
offset += 32 offset += 32
} }
return ret return {
value: ret,
length: '0x' + length.toString(16),
type: this.typeName
}
} }
} }
......
...@@ -30,7 +30,8 @@ class DynamicByteArray extends RefType { ...@@ -30,7 +30,8 @@ class DynamicByteArray extends RefType {
var size = parseInt(value.substr(value.length - 2, 2), 16) / 2 var size = parseInt(value.substr(value.length - 2, 2), 16) / 2
return { return {
value: '0x' + value.substr(0, size * 2), value: '0x' + value.substr(0, size * 2),
length: '0x' + size.toString(16) length: '0x' + size.toString(16),
type: this.typeName
} }
} }
} }
...@@ -41,7 +42,8 @@ class DynamicByteArray extends RefType { ...@@ -41,7 +42,8 @@ class DynamicByteArray extends RefType {
length = 2 * parseInt(length, 16) length = 2 * parseInt(length, 16)
return { return {
length: '0x' + length.toString(16), length: '0x' + length.toString(16),
value: '0x' + memory.substr(offset + 64, length) value: '0x' + memory.substr(offset + 64, length),
type: this.typeName
} }
} }
} }
......
...@@ -3,7 +3,7 @@ var ValueType = require('./ValueType') ...@@ -3,7 +3,7 @@ var ValueType = require('./ValueType')
class FixedByteArray extends ValueType { class FixedByteArray extends ValueType {
constructor (storageBytes) { constructor (storageBytes) {
super(1, storageBytes, 'bytesX') super(1, storageBytes, 'bytes' + storageBytes)
} }
decodeValue (value) { decodeValue (value) {
......
...@@ -4,7 +4,7 @@ var ValueType = require('./ValueType') ...@@ -4,7 +4,7 @@ var ValueType = require('./ValueType')
class Int extends ValueType { class Int extends ValueType {
constructor (storageBytes) { constructor (storageBytes) {
super(1, storageBytes, 'int') super(1, storageBytes, 'int' + storageBytes * 8)
} }
decodeValue (value) { decodeValue (value) {
......
...@@ -20,7 +20,10 @@ class RefType { ...@@ -20,7 +20,10 @@ class RefType {
*/ */
decodeFromStack (stackDepth, stack, memory, storage) { decodeFromStack (stackDepth, stack, memory, storage) {
if (stack.length - 1 < stackDepth) { if (stack.length - 1 < stackDepth) {
return { error: '<decoding failed - stack underflow ' + stackDepth + '>' } return {
error: '<decoding failed - stack underflow ' + stackDepth + '>',
type: this.typeName
}
} }
if (!storage) { if (!storage) {
storage = {} // TODO this is a fallback, should manage properly locals store in storage storage = {} // TODO this is a fallback, should manage properly locals store in storage
...@@ -32,7 +35,10 @@ class RefType { ...@@ -32,7 +35,10 @@ class RefType {
} else if (this.isInMemory()) { } else if (this.isInMemory()) {
return this.decodeFromMemoryInternal(offset, memory) return this.decodeFromMemoryInternal(offset, memory)
} else { } else {
return { error: '<decoding failed - no decoder for ' + this.location + '>' } return {
error: '<decoding failed - no decoder for ' + this.location + '>',
type: this.typeName
}
} }
} }
......
...@@ -30,7 +30,8 @@ function format (decoded) { ...@@ -30,7 +30,8 @@ function format (decoded) {
value = value.replace('0x', '').replace(/(..)/g, '%$1') value = value.replace('0x', '').replace(/(..)/g, '%$1')
var ret = { var ret = {
length: decoded.length, length: decoded.length,
raw: decoded.value raw: decoded.value,
type: 'string'
} }
try { try {
ret.value = decodeURIComponent(value) ret.value = decodeURIComponent(value)
......
...@@ -3,8 +3,8 @@ var util = require('./util') ...@@ -3,8 +3,8 @@ var util = require('./util')
var RefType = require('./RefType') var RefType = require('./RefType')
class Struct extends RefType { class Struct extends RefType {
constructor (memberDetails, location) { constructor (memberDetails, location, fullType) {
super(memberDetails.storageSlots, 32, 'struct', location) super(memberDetails.storageSlots, 32, 'struct ' + fullType, location)
this.members = memberDetails.members this.members = memberDetails.members
} }
...@@ -17,7 +17,10 @@ class Struct extends RefType { ...@@ -17,7 +17,10 @@ class Struct extends RefType {
} }
ret[item.name] = item.type.decodeFromStorage(globalLocation, storageContent) ret[item.name] = item.type.decodeFromStorage(globalLocation, storageContent)
}) })
return ret return {
value: ret,
type: this.typeName
}
} }
decodeFromMemoryInternal (offset, memory) { decodeFromMemoryInternal (offset, memory) {
...@@ -28,7 +31,10 @@ class Struct extends RefType { ...@@ -28,7 +31,10 @@ class Struct extends RefType {
ret[item.name] = member ret[item.name] = member
offset += 32 offset += 32
}) })
return ret return {
value: ret,
type: this.typeName
}
} }
} }
......
...@@ -4,7 +4,7 @@ var ValueType = require('./ValueType') ...@@ -4,7 +4,7 @@ var ValueType = require('./ValueType')
class Uint extends ValueType { class Uint extends ValueType {
constructor (storageBytes) { constructor (storageBytes) {
super(1, storageBytes, 'uint') super(1, storageBytes, 'uint' + storageBytes * 8)
} }
decodeValue (value) { decodeValue (value) {
......
...@@ -18,7 +18,10 @@ class ValueType { ...@@ -18,7 +18,10 @@ class ValueType {
*/ */
decodeFromStorage (location, storageContent) { decodeFromStorage (location, storageContent) {
var value = util.extractHexValue(location, storageContent, this.storageBytes) var value = util.extractHexValue(location, storageContent, this.storageBytes)
return this.decodeValue(value) return {
value: this.decodeValue(value),
type: this.typeName
}
} }
/** /**
...@@ -30,10 +33,15 @@ class ValueType { ...@@ -30,10 +33,15 @@ class ValueType {
* @return {Object} - decoded value * @return {Object} - decoded value
*/ */
decodeFromStack (stackDepth, stack, memory) { decodeFromStack (stackDepth, stack, memory) {
var value
if (stackDepth >= stack.length) { if (stackDepth >= stack.length) {
return this.decodeValue('') value = this.decodeValue('')
} else { } else {
return this.decodeValue(stack[stack.length - 1 - stackDepth].replace('0x', '')) value = this.decodeValue(stack[stack.length - 1 - stackDepth].replace('0x', ''))
}
return {
value: value,
type: this.typeName
} }
} }
...@@ -46,7 +54,10 @@ class ValueType { ...@@ -46,7 +54,10 @@ class ValueType {
*/ */
decodeFromMemory (offset, memory) { decodeFromMemory (offset, memory) {
var value = memory.substr(2 * offset, 64) var value = memory.substr(2 * offset, 64)
return this.decodeValue(util.extractHexByteSlice(value, this.storageBytes, 0)) return {
value: this.decodeValue(util.extractHexByteSlice(value, this.storageBytes, 0)),
type: this.typeName
}
} }
} }
......
'use strict'
var style = require('./styles/basicStyles')
var yo = require('yo-yo')
var ui = require('../helpers/ui')
function ASMCode (_parent, _codeManager) {
this.parent = _parent
this.codeManager = _codeManager
this.code
this.address
this.codeView
this.init()
}
ASMCode.prototype.render = function () {
var view = (
yo`<select size='10' id='asmitems' ref='itemsList' style=${ui.formatCss(style.instructionsList)}>
${this.codeView}
</select>`
)
if (!this.view) {
this.view = view
}
return view
}
ASMCode.prototype.init = function () {
this.codeManager.event.register('changed', this, this.changed)
}
ASMCode.prototype.indexChanged = function (index) {
document.getElementById('asmitems').value = index
}
ASMCode.prototype.changed = function (code, address, index) {
if (this.address !== address) {
this.code = code
this.address = address
this.renderAssemblyItems()
yo.update(this.view, this.render())
}
this.indexChanged(index)
}
ASMCode.prototype.renderAssemblyItems = function () {
if (this.code) {
this.codeView = this.code.map(function (item, i) {
return yo`<option key=${i} value=${i}>${item}</option>`
})
return this.codeView
}
}
module.exports = ASMCode
...@@ -41,6 +41,7 @@ DropdownPanel.prototype.render = function (overridestyle) { ...@@ -41,6 +41,7 @@ DropdownPanel.prototype.render = function (overridestyle) {
var self = this var self = this
var view = yo`<div> var view = yo`<div>
<div class='title' style=${ui.formatCss(styleDropdown.title)} onclick=${function () { self.toggle() }}> <div class='title' style=${ui.formatCss(styleDropdown.title)} onclick=${function () { self.toggle() }}>
<div style=${ui.formatCss(styleDropdown.caret)} class='fa fa-caret-right'></div>
<div style=${ui.formatCss(styleDropdown.inner, styleDropdown.titleInner)}>${this.name}</div> <div style=${ui.formatCss(styleDropdown.inner, styleDropdown.titleInner)}>${this.name}</div>
</div> </div>
<div class='dropdownpanel' style=${ui.formatCss(styleDropdown.content)} style='display:none'> <div class='dropdownpanel' style=${ui.formatCss(styleDropdown.content)} style='display:none'>
...@@ -65,24 +66,31 @@ DropdownPanel.prototype.toggleRaw = function () { ...@@ -65,24 +66,31 @@ DropdownPanel.prototype.toggleRaw = function () {
DropdownPanel.prototype.toggle = function () { DropdownPanel.prototype.toggle = function () {
var el = this.view.querySelector('.dropdownpanel') var el = this.view.querySelector('.dropdownpanel')
var caret = this.view.querySelector('.title').firstElementChild
if (el.style.display === '') { if (el.style.display === '') {
el.style.display = 'none' el.style.display = 'none'
caret.className = 'fa fa-caret-right'
} else { } else {
el.style.display = '' el.style.display = ''
caret.className = 'fa fa-caret-down'
} }
} }
DropdownPanel.prototype.hide = function () { DropdownPanel.prototype.hide = function () {
if (this.view) { if (this.view) {
var caret = this.view.querySelector('.title').firstElementChild
var el = this.view.querySelector('.dropdownpanel') var el = this.view.querySelector('.dropdownpanel')
el.style.display = 'none' el.style.display = 'none'
caret.className = 'fa fa-caret-right'
} }
} }
DropdownPanel.prototype.show = function () { DropdownPanel.prototype.show = function () {
if (this.view) { if (this.view) {
var caret = this.view.querySelector('.title').firstElementChild
var el = this.view.querySelector('.dropdownpanel') var el = this.view.querySelector('.dropdownpanel')
el.style.display = '' el.style.display = ''
caret.className = 'fa fa-caret-down'
} }
} }
......
'use strict' 'use strict'
var DropdownPanel = require('./DropdownPanel') var DropdownPanel = require('./DropdownPanel')
var localDecoder = require('../solidity/localDecoder') var localDecoder = require('../solidity/localDecoder')
var solidityTypeFormatter = require('./SolidityTypeFormatter')
var yo = require('yo-yo') var yo = require('yo-yo')
class SolidityLocals { class SolidityLocals {
...@@ -9,20 +10,32 @@ class SolidityLocals { ...@@ -9,20 +10,32 @@ class SolidityLocals {
this.parent = _parent this.parent = _parent
this.internalTreeCall = internalTreeCall this.internalTreeCall = internalTreeCall
this.traceManager = _traceManager this.traceManager = _traceManager
this.basicPanel = new DropdownPanel('Solidity Locals', {json: true}) this.basicPanel = new DropdownPanel('Solidity Locals', {
json: true,
formatSelf: solidityTypeFormatter.formatSelf,
extractData: solidityTypeFormatter.extractData
})
this.init() this.init()
this.view
} }
render () { render () {
return yo`<div id='soliditylocals' >${this.basicPanel.render()}</div>` this.view = yo`<div id='soliditylocals' >
<div id='warning'></div>
${this.basicPanel.render()}
</div>`
return this.view
} }
init () { init () {
this.parent.event.register('indexChanged', this, (index) => { this.parent.event.register('indexChanged', this, (index) => {
var warningDiv = this.view.querySelector('#warning')
warningDiv.innerHTML = ''
if (index < 0) { if (index < 0) {
this.basicPanel.update({info: 'invalid step index'}) warningDiv.innerHTML = 'invalid step index'
return return
} }
if (this.parent.currentStepIndex !== index) return if (this.parent.currentStepIndex !== index) return
this.traceManager.waterfall([ this.traceManager.waterfall([
...@@ -33,8 +46,12 @@ class SolidityLocals { ...@@ -33,8 +46,12 @@ class SolidityLocals {
if (!error) { if (!error) {
var stack = result[0].value var stack = result[0].value
var memory = result[1].value var memory = result[1].value
try {
var locals = localDecoder.solidityLocals(index, this.internalTreeCall, stack, memory) var locals = localDecoder.solidityLocals(index, this.internalTreeCall, stack, memory)
this.basicPanel.update(locals) this.basicPanel.update(locals)
} catch (e) {
warningDiv.innerHTML = e.message
}
} }
}) })
}) })
......
'use strict' 'use strict'
var DropdownPanel = require('./DropdownPanel') var DropdownPanel = require('./DropdownPanel')
var stateDecoder = require('../solidity/stateDecoder') var stateDecoder = require('../solidity/stateDecoder')
var solidityTypeFormatter = require('./SolidityTypeFormatter')
var yo = require('yo-yo') var yo = require('yo-yo')
function SolidityState (_parent, _traceManager, _codeManager, _solidityProxy) { function SolidityState (_parent, _traceManager, _codeManager, _solidityProxy) {
...@@ -8,24 +9,36 @@ function SolidityState (_parent, _traceManager, _codeManager, _solidityProxy) { ...@@ -8,24 +9,36 @@ function SolidityState (_parent, _traceManager, _codeManager, _solidityProxy) {
this.traceManager = _traceManager this.traceManager = _traceManager
this.codeManager = _codeManager this.codeManager = _codeManager
this.solidityProxy = _solidityProxy this.solidityProxy = _solidityProxy
this.basicPanel = new DropdownPanel('Solidity State', {json: true}) this.basicPanel = new DropdownPanel('Solidity State', {
json: true,
formatSelf: solidityTypeFormatter.formatSelf,
extractData: solidityTypeFormatter.extractData
})
this.init() this.init()
this.view
} }
SolidityState.prototype.render = function () { SolidityState.prototype.render = function () {
return yo`<div id='soliditystate' >${this.basicPanel.render()}</div>` this.view = yo`<div id='soliditystate' >
<div id='warning'></div>
${this.basicPanel.render()}
</div>`
return this.view
} }
SolidityState.prototype.init = function () { SolidityState.prototype.init = function () {
var self = this var self = this
this.parent.event.register('indexChanged', this, function (index) { this.parent.event.register('indexChanged', this, function (index) {
var warningDiv = this.view.querySelector('#warning')
warningDiv.innerHTML = ''
if (index < 0) { if (index < 0) {
self.basicPanel.update({info: 'invalid step index'}) warningDiv.innerHTML = 'invalid step index'
return return
} }
if (self.parent.currentStepIndex !== index) return if (self.parent.currentStepIndex !== index) return
if (!this.solidityProxy.loaded()) { if (!this.solidityProxy.loaded()) {
self.basicPanel.update({info: 'no source has been specified'}) warningDiv.innerHTML = 'no source has been specified'
return return
} }
......
'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}</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 {
ret.children = []
ret.self = item.value
ret.type = item.type
}
return ret
}
function fontColor (data) {
var color = '#124B46'
if (data.isArray || data.isStruct) {
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
}
...@@ -11,14 +11,16 @@ class TreeView { ...@@ -11,14 +11,16 @@ class TreeView {
this.beforeJsonNodeRendered = opts.beforeJsonNodeRendered || noop this.beforeJsonNodeRendered = opts.beforeJsonNodeRendered || noop
this.beforeJsonValueRendered = opts.beforeJsonValueRendered || noop this.beforeJsonValueRendered = opts.beforeJsonValueRendered || noop
this.extractData = opts.extractData || this.extractDataDefault this.extractData = opts.extractData || this.extractDataDefault
this.formatData = opts.formatData || this.formatDataDefault this.formatSelf = opts.formatSelf || this.formatSelfDefault
this.view = null this.view = null
this.cssLabel = ui.formatCss(opts.css || {}, style.label) this.cssLabel = ui.formatCss(opts.css || {}, style.label)
this.cssList = ui.formatCss(opts.css || {}, style.list) this.cssUl = ui.formatCss(opts.css || {}, style.cssUl)
this.cssLi = ui.formatCss(opts.css || {}, style.cssLi)
this.nodeIsExpanded = {}
} }
render (json) { render (json) {
var view = yo`<div>${this.renderProperties(json, true)}</div>` var view = this.renderProperties(json, false)
if (!this.view) { if (!this.view) {
this.view = view this.view = view
} }
...@@ -27,52 +29,58 @@ class TreeView { ...@@ -27,52 +29,58 @@ class TreeView {
update (json) { update (json) {
if (this.view) { if (this.view) {
yo.update(this.view, this.render(json), {onBeforeElUpdated: (fromEl, toEl) => { yo.update(this.view, this.render(json))
toEl.style.display = fromEl.style.display
toEl.className = fromEl.className
return true
}})
} }
} }
renderObject (item, key, expand) { renderObject (item, parent, key, expand, keyPath) {
var data = this.extractData(item, key) var data = this.extractData(item, parent, key)
var children = Object.keys(data.children).map((innerkey) => { var children = (data.children || []).map((child, index) => {
return this.renderObject(data.children[innerkey], innerkey, expand) return this.renderObject(child.value, data, child.key, expand, keyPath + ',' + child.key)
}) })
return this.formatData(key, data.self, children, expand) return this.formatData(key, data, children, expand, keyPath)
} }
renderProperties (json, expand) { renderProperties (json, expand) {
var children = Object.keys(json).map((innerkey) => { var children = Object.keys(json).map((innerkey) => {
return this.renderObject(json[innerkey], innerkey, expand) return this.renderObject(json[innerkey], json, innerkey, expand, innerkey)
}) })
return yo`<ul style=${this.cssList}>${children}</ul>` return yo`<ul style=${this.cssUl}>${children}</ul>`
} }
formatDataDefault (key, self, children, expand) { formatData (key, data, children, expand, keyPath) {
var label = yo`<span style=${this.cssLabel}><label style='width: 10px'></label><label>${key}: ${self}</label></span>` var label = yo`<span style=${this.cssLabel}><label style=${ui.formatCss(style.caret)}></label><span style=${ui.formatCss(style.data)}>${this.formatSelf(key, data)}</span></span>`
var renderedChildren = '' var renderedChildren = ''
if (children.length) { if (children.length) {
renderedChildren = yo`<ul style=${this.cssList}>${children}</ul>` renderedChildren = yo`<ul style=${this.cssUl}>${children}</ul>`
renderedChildren.style.display = expand ? 'block' : 'none' renderedChildren.style.display = this.nodeIsExpanded[keyPath] !== undefined ? (this.nodeIsExpanded[keyPath] ? 'block' : 'none') : (expand ? 'block' : 'none')
label.firstElementChild.className = expand ? 'fa fa-caret-down' : 'fa fa-caret-right' label.firstElementChild.className = renderedChildren.style.display === 'none' ? 'fa fa-caret-right' : 'fa fa-caret-down'
var self = this
label.onclick = function () { label.onclick = function () {
this.firstElementChild.className = this.firstElementChild.className === 'fa fa-caret-right' ? 'fa fa-caret-down' : 'fa fa-caret-right' this.firstElementChild.className = this.firstElementChild.className === 'fa fa-caret-right' ? 'fa fa-caret-down' : 'fa fa-caret-right'
var list = this.parentElement.querySelector('ul') var list = this.parentElement.querySelector('ul')
list.style.display = list.style.display === 'none' ? 'block' : 'none' list.style.display = list.style.display === 'none' ? 'block' : 'none'
self.nodeIsExpanded[keyPath] = list.style.display === 'block'
} }
} }
return yo`<li style=${this.cssList}>${label}${renderedChildren}</li>` return yo`<li style=${this.cssLi}>${label}${renderedChildren}</li>`
} }
extractDataDefault (item, key) { formatSelfDefault (key, data) {
return yo`<label>${key}: ${data.self}</label>`
}
extractDataDefault (item, parent, key) {
var ret = {} var ret = {}
if (item instanceof Array) { if (item instanceof Array) {
ret.children = item ret.children = item.map((item, index) => {
return {key: index, value: item}
})
ret.self = 'Array' ret.self = 'Array'
} else if (item instanceof Object) { } else if (item instanceof Object) {
ret.children = item ret.children = Object.keys(item).map((key) => {
return {key: key, value: item[key]}
})
ret.self = 'Object' ret.self = 'Object'
} else { } else {
ret.self = item ret.self = item
......
...@@ -27,7 +27,9 @@ module.exports = { ...@@ -27,7 +27,9 @@ module.exports = {
'width': '52%', 'width': '52%',
'overflow-y': 'scroll', 'overflow-y': 'scroll',
'max-height': '250px', 'max-height': '250px',
'margin': '0' 'margin': '0',
'margin-left': '10px',
'padding': '2px'
}, },
transactionInfo: { transactionInfo: {
'margin-top': '5px' 'margin-top': '5px'
......
...@@ -13,15 +13,18 @@ module.exports = { ...@@ -13,15 +13,18 @@ module.exports = {
}, },
content: { content: {
'color': '#111111', 'color': '#111111',
'width': '100%' 'width': '100%',
'min-height': '20px'
}, },
inner: { inner: {
'padding': '2px', 'padding': '2px',
'margin-left': '10px',
'word-break': 'break-all' 'word-break': 'break-all'
}, },
copyBtn: { copyBtn: {
'float': 'right', 'float': 'right',
'margin-top': '3px' 'margin-top': '3px'
},
caret: {
'margin-left': '5px'
} }
} }
'use strict' 'use strict'
module.exports = { module.exports = {
list: { cssUl: {
'list-style-type': 'none',
'-webkit-margin-before': '0px',
'-webkit-margin-after': '0px',
'-webkit-margin-start': '0px',
'-webkit-margin-end': '0px',
'-webkit-padding-start': '0px'
},
cssLi: {
'list-style-type': 'none', 'list-style-type': 'none',
'-webkit-margin-before': '0px', '-webkit-margin-before': '0px',
'-webkit-margin-after': '0px', '-webkit-margin-after': '0px',
...@@ -12,5 +20,12 @@ module.exports = { ...@@ -12,5 +20,12 @@ module.exports = {
label: { label: {
'vertical-align': 'top', 'vertical-align': 'top',
'font-family': 'arial,sans-serif' 'font-family': 'arial,sans-serif'
},
caret: {
'position': 'absolute',
'margin-top': '3px'
},
data: {
'margin-left': '10px'
} }
} }
...@@ -128,7 +128,7 @@ browser.fireEvent = function (el, key, times, callback) { ...@@ -128,7 +128,7 @@ browser.fireEvent = function (el, key, times, callback) {
} }
function assertPanel (id, browser, value) { function assertPanel (id, browser, value) {
var selector = '.dropdownpanel div.dropdowncontent div ul' var selector = '.dropdownpanel div.dropdowncontent ul'
browser.execute(function (id, selector) { browser.execute(function (id, selector) {
var el = document.getElementById(id.replace('#', '').replace('.', '')) var el = document.getElementById(id.replace('#', '').replace('.', ''))
var node = el.querySelector(selector) var node = el.querySelector(selector)
...@@ -153,7 +153,7 @@ function assertPanel (id, browser, value) { ...@@ -153,7 +153,7 @@ function assertPanel (id, browser, value) {
} }
function assertPanelValue (id, browser, index, value) { function assertPanelValue (id, browser, index, value) {
var selector = id + ' .dropdownpanel .dropdowncontent div ul' var selector = id + ' .dropdownpanel .dropdowncontent ul'
browser.execute(function (id, index) { browser.execute(function (id, index) {
var node = document.querySelector(id) var node = document.querySelector(id)
return node.children[index].innerText return node.children[index].innerText
......
...@@ -13,31 +13,31 @@ tape('solidity', function (t) { ...@@ -13,31 +13,31 @@ tape('solidity', function (t) {
var states = index.solidity.astHelper.extractStatesDefinitions(output.sources) var states = index.solidity.astHelper.extractStatesDefinitions(output.sources)
var stateDef = state.stateDefinitions var stateDef = state.stateDefinitions
var decodeInfo = index.solidity.decodeInfo.parseType(stateDef[0].attributes.type, states, 'contractUint') var decodeInfo = index.solidity.decodeInfo.parseType(stateDef[0].attributes.type, states, 'contractUint')
checkDecodeInfo(st, decodeInfo, 1, 1, 'uint') checkDecodeInfo(st, decodeInfo, 1, 1, 'uint8')
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractUint') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractUint')
checkDecodeInfo(st, decodeInfo, 1, 32, 'uint') checkDecodeInfo(st, decodeInfo, 1, 32, 'uint256')
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[3].attributes.type, states, 'contractUint') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[3].attributes.type, states, 'contractUint')
checkDecodeInfo(st, decodeInfo, 1, 32, 'uint') checkDecodeInfo(st, decodeInfo, 1, 32, 'uint256')
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[4].attributes.type, states, 'contractUint') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[4].attributes.type, states, 'contractUint')
checkDecodeInfo(st, decodeInfo, 1, 16, 'bytesX') checkDecodeInfo(st, decodeInfo, 1, 16, 'bytes16')
state = index.solidity.astHelper.extractStateDefinitions('contractStructAndArray', output.sources) state = index.solidity.astHelper.extractStateDefinitions('contractStructAndArray', output.sources)
stateDef = state.stateDefinitions stateDef = state.stateDefinitions
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[1].attributes.type, states, 'contractStructAndArray') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[1].attributes.type, states, 'contractStructAndArray')
checkDecodeInfo(st, decodeInfo, 2, 32, 'struct') checkDecodeInfo(st, decodeInfo, 2, 32, 'struct contractStructAndArray.structDef')
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractStructAndArray') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractStructAndArray')
checkDecodeInfo(st, decodeInfo, 6, 32, 'array') checkDecodeInfo(st, decodeInfo, 6, 32, 'struct contractStructAndArray.structDef[3]')
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[3].attributes.type, states, 'contractStructAndArray') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[3].attributes.type, states, 'contractStructAndArray')
checkDecodeInfo(st, decodeInfo, 2, 32, 'array') checkDecodeInfo(st, decodeInfo, 2, 32, 'bytes12[4]')
state = index.solidity.astHelper.extractStateDefinitions('contractArray', output.sources) state = index.solidity.astHelper.extractStateDefinitions('contractArray', output.sources)
stateDef = state.stateDefinitions stateDef = state.stateDefinitions
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[0].attributes.type, states, 'contractArray') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[0].attributes.type, states, 'contractArray')
checkDecodeInfo(st, decodeInfo, 1, 32, 'array') checkDecodeInfo(st, decodeInfo, 1, 32, 'uint32[5]')
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[1].attributes.type, states, 'contractArray') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[1].attributes.type, states, 'contractArray')
checkDecodeInfo(st, decodeInfo, 1, 32, 'array') checkDecodeInfo(st, decodeInfo, 1, 32, 'int8[]')
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractArray') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractArray')
checkDecodeInfo(st, decodeInfo, 4, 32, 'array') checkDecodeInfo(st, decodeInfo, 4, 32, 'int16[][3][][4]')
state = index.solidity.astHelper.extractStateDefinitions('contractEnum', output.sources) state = index.solidity.astHelper.extractStateDefinitions('contractEnum', output.sources)
stateDef = state.stateDefinitions stateDef = state.stateDefinitions
...@@ -47,17 +47,17 @@ tape('solidity', function (t) { ...@@ -47,17 +47,17 @@ tape('solidity', function (t) {
state = index.solidity.astHelper.extractStateDefinitions('contractSmallVariable', output.sources) state = index.solidity.astHelper.extractStateDefinitions('contractSmallVariable', output.sources)
stateDef = state.stateDefinitions stateDef = state.stateDefinitions
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[0].attributes.type, states, 'contractSmallVariable') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[0].attributes.type, states, 'contractSmallVariable')
checkDecodeInfo(st, decodeInfo, 1, 1, 'int') checkDecodeInfo(st, decodeInfo, 1, 1, 'int8')
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[1].attributes.type, states, 'contractSmallVariable') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[1].attributes.type, states, 'contractSmallVariable')
checkDecodeInfo(st, decodeInfo, 1, 1, 'uint') checkDecodeInfo(st, decodeInfo, 1, 1, 'uint8')
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractSmallVariable') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractSmallVariable')
checkDecodeInfo(st, decodeInfo, 1, 2, 'uint') checkDecodeInfo(st, decodeInfo, 1, 2, 'uint16')
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[3].attributes.type, states, 'contractSmallVariable') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[3].attributes.type, states, 'contractSmallVariable')
checkDecodeInfo(st, decodeInfo, 1, 4, 'int') checkDecodeInfo(st, decodeInfo, 1, 4, 'int32')
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[4].attributes.type, states, 'contractSmallVariable') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[4].attributes.type, states, 'contractSmallVariable')
checkDecodeInfo(st, decodeInfo, 1, 32, 'uint') checkDecodeInfo(st, decodeInfo, 1, 32, 'uint256')
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[5].attributes.type, states, 'contractSmallVariable') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[5].attributes.type, states, 'contractSmallVariable')
checkDecodeInfo(st, decodeInfo, 1, 2, 'int') checkDecodeInfo(st, decodeInfo, 1, 2, 'int16')
output = compiler.compile(simplecontracts, 0) output = compiler.compile(simplecontracts, 0)
...@@ -65,19 +65,19 @@ tape('solidity', function (t) { ...@@ -65,19 +65,19 @@ tape('solidity', function (t) {
states = index.solidity.astHelper.extractStatesDefinitions(output.sources) states = index.solidity.astHelper.extractStatesDefinitions(output.sources)
stateDef = state.stateDefinitions stateDef = state.stateDefinitions
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[2].attributes.type, states, 'simpleContract') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[2].attributes.type, states, 'simpleContract')
checkDecodeInfo(st, decodeInfo, 2, 32, 'struct') checkDecodeInfo(st, decodeInfo, 2, 32, 'struct simpleContract.structDef')
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[3].attributes.type, states, 'simpleContract') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[3].attributes.type, states, 'simpleContract')
checkDecodeInfo(st, decodeInfo, 6, 32, 'array') checkDecodeInfo(st, decodeInfo, 6, 32, 'struct simpleContract.structDef[3]')
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[4].attributes.type, states, 'simpleContract') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[4].attributes.type, states, 'simpleContract')
checkDecodeInfo(st, decodeInfo, 1, 1, 'enum') checkDecodeInfo(st, decodeInfo, 1, 1, 'enum')
state = index.solidity.astHelper.extractStateDefinitions('test2', output.sources) state = index.solidity.astHelper.extractStateDefinitions('test2', output.sources)
stateDef = state.stateDefinitions stateDef = state.stateDefinitions
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[0].attributes.type, states, 'test1') decodeInfo = index.solidity.decodeInfo.parseType(stateDef[0].attributes.type, states, 'test1')
checkDecodeInfo(st, decodeInfo, 0, 32, 'struct') checkDecodeInfo(st, decodeInfo, 0, 32, 'struct test1.str')
state = index.solidity.stateDecoder.extractStateVariables('test2', output.sources) state = index.solidity.stateDecoder.extractStateVariables('test2', output.sources)
checkDecodeInfo(st, decodeInfo, 0, 32, 'struct') checkDecodeInfo(st, decodeInfo, 0, 32, 'struct test1.str')
st.end() st.end()
}) })
......
...@@ -37,52 +37,52 @@ module.exports = function (st, vm, privateKey, contractBytecode, compilationResu ...@@ -37,52 +37,52 @@ module.exports = function (st, vm, privateKey, contractBytecode, compilationResu
st.equals(scopeStarts[135], '2') st.equals(scopeStarts[135], '2')
st.equals(scopeStarts[154], '3') st.equals(scopeStarts[154], '3')
st.equals(scopeStarts[169], '3.1') st.equals(scopeStarts[169], '3.1')
st.equals(scopes[''].locals['ui8'].type.typeName, 'uint') st.equals(scopes[''].locals['ui8'].type.typeName, 'uint8')
st.equals(scopes[''].locals['ui16'].type.typeName, 'uint') st.equals(scopes[''].locals['ui16'].type.typeName, 'uint16')
st.equals(scopes[''].locals['ui32'].type.typeName, 'uint') st.equals(scopes[''].locals['ui32'].type.typeName, 'uint32')
st.equals(scopes[''].locals['ui64'].type.typeName, 'uint') st.equals(scopes[''].locals['ui64'].type.typeName, 'uint64')
st.equals(scopes[''].locals['ui128'].type.typeName, 'uint') st.equals(scopes[''].locals['ui128'].type.typeName, 'uint128')
st.equals(scopes[''].locals['ui256'].type.typeName, 'uint') st.equals(scopes[''].locals['ui256'].type.typeName, 'uint256')
st.equals(scopes[''].locals['ui'].type.typeName, 'uint') st.equals(scopes[''].locals['ui'].type.typeName, 'uint256')
st.equals(scopes[''].locals['i8'].type.typeName, 'int') st.equals(scopes[''].locals['i8'].type.typeName, 'int8')
st.equals(scopes[''].locals['i16'].type.typeName, 'int') st.equals(scopes[''].locals['i16'].type.typeName, 'int16')
st.equals(scopes[''].locals['i32'].type.typeName, 'int') st.equals(scopes[''].locals['i32'].type.typeName, 'int32')
st.equals(scopes[''].locals['i64'].type.typeName, 'int') st.equals(scopes[''].locals['i64'].type.typeName, 'int64')
st.equals(scopes[''].locals['i128'].type.typeName, 'int') st.equals(scopes[''].locals['i128'].type.typeName, 'int128')
st.equals(scopes[''].locals['i256'].type.typeName, 'int') st.equals(scopes[''].locals['i256'].type.typeName, 'int256')
st.equals(scopes[''].locals['i'].type.typeName, 'int') st.equals(scopes[''].locals['i'].type.typeName, 'int256')
st.equals(scopes[''].locals['ishrink'].type.typeName, 'int') st.equals(scopes[''].locals['ishrink'].type.typeName, 'int32')
st.equals(scopes['1'].locals['ui8'].type.typeName, 'uint') st.equals(scopes['1'].locals['ui8'].type.typeName, 'uint8')
st.equals(scopes['1.1'].locals['ui81'].type.typeName, 'uint') st.equals(scopes['1.1'].locals['ui81'].type.typeName, 'uint8')
st.equals(scopes['2'].locals['ui81'].type.typeName, 'uint') st.equals(scopes['2'].locals['ui81'].type.typeName, 'uint8')
st.equals(scopes['3'].locals['ui8'].type.typeName, 'uint') st.equals(scopes['3'].locals['ui8'].type.typeName, 'uint8')
st.equals(scopes['3.1'].locals['ui81'].type.typeName, 'uint') st.equals(scopes['3.1'].locals['ui81'].type.typeName, 'uint8')
} catch (e) { } catch (e) {
st.fail(e.message) st.fail(e.message)
} }
helper.decodeLocals(st, 125, traceManager, callTree, function (locals) { helper.decodeLocals(st, 125, traceManager, callTree, function (locals) {
st.equals(Object.keys(locals).length, 16) st.equals(Object.keys(locals).length, 16)
st.equals(locals['ui8'], '130') st.equals(locals['ui8'].value, '130')
st.equals(locals['ui16'], '456') st.equals(locals['ui16'].value, '456')
st.equals(locals['ui32'], '4356') st.equals(locals['ui32'].value, '4356')
st.equals(locals['ui64'], '3543543543') st.equals(locals['ui64'].value, '3543543543')
st.equals(locals['ui128'], '234567') st.equals(locals['ui128'].value, '234567')
st.equals(locals['ui256'], '115792089237316195423570985008687907853269984665640564039457584007880697216513') st.equals(locals['ui256'].value, '115792089237316195423570985008687907853269984665640564039457584007880697216513')
st.equals(locals['ui'], '123545666') st.equals(locals['ui'].value, '123545666')
st.equals(locals['i8'], '-45') st.equals(locals['i8'].value, '-45')
st.equals(locals['i16'], '-1234') st.equals(locals['i16'].value, '-1234')
st.equals(locals['i32'], '3455') st.equals(locals['i32'].value, '3455')
st.equals(locals['i64'], '-35566') st.equals(locals['i64'].value, '-35566')
st.equals(locals['i128'], '-444444') st.equals(locals['i128'].value, '-444444')
st.equals(locals['i256'], '3434343') st.equals(locals['i256'].value, '3434343')
st.equals(locals['i'], '-32432423423') st.equals(locals['i'].value, '-32432423423')
st.equals(locals['ishrink'], '2') st.equals(locals['ishrink'].value, '2')
}) })
helper.decodeLocals(st, 177, traceManager, callTree, function (locals) { helper.decodeLocals(st, 177, traceManager, callTree, function (locals) {
try { try {
st.equals(locals['ui8'], '123') st.equals(locals['ui8'].value, '123')
st.equals(Object.keys(locals).length, 1) st.equals(Object.keys(locals).length, 1)
} catch (e) { } catch (e) {
st.fail(e.message) st.fail(e.message)
......
...@@ -32,22 +32,22 @@ module.exports = function (st, vm, privateKey, contractBytecode, compilationResu ...@@ -32,22 +32,22 @@ module.exports = function (st, vm, privateKey, contractBytecode, compilationResu
callTree.event.register('callTreeReady', (scopes, scopeStarts) => { callTree.event.register('callTreeReady', (scopes, scopeStarts) => {
helper.decodeLocals(st, 70, traceManager, callTree, function (locals) { helper.decodeLocals(st, 70, traceManager, callTree, function (locals) {
try { try {
st.equals(locals['boolFalse'], false) st.equals(locals['boolFalse'].value, false)
st.equals(locals['boolTrue'], true) st.equals(locals['boolTrue'].value, true)
st.equals(locals['testEnum'], 'three') st.equals(locals['testEnum'].value, 'three')
st.equals(locals['sender'], '0x4B0897B0513FDC7C541B6D9D7E929C4E5364D2DB') st.equals(locals['sender'].value, '0x4B0897B0513FDC7C541B6D9D7E929C4E5364D2DB')
st.equals(locals['_bytes1'], '0x99') st.equals(locals['_bytes1'].value, '0x99')
st.equals(locals['__bytes1'], '0x99') st.equals(locals['__bytes1'].value, '0x99')
st.equals(locals['__bytes2'], '0x99AB') st.equals(locals['__bytes2'].value, '0x99AB')
st.equals(locals['__bytes4'], '0x99FA0000') st.equals(locals['__bytes4'].value, '0x99FA0000')
st.equals(locals['__bytes6'], '0x990000000000') st.equals(locals['__bytes6'].value, '0x990000000000')
st.equals(locals['__bytes7'], '0x99356700000000') st.equals(locals['__bytes7'].value, '0x99356700000000')
st.equals(locals['__bytes8'], '0x99ABD41700000000') st.equals(locals['__bytes8'].value, '0x99ABD41700000000')
st.equals(locals['__bytes9'], '0x99156744AF00000000') st.equals(locals['__bytes9'].value, '0x99156744AF00000000')
st.equals(locals['__bytes13'], '0x99123423425300000000000000') st.equals(locals['__bytes13'].value, '0x99123423425300000000000000')
st.equals(locals['__bytes16'], '0x99AFAD23432400000000000000000000') st.equals(locals['__bytes16'].value, '0x99AFAD23432400000000000000000000')
st.equals(locals['__bytes24'], '0x99AFAD234324000000000000000000000000000000000000') st.equals(locals['__bytes24'].value, '0x99AFAD234324000000000000000000000000000000000000')
st.equals(locals['__bytes32'], '0x9999ABD41799ABD4170000000000000000000000000000000000000000000000') st.equals(locals['__bytes32'].value, '0x9999ABD41799ABD4170000000000000000000000000000000000000000000000')
st.equals(Object.keys(locals).length, 16) st.equals(Object.keys(locals).length, 16)
} catch (e) { } catch (e) {
st.fail(e.message) st.fail(e.message)
...@@ -56,22 +56,22 @@ module.exports = function (st, vm, privateKey, contractBytecode, compilationResu ...@@ -56,22 +56,22 @@ module.exports = function (st, vm, privateKey, contractBytecode, compilationResu
helper.decodeLocals(st, 7, traceManager, callTree, function (locals) { helper.decodeLocals(st, 7, traceManager, callTree, function (locals) {
try { try {
st.equals(locals['boolFalse'], false) st.equals(locals['boolFalse'].value, false)
st.equals(locals['boolTrue'], false) st.equals(locals['boolTrue'].value, false)
st.equals(locals['testEnum'], 'one') st.equals(locals['testEnum'].value, 'one')
st.equals(locals['sender'], '0x0000000000000000000000000000000000000000') st.equals(locals['sender'].value, '0x0000000000000000000000000000000000000000')
st.equals(locals['_bytes1'], '0x') st.equals(locals['_bytes1'].value, '0x')
st.equals(locals['__bytes1'], '0x') st.equals(locals['__bytes1'].value, '0x')
st.equals(locals['__bytes2'], '0x') st.equals(locals['__bytes2'].value, '0x')
st.equals(locals['__bytes4'], '0x') st.equals(locals['__bytes4'].value, '0x')
st.equals(locals['__bytes6'], '0x') st.equals(locals['__bytes6'].value, '0x')
st.equals(locals['__bytes7'], '0x') st.equals(locals['__bytes7'].value, '0x')
st.equals(locals['__bytes8'], '0x') st.equals(locals['__bytes8'].value, '0x')
st.equals(locals['__bytes9'], '0x') st.equals(locals['__bytes9'].value, '0x')
st.equals(locals['__bytes13'], '0x') st.equals(locals['__bytes13'].value, '0x')
st.equals(locals['__bytes16'], '0x') st.equals(locals['__bytes16'].value, '0x')
st.equals(locals['__bytes24'], '0x') st.equals(locals['__bytes24'].value, '0x')
st.equals(locals['__bytes32'], '0x') st.equals(locals['__bytes32'].value, '0x')
st.equals(Object.keys(locals).length, 16) st.equals(Object.keys(locals).length, 16)
} catch (e) { } catch (e) {
st.fail(e.message) st.fail(e.message)
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment