commit
cb05660b23
@ -1,39 +1,134 @@ |
|||||||
var remix = require('ethereum-remix'); |
var remix = require('ethereum-remix'); |
||||||
|
var utils = require('./utils'); |
||||||
|
var ace = require('brace'); |
||||||
|
var Range = ace.acequire('ace/range').Range; |
||||||
|
|
||||||
function Debugger (id, executionContextEvent) { |
/** |
||||||
|
* Manage remix and source highlighting |
||||||
|
*/ |
||||||
|
function Debugger (id, editor, compiler, executionContextEvent, switchToFile) { |
||||||
this.el = document.querySelector(id); |
this.el = document.querySelector(id); |
||||||
this.debugger = new remix.ui.Debugger(); |
this.debugger = new remix.ui.Debugger(); |
||||||
|
this.sourceMappingDecoder = new remix.util.SourceMappingDecoder(); |
||||||
this.el.appendChild(this.debugger.render()); |
this.el.appendChild(this.debugger.render()); |
||||||
|
this.editor = editor; |
||||||
|
this.switchToFile = switchToFile; |
||||||
|
this.compiler = compiler; |
||||||
|
this.cache = new Cache(); |
||||||
|
|
||||||
var self = this; |
var self = this; |
||||||
executionContextEvent.register('contextChanged', this, function (context) { |
executionContextEvent.register('contextChanged', this, function (context) { |
||||||
context = context === 'vm' ? 'VM' : context; |
|
||||||
context = context === 'injected' ? 'EXTERNAL' : context; |
|
||||||
context = context === 'web3' ? 'INTERNAL' : context; |
|
||||||
self.switchProvider(context); |
self.switchProvider(context); |
||||||
}); |
}); |
||||||
|
|
||||||
|
this.lastCompilationResult = null; |
||||||
|
this.debugger.register('newTraceLoaded', this, function () { |
||||||
|
self.cache.clear(); |
||||||
|
self.lastCompilationResult = self.compiler.lastCompilationResult; |
||||||
|
}); |
||||||
|
|
||||||
|
this.debugger.register('traceUnloaded', this, function () { |
||||||
|
self.removeCurrentMarker(); |
||||||
|
self.cache.clear(); |
||||||
|
}); |
||||||
|
|
||||||
|
this.editor.onChangeSetup(function () { |
||||||
|
if (arguments.length > 0) { // if arguments.length === 0 this is a session change, we don't want to stop debugging in that case
|
||||||
|
self.debugger.unLoad(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
// register selected code item, highlight the corresponding source location
|
||||||
|
this.debugger.codeManager.register('changed', this, function (code, address, index) { |
||||||
|
if (self.lastCompilationResult) { |
||||||
|
this.debugger.sourceLocationTracker.getSourceLocation(address, index, self.lastCompilationResult.data.contracts, function (error, rawLocation) { |
||||||
|
if (!error) { |
||||||
|
if (!self.cache.lineBreakPositionsByContent[address]) { |
||||||
|
self.cache.lineBreakPositionsByContent[address] = self.sourceMappingDecoder.getLinebreakPositions(self.editor.getFile(self.lastCompilationResult.data.sourceList[rawLocation.file])); |
||||||
|
} |
||||||
|
var lineColumnPos = self.sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, self.cache.lineBreakPositionsByContent[address]); |
||||||
|
self.highlight(lineColumnPos, rawLocation); |
||||||
|
} else { |
||||||
|
self.removeCurrentMarker(); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
}); |
||||||
} |
} |
||||||
|
|
||||||
Debugger.prototype.debug = function (receipt) { |
/** |
||||||
if (this.onDebugRequested) this.onDebugRequested(); |
* Start debugging using Remix |
||||||
|
* |
||||||
|
* @param {String} txHash - hash of the transaction |
||||||
|
*/ |
||||||
|
Debugger.prototype.debug = function (txHash) { |
||||||
var self = this; |
var self = this; |
||||||
this.debugger.web3().eth.getTransaction(receipt.transactionHash, function (error, tx) { |
this.debugger.web3().eth.getTransaction(txHash, function (error, tx) { |
||||||
if (!error) { |
if (!error) { |
||||||
self.debugger.debug(tx); |
self.debugger.debug(tx); |
||||||
} |
} |
||||||
}); |
}); |
||||||
}; |
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* highlight the given @arg lineColumnPos |
||||||
|
* |
||||||
|
* @param {Object} lineColumnPos - position of the source code to hightlight {start: {line, column}, end: {line, column}} |
||||||
|
* @param {Object} rawLocation - raw position of the source code to hightlight {start, length, file, jump} |
||||||
|
*/ |
||||||
|
Debugger.prototype.highlight = function (lineColumnPos, rawLocation) { |
||||||
|
var name = utils.fileNameFromKey(this.editor.getCacheFile()); // current opened tab
|
||||||
|
var source = this.lastCompilationResult.data.sourceList[rawLocation.file]; // auto switch to that tab
|
||||||
|
this.removeCurrentMarker(); |
||||||
|
if (name !== source) { |
||||||
|
this.switchToFile(source); // command the app to swicth to the next file
|
||||||
|
} |
||||||
|
this.currentRange = new Range(lineColumnPos.start.line, lineColumnPos.start.column, lineColumnPos.end.line, lineColumnPos.end.column); |
||||||
|
this.currentMarker = this.editor.addMarker(this.currentRange, 'highlightcode'); |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* add a new web3 provider to remix |
||||||
|
* |
||||||
|
* @param {String} type - type/name of the provider to add |
||||||
|
* @param {Object} obj - provider |
||||||
|
*/ |
||||||
Debugger.prototype.addProvider = function (type, obj) { |
Debugger.prototype.addProvider = function (type, obj) { |
||||||
this.debugger.addProvider(type, obj); |
this.debugger.addProvider(type, obj); |
||||||
}; |
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* switch the provider |
||||||
|
* |
||||||
|
* @param {String} type - type/name of the provider to use |
||||||
|
*/ |
||||||
Debugger.prototype.switchProvider = function (type) { |
Debugger.prototype.switchProvider = function (type) { |
||||||
this.debugger.switchProvider(type); |
this.debugger.switchProvider(type); |
||||||
}; |
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* get the current provider |
||||||
|
*/ |
||||||
Debugger.prototype.web3 = function (type) { |
Debugger.prototype.web3 = function (type) { |
||||||
return this.debugger.web3(); |
return this.debugger.web3(); |
||||||
}; |
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* unhighlight the current highlighted statement |
||||||
|
*/ |
||||||
|
Debugger.prototype.removeCurrentMarker = function () { |
||||||
|
if (this.currentMarker) { |
||||||
|
this.editor.removeMarker(this.currentMarker); |
||||||
|
this.currentMarker = null; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
function Cache () { |
||||||
|
this.contentLineBreakPosition = {}; |
||||||
|
} |
||||||
|
|
||||||
|
Cache.prototype.clear = function () { |
||||||
|
this.lineBreakPositionsByContent = {}; |
||||||
|
}; |
||||||
|
|
||||||
module.exports = Debugger; |
module.exports = Debugger; |
||||||
|
Loading…
Reference in new issue