diff --git a/libs/remix-debug/src/Ethdebugger.ts b/libs/remix-debug/src/Ethdebugger.ts index 85d6060ae9..96eb8acb65 100644 --- a/libs/remix-debug/src/Ethdebugger.ts +++ b/libs/remix-debug/src/Ethdebugger.ts @@ -23,141 +23,152 @@ const {SolidityProxy, stateDecoder, localDecoder, InternalCallTree} = require('. * * @param {Map} opts - { function compilationResult } // */ -function Ethdebugger (opts) { - this.compilationResult = opts.compilationResult || function (contractAddress) { return null } - this.web3 = opts.web3 - this.opts = opts - - this.event = new EventManager() - - this.tx - - this.traceManager = new TraceManager({web3: this.web3}) - this.codeManager = new CodeManager(this.traceManager) - this.solidityProxy = new SolidityProxy({getCurrentCalledAddressAt: this.traceManager.getCurrentCalledAddressAt.bind(this.traceManager), getCode: this.codeManager.getCode.bind(this.codeManager)}) - this.storageResolver = null - - const includeLocalVariables = true - this.callTree = new InternalCallTree(this.event, - this.traceManager, - this.solidityProxy, - this.codeManager, - { ...opts, includeLocalVariables}) -} +export class Ethdebugger { + + compilationResult + web3 + opts + event + tx + traceManager + codeManager + solidityProxy + storageResolver + callTree + breakpointManager + statusMessage + + constructor (opts) { + this.compilationResult = opts.compilationResult || function (contractAddress) { return null } + this.web3 = opts.web3 + this.opts = opts + + this.event = new EventManager() + this.traceManager = new TraceManager({web3: this.web3}) + this.codeManager = new CodeManager(this.traceManager) + this.solidityProxy = new SolidityProxy({getCurrentCalledAddressAt: this.traceManager.getCurrentCalledAddressAt.bind(this.traceManager), getCode: this.codeManager.getCode.bind(this.codeManager)}) + this.storageResolver = null + + const includeLocalVariables = true + this.callTree = new InternalCallTree(this.event, + this.traceManager, + this.solidityProxy, + this.codeManager, + { ...opts, includeLocalVariables}) + } -Ethdebugger.prototype.setManagers = function () { - this.traceManager = new TraceManager({web3: this.web3}) - this.codeManager = new CodeManager(this.traceManager) - this.solidityProxy = new SolidityProxy({getCurrentCalledAddressAt: this.traceManager.getCurrentCalledAddressAt.bind(this.traceManager), getCode: this.codeManager.getCode.bind(this.codeManager)}) - this.storageResolver = null - const includeLocalVariables = true - - this.callTree = new InternalCallTree(this.event, - this.traceManager, - this.solidityProxy, - this.codeManager, - { ...this.opts, includeLocalVariables}) - this.event.trigger('managersChanged') -} + setManagers () { + this.traceManager = new TraceManager({web3: this.web3}) + this.codeManager = new CodeManager(this.traceManager) + this.solidityProxy = new SolidityProxy({getCurrentCalledAddressAt: this.traceManager.getCurrentCalledAddressAt.bind(this.traceManager), getCode: this.codeManager.getCode.bind(this.codeManager)}) + this.storageResolver = null + const includeLocalVariables = true + + this.callTree = new InternalCallTree(this.event, + this.traceManager, + this.solidityProxy, + this.codeManager, + { ...this.opts, includeLocalVariables}) + this.event.trigger('managersChanged') + } -Ethdebugger.prototype.resolveStep = function (index) { - this.codeManager.resolveStep(index, this.tx) -} + resolveStep (index) { + this.codeManager.resolveStep(index, this.tx) + } -Ethdebugger.prototype.setCompilationResult = function (compilationResult) { - this.solidityProxy.reset((compilationResult && compilationResult.data) || {}) -} + setCompilationResult (compilationResult) { + this.solidityProxy.reset((compilationResult && compilationResult.data) || {}) + } -Ethdebugger.prototype.sourceLocationFromVMTraceIndex = async function (address, stepIndex) { - return this.callTree.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, stepIndex, this.solidityProxy.contracts) -} + async sourceLocationFromVMTraceIndex (address, stepIndex) { + return this.callTree.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, stepIndex, this.solidityProxy.contracts) + } -Ethdebugger.prototype.getValidSourceLocationFromVMTraceIndex = async function (address, stepIndex) { - return this.callTree.sourceLocationTracker.getValidSourceLocationFromVMTraceIndex(address, stepIndex, this.solidityProxy.contracts) -} + async getValidSourceLocationFromVMTraceIndex (address, stepIndex) { + return this.callTree.sourceLocationTracker.getValidSourceLocationFromVMTraceIndex(address, stepIndex, this.solidityProxy.contracts) + } -Ethdebugger.prototype.sourceLocationFromInstructionIndex = async function (address, instIndex, callback) { - return this.callTree.sourceLocationTracker.getSourceLocationFromInstructionIndex(address, instIndex, this.solidityProxy.contracts) -} + async sourceLocationFromInstructionIndex (address, instIndex, callback) { + return this.callTree.sourceLocationTracker.getSourceLocationFromInstructionIndex(address, instIndex, this.solidityProxy.contracts) + } -/* breakpoint */ -Ethdebugger.prototype.setBreakpointManager = function (breakpointManager) { - this.breakpointManager = breakpointManager -} + /* breakpoint */ + setBreakpointManager (breakpointManager) { + this.breakpointManager = breakpointManager + } -/* decode locals */ -Ethdebugger.prototype.extractLocalsAt = function (step) { - return this.callTree.findScope(step) -} + /* decode locals */ + extractLocalsAt (step) { + return this.callTree.findScope(step) + } -Ethdebugger.prototype.decodeLocalsAt = async function (step, sourceLocation, callback) { - try { - const stack = this.traceManager.getStackAt(step) - const memory = this.traceManager.getMemoryAt(step) - const address = this.traceManager.getCurrentCalledAddressAt(step) + async decodeLocalsAt (step, sourceLocation, callback) { try { - const storageViewer = new StorageViewer({ stepIndex: step, tx: this.tx, address: address }, this.storageResolver, this.traceManager) - const locals = await localDecoder.solidityLocals(step, this.callTree, stack, memory, storageViewer, sourceLocation) - if (locals.error) { - return callback(locals.error) + const stack = this.traceManager.getStackAt(step) + const memory = this.traceManager.getMemoryAt(step) + const address = this.traceManager.getCurrentCalledAddressAt(step) + try { + const storageViewer = new StorageViewer({ stepIndex: step, tx: this.tx, address: address }, this.storageResolver, this.traceManager) + const locals = await localDecoder.solidityLocals(step, this.callTree, stack, memory, storageViewer, sourceLocation) + if (locals.error) { + return callback(locals.error) + } + return callback(null, locals) + } catch (e) { + callback(e.message) } - return callback(null, locals) - } catch (e) { - callback(e.message) + } catch (error) { + callback(error) } - } catch (error) { - callback(error) } -} - -/* decode state */ -Ethdebugger.prototype.extractStateAt = async function (step) { - return this.solidityProxy.extractStateVariablesAt(step) -} -Ethdebugger.prototype.decodeStateAt = async function (step, stateVars, callback) { - try { - const address = this.traceManager.getCurrentCalledAddressAt(step) - const storageViewer = new StorageViewer({stepIndex: step, tx: this.tx, address: address}, this.storageResolver, this.traceManager) - const result = await stateDecoder.decodeState(stateVars, storageViewer) - return result - } catch (error) { - callback(error) + /* decode state */ + async extractStateAt (step) { + return this.solidityProxy.extractStateVariablesAt(step) } -} -Ethdebugger.prototype.storageViewAt = function (step, address) { - return new StorageViewer({stepIndex: step, tx: this.tx, address: address}, this.storageResolver, this.traceManager) -} + async decodeStateAt (step, stateVars, callback) { + try { + const address = this.traceManager.getCurrentCalledAddressAt(step) + const storageViewer = new StorageViewer({stepIndex: step, tx: this.tx, address: address}, this.storageResolver, this.traceManager) + const result = await stateDecoder.decodeState(stateVars, storageViewer) + return result + } catch (error) { + callback(error) + } + } -Ethdebugger.prototype.updateWeb3 = function (web3) { - this.web3 = web3 - this.setManagers() -} + storageViewAt (step, address) { + return new StorageViewer({stepIndex: step, tx: this.tx, address: address}, this.storageResolver, this.traceManager) + } -Ethdebugger.prototype.unLoad = function () { - this.traceManager.init() - this.codeManager.clear() - this.event.trigger('traceUnloaded') -} + updateWeb3 (web3) { + this.web3 = web3 + this.setManagers() + } -Ethdebugger.prototype.debug = function (tx) { - if (this.traceManager.isLoading) { - return + unLoad () { + this.traceManager.init() + this.codeManager.clear() + this.event.trigger('traceUnloaded') } - tx.to = tx.to || traceHelper.contractCreationToken('0') - this.tx = tx - this.traceManager.resolveTrace(tx).then(async (result) => { - this.setCompilationResult(await this.compilationResult(tx.to)) - this.event.trigger('newTraceLoaded', [this.traceManager.trace]) - if (this.breakpointManager && this.breakpointManager.hasBreakpoint()) { - this.breakpointManager.jumpNextBreakpoint(false) + debug (tx) { + if (this.traceManager.isLoading) { + return } - this.storageResolver = new StorageResolver({web3: this.traceManager.web3}) - }).catch((error) => { - this.statusMessage = error ? error.message : 'Trace not loaded' - }) + tx.to = tx.to || traceHelper.contractCreationToken('0') + this.tx = tx + + this.traceManager.resolveTrace(tx).then(async (result) => { + this.setCompilationResult(await this.compilationResult(tx.to)) + this.event.trigger('newTraceLoaded', [this.traceManager.trace]) + if (this.breakpointManager && this.breakpointManager.hasBreakpoint()) { + this.breakpointManager.jumpNextBreakpoint(false) + } + this.storageResolver = new StorageResolver({web3: this.traceManager.web3}) + }).catch((error) => { + this.statusMessage = error ? error.message : 'Trace not loaded' + }) + } } - -module.exports = Ethdebugger diff --git a/libs/remix-debug/src/eventManager.ts b/libs/remix-debug/src/eventManager.ts index 8d1ffb9e37..37f01ef0ed 100644 --- a/libs/remix-debug/src/eventManager.ts +++ b/libs/remix-debug/src/eventManager.ts @@ -1,70 +1,74 @@ 'use strict' -function eventManager () { - this.registered = {} - this.anonymous = {} -} +export class eventManager { -/* - * Unregister a listener. - * Note that if obj is a function. the unregistration will be applied to the dummy obj {}. - * - * @param {String} eventName - the event name - * @param {Object or Func} obj - object that will listen on this event - * @param {Func} func - function of the listeners that will be executed -*/ -eventManager.prototype.unregister = function (eventName, obj, func) { - if (!this.registered[eventName]) { - return - } - if (obj instanceof Function) { - func = obj - obj = this.anonymous + registered + anonymous + + constructor() { + this.registered = {} + this.anonymous = {} } - for (let reg in this.registered[eventName]) { - if (this.registered[eventName][reg].obj === obj && this.registered[eventName][reg].func === func) { - this.registered[eventName].splice(reg, 1) + + /* + * Unregister a listener. + * Note that if obj is a function. the unregistration will be applied to the dummy obj {}. + * + * @param {String} eventName - the event name + * @param {Object or Func} obj - object that will listen on this event + * @param {Func} func - function of the listeners that will be executed + */ + unregister (eventName, obj, func) { + if (!this.registered[eventName]) { + return + } + if (obj instanceof Function) { + func = obj + obj = this.anonymous + } + for (let reg in this.registered[eventName]) { + if (this.registered[eventName][reg].obj === obj && this.registered[eventName][reg].func === func) { + this.registered[eventName].splice(reg, 1) + } } } -} -/* - * Register a new listener. - * Note that if obj is a function, the function registration will be associated with the dummy object {} - * - * @param {String} eventName - the event name - * @param {Object or Func} obj - object that will listen on this event - * @param {Func} func - function of the listeners that will be executed -*/ -eventManager.prototype.register = function (eventName, obj, func) { - if (!this.registered[eventName]) { - this.registered[eventName] = [] - } - if (obj instanceof Function) { - func = obj - obj = this.anonymous + /* + * Register a new listener. + * Note that if obj is a function, the function registration will be associated with the dummy object {} + * + * @param {String} eventName - the event name + * @param {Object or Func} obj - object that will listen on this event + * @param {Func} func - function of the listeners that will be executed + */ + register (eventName, obj, func) { + if (!this.registered[eventName]) { + this.registered[eventName] = [] + } + if (obj instanceof Function) { + func = obj + obj = this.anonymous + } + this.registered[eventName].push({ + obj: obj, + func: func + }) } - this.registered[eventName].push({ - obj: obj, - func: func - }) -} -/* - * trigger event. - * Every listener have their associated function executed - * - * @param {String} eventName - the event name - * @param {Array}j - argument that will be passed to the executed function. -*/ -eventManager.prototype.trigger = function (eventName, args) { - if (!this.registered[eventName]) { - return - } - for (let listener in this.registered[eventName]) { - const l = this.registered[eventName][listener] - l.func.apply(l.obj === this.anonymous ? {} : l.obj, args) + /* + * trigger event. + * Every listener have their associated function executed + * + * @param {String} eventName - the event name + * @param {Array}j - argument that will be passed to the executed function. + */ + trigger (eventName, args) { + if (!this.registered[eventName]) { + return + } + for (let listener in this.registered[eventName]) { + const l = this.registered[eventName][listener] + l.func.apply(l.obj === this.anonymous ? {} : l.obj, args) + } } } - -module.exports = eventManager \ No newline at end of file diff --git a/libs/remix-debug/src/index.ts b/libs/remix-debug/src/index.ts index ee023260a6..cda79944be 100644 --- a/libs/remix-debug/src/index.ts +++ b/libs/remix-debug/src/index.ts @@ -23,23 +23,23 @@ const traceHelper = require('./src/trace/traceHelper') }) this.debugger.setBreakpointManager(breakPointManager) */ -module.exports = { +export = { init, traceHelper, SourceMappingDecoder, - EthDebugger: EthDebugger, - TransactionDebugger: TransactionDebugger, + EthDebugger, + TransactionDebugger, /** * constructor * * @param {Object} _debugger - type of EthDebugger * @return {Function} _locationToRowConverter - function implemented by editor which return a column/line position for a char source location */ - BreakpointManager: BreakpointManager, - SolidityDecoder: SolidityDecoder, + BreakpointManager, + SolidityDecoder, storage: { StorageViewer: StorageViewer, StorageResolver: StorageResolver }, - CmdLine: CmdLine + CmdLine } diff --git a/libs/remix-debug/src/init.ts b/libs/remix-debug/src/init.ts index bfee5f10f0..ac1c330377 100644 --- a/libs/remix-debug/src/init.ts +++ b/libs/remix-debug/src/init.ts @@ -1,7 +1,7 @@ 'use strict' const Web3 = require('web3') -module.exports = { +export = { loadWeb3: function (url) { if (!url) url = 'http://localhost:8545' const web3 = new Web3() @@ -19,6 +19,13 @@ module.exports = { }, web3DebugNode: function (network) { + const web3DebugNodes = { + 'Main': 'https://rpc.archivenode.io/e50zmkroshle2e2e50zm0044i7ao04ym', + 'Rinkeby': 'https://remix-rinkeby.ethdevops.io', + 'Ropsten': 'https://remix-ropsten.ethdevops.io', + 'Goerli': 'https://remix-goerli.ethdevops.io', + 'Kovan': 'https://remix-kovan.ethdevops.io' + } if (web3DebugNodes[network]) { return this.loadWeb3(web3DebugNodes[network]) } @@ -66,11 +73,3 @@ module.exports = { } } } - -const web3DebugNodes = { - 'Main': 'https://rpc.archivenode.io/e50zmkroshle2e2e50zm0044i7ao04ym', - 'Rinkeby': 'https://remix-rinkeby.ethdevops.io', - 'Ropsten': 'https://remix-ropsten.ethdevops.io', - 'Goerli': 'https://remix-goerli.ethdevops.io', - 'Kovan': 'https://remix-kovan.ethdevops.io' -}