delete sourcehightlighter.js

pull/1/head
yann300 8 years ago
parent c33a671148
commit e7f0512635
  1. 44
      src/app.js
  2. 2
      src/app/compiler-worker.js
  3. 24
      src/app/compiler.js
  4. 108
      src/app/debugger.js
  5. 34
      src/app/execution-context.js
  6. 206
      src/app/sourceHighlighter.js

@ -18,8 +18,6 @@ var UniversalDApp = require('./universal-dapp.js');
var Debugger = require('./app/debugger');
var FormalVerification = require('./app/formalVerification');
var EventManager = require('./lib/eventManager');
var SourceHighlighter = require('./app/sourceHighlighter');
// The event listener needs to be registered as early as possible, because the
// parent will send the message upon the "load" event.
var filesToLoad = null;
@ -234,7 +232,7 @@ var run = function () {
}
return false;
});
function swicthToFile (file) {
editor.setCacheFile(utils.fileKey(file));
updateFiles();
@ -242,8 +240,7 @@ var run = function () {
function showFileHandler (ev) {
ev.preventDefault();
swicthToFile($(this).find('.name').text())
updateFiles();
swicthToFile($(this).find('.name').text());
return false;
}
@ -422,11 +419,14 @@ var run = function () {
}
var executionContext = new ExecutionContext();
var transactionDebugger = new Debugger('#debugger', executionContext.event);
transactionDebugger.addProvider('VM', executionContext.vm());
var compiler = new Compiler(editor, queryParams, handleGithubCall, updateFiles);
var formalVerification = new FormalVerification($('#verificationView'), compiler.event);
var transactionDebugger = new Debugger('#debugger', editor, compiler, executionContext.event, swicthToFile);
transactionDebugger.addProvider('vm', executionContext.vm());
transactionDebugger.switchProvider('VM');
transactionDebugger.addProvider('INTERNAL', executionContext.web3());
transactionDebugger.addProvider('EXTERNAL', executionContext.web3());
transactionDebugger.addProvider('injected', executionContext.web3());
transactionDebugger.addProvider('web3', executionContext.web3());
var udapp = new UniversalDApp(executionContext, {
removable: false,
@ -434,14 +434,10 @@ var run = function () {
}, transactionDebugger);
udapp.event.register('debugRequested', this, function (txResult) {
transactionDebugger.debug(txResult);
selectTab($('ul#options li.debugView'));
startdebugging(txResult.transactionHash);
});
var compiler = new Compiler(editor, queryParams, handleGithubCall, updateFiles);
var formalVerification = new FormalVerification($('#verificationView'), compiler.event);
var renderer = new Renderer(editor, executionContext.web3(), updateFiles, udapp, executionContext, formalVerification.event, compiler.event); // eslint-disable-line
var sourceHighlighter = new SourceHighlighter(editor, transactionDebugger.debugger, compiler.event, this.event, swicthToFile) // eslint-disable-line
executionContext.event.register('contextChanged', this, function (context) {
compiler.compile();
@ -451,8 +447,9 @@ var run = function () {
compiler.compile();
});
executionContext.event.register('compilerLoaded', this, function (context) {
compiler.event.register('compilerLoaded', this, function (context) {
compiler.compile();
initWithQueryParams();
});
compiler.event.register('compilerLoaded', this, function (version) {
@ -460,6 +457,23 @@ var run = function () {
compiler.compile();
});
function initWithQueryParams () {
if (queryParams.get().endpointurl) {
executionContext.setEndPointUrl(queryParams.get().endpointurl);
}
if (queryParams.get().context) {
executionContext.setContext(queryParams.get().context);
}
if (queryParams.get().debugtx) {
startdebugging(queryParams.get().debugtx);
}
}
function startdebugging (txHash) {
transactionDebugger.debug(txHash);
selectTab($('ul#options li.debugView'));
}
function setVersionText (text) {
$('#version').text(text);
}

@ -34,7 +34,7 @@ module.exports = function (self) {
break;
case 'compile':
missingInputs.length = 0;
self.postMessage({cmd: 'compiled', data: compileJSON(data.source, data.optimize), missingInputs: missingInputs});
self.postMessage({cmd: 'compiled', data: compileJSON(data.source, data.optimize), missingInputs: missingInputs, source: data.source});
break;
}
}, false);

@ -16,7 +16,7 @@ function Compiler (editor, queryParams, handleGithubCall, updateFiles) {
var compileJSON;
var compilerAcceptsMultipleFiles;
var previousInput = '';
var cachedRemoteFiles = {};
@ -60,7 +60,7 @@ function Compiler (editor, queryParams, handleGithubCall, updateFiles) {
});
};
this.compile = compile;
function setCompileJSON (_compileJSON) {
compileJSON = _compileJSON;
}
@ -91,24 +91,28 @@ function Compiler (editor, queryParams, handleGithubCall, updateFiles) {
result = { error: 'Uncaught JavaScript exception:\n' + exception };
}
compilationFinished(result, missingInputs);
compilationFinished(result, missingInputs, source);
};
onCompilerLoaded(compiler.version());
}
}
function compilationFinished (data, missingInputs) {
this.lastCompilationResult = {
data: null,
source: null
}
function compilationFinished (data, missingInputs, source) {
var noFatalErrors = true; // ie warnings are ok
if (data['error'] !== undefined) {
self.event.trigger('compilationFinished', [false, [data['error']], editor.getValue()]);
self.event.trigger('compilationFinished', [false, [data['error']], source]);
if (utils.errortype(data['error']) !== 'warning') {
noFatalErrors = false;
}
}
if (data['errors'] !== undefined) {
self.event.trigger('compilationFinished', [false, data['errors'], editor.getValue()]);
self.event.trigger('compilationFinished', [false, data['errors'], source]);
data['errors'].forEach(function (err) {
if (utils.errortype(err) !== 'warning') {
noFatalErrors = false;
@ -119,7 +123,11 @@ function Compiler (editor, queryParams, handleGithubCall, updateFiles) {
if (missingInputs !== undefined && missingInputs.length > 0) {
compile(missingInputs);
} else if (noFatalErrors) {
self.event.trigger('compilationFinished', [true, data, editor.getValue()]);
self.lastCompilationResult = {
data: data,
source: source
}
self.event.trigger('compilationFinished', [true, data, source]);
}
}
@ -170,7 +178,7 @@ function Compiler (editor, queryParams, handleGithubCall, updateFiles) {
} catch (exception) {
result = { 'error': 'Invalid JSON output from the compiler: ' + exception };
}
compilationFinished(result, data.missingInputs);
compilationFinished(result, data.missingInputs, data.source);
break;
}
});

@ -1,38 +1,132 @@
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.debugger = new remix.ui.Debugger();
this.sourceMappingDecoder = new remix.util.SourceMappingDecoder()
this.el.appendChild(this.debugger.render());
this.editor = editor;
this.switchToFile = switchToFile;
this.compiler = compiler;
this.cache = new Cache()
var self = this;
executionContextEvent.register('contextChanged', this, function (context) {
context = context === 'vm' ? 'VM' : context;
context = context === 'injected' ? 'EXTERNAL' : context;
context = context === 'web3' ? 'INTERNAL' : 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.lastCompilationResult = null;
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) {
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);
}
});
});
}
Debugger.prototype.debug = function (receipt) {
var self = this
this.debugger.web3().eth.getTransaction(receipt.transactionHash, function (error, tx) {
/**
* Start debugging using Remix
*
* @param {String} txHash - hash of the transaction
*/
Debugger.prototype.debug = function (txHash) {
var self = this;
this.debugger.web3().eth.getTransaction(txHash, function (error, tx) {
if (!error) {
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) {
this.debugger.addProvider(type, obj);
};
/**
* switch the provider
*
* @param {String} type - type/name of the provider to use
*/
Debugger.prototype.switchProvider = function (type) {
this.debugger.switchProvider(type);
};
/**
* get the current provider
*/
Debugger.prototype.web3 = function (type) {
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;

@ -21,7 +21,6 @@ vm.stateManager.checkpoint();
/*
trigger contextChanged, web3EndpointChanged
*/
function ExecutionContext () {
var self = this;
this.event = new EventManager();
@ -39,6 +38,16 @@ function ExecutionContext () {
return vm;
};
this.setEndPointUrl = function (url) {
$web3endpoint.val(url);
};
this.setContext = function (context) {
executionContext = context;
executionContextChange(context);
setExecutionContextRadio()
};
var $injectedToggle = $('#injected-mode');
var $vmToggle = $('#vm-mode');
var $web3Toggle = $('#web3-mode');
@ -50,9 +59,9 @@ function ExecutionContext () {
setExecutionContextRadio();
$injectedToggle.on('change', executionContextChange);
$vmToggle.on('change', executionContextChange);
$web3Toggle.on('change', executionContextChange);
$injectedToggle.on('change', executionContextUIChange);
$vmToggle.on('change', executionContextUIChange);
$web3Toggle.on('change', executionContextUIChange);
$web3endpoint.on('change', function () {
setProviderFromEndpoint();
if (executionContext === 'web3') {
@ -60,20 +69,23 @@ function ExecutionContext () {
}
});
function executionContextChange (ev) {
if (ev.target.value === 'web3' && !confirm('Are you sure you want to connect to a local ethereum node?')) {
function executionContextUIChange (ev) {
executionContextChange(ev.target.value);
}
function executionContextChange (context) {
if (context === 'web3' && !confirm('Are you sure you want to connect to a local ethereum node?')) {
setExecutionContextRadio();
} else if (ev.target.value === 'injected' && injectedProvider === undefined) {
} else if (context === 'injected' && injectedProvider === undefined) {
setExecutionContextRadio();
} else {
executionContext = ev.target.value;
if (executionContext === 'web3') {
if (context === 'web3') {
setProviderFromEndpoint();
self.event.trigger('contextChanged', ['web3']);
} else if (executionContext === 'injected') {
} else if (context === 'injected') {
web3.setProvider(injectedProvider);
self.event.trigger('contextChanged', ['injected']);
} else if (executionContext === 'vm') {
} else if (context === 'vm') {
vm.stateManager.revert(function () {
vm.stateManager.checkpoint();
});

@ -1,206 +0,0 @@
var utils = require('./utils')
var remix = require('ethereum-remix')
var ace = require('brace')
var Range = ace.acequire('ace/range').Range
/*
Provides source highlighting when debugging a transaction
*/
function SourceHighlighter (editor, txdebugger, compilerEvent, appEvent, switchToFile) {
this.switchToFile = switchToFile
this.editor = editor
this.txdebugger = txdebugger
this.sourceMappingDecoder = new remix.util.SourceMappingDecoder()
this.compilationData
this.currentSourceMap
this.currentLineColumnLayout // used to retrieve line/column from char/length
this.currentRange
this.currentMarker
this.currentExecutingAddress
this.currentFile
this.isDebugging = false
var self = this
/* hide/show marker when debugger does not have the focus */
appEvent.register('tabChanged', function (tab) {
if (tab !== 'debugView') {
self.editor.removeMarker(self.currentMarker)
} else {
if (self.currentRange) {
self.currentMarker = self.editor.addMarker(self.currentRange, 'highlightcode')
}
}
})
/* update compilation data */
compilerEvent.register('compilationFinished', this, function (success, data, source) {
if (!self.isDebugging) {
self.reset()
self.compilationData = success ? data : null
}
})
/* update marker, switch file if necessary */
txdebugger.codeManager.register('changed', this, function (code, address, index) {
if (!this.currentExecutingAddress !== address) {
// context changed, need to update srcmap
this.currentExecutingAddress = address
self.loadContext(txdebugger.tx, function (error, ctrName, srcmap) {
if (!error) {
self.currentSourceMap = srcmap
self.currentContractName = ctrName
self.highlightSource(index)
}
})
} else {
self.highlightSource(index)
}
})
txdebugger.register('newTraceLoaded', this, function () {
self.isDebugging = true
})
txdebugger.register('traceUnloaded', this, function () {
self.reset()
self.isDebugging = false
})
}
/*
* Load a new debugging context. A context is define by a new transaction.
* it:
* - builds the line/column layout from the source code.
* - retrieves the source map
*
* @param {Integer} index - the tx which defined the new debugging context
* @param {Function} callback - returns the decompressed source mapping for the given index {start, length, file, jump}
*/
SourceHighlighter.prototype.loadContext = function (tx, cb) {
var self = this
contractName(self.currentExecutingAddress, self, function (error, ctrName) {
if (!error) {
var srcmap = sourceMap(isContractCreation(self.currentExecutingAddress), ctrName, self.compilationData)
cb(null, ctrName, srcmap)
}
})
}
/*
* remove the editor marker and init attributes
*/
SourceHighlighter.prototype.reset = function () {
this.currentSourceMap = null
this.currentLineColumnLayout = null
this.removeCurrentMarker()
this.currentRange = null
this.currentMarker = null
this.currentExecutingAddress = null
this.currentFile = null
}
/*
* remove the current highlighted statement
*/
SourceHighlighter.prototype.removeCurrentMarker = function () {
if (this.currentMarker) {
this.editor.removeMarker(this.currentMarker)
this.currentMarker = null
}
}
/*
* highlight the statement with the given @arg index
*
* @param {Integer} index - the index of the assembly item to be highlighted
*/
SourceHighlighter.prototype.highlightSource = function (index) {
var self = this
this.sourceMappingDecoder.decompress(index, self.currentSourceMap, function (error, rawPos) { // retrieve the sourcemap location
if (!error) {
if (self.currentFile !== rawPos.file) { // source file changed, need to update the line/column layout
var file = self.compilationData.sourceList[rawPos.file]
self.sourceMappingDecoder.retrieveLineColumnLayout(self.editor.getFile(file), function (error, result) {
if (!error) {
self.currentLineColumnLayout = result
self.currentFile = rawPos.file
self.sourceMappingDecoder.getLineColumnPosition(rawPos, self.currentLineColumnLayout, function (error, pos) {
if (!error) {
self.highlight(pos, rawPos.file)
}
})
}
})
} else {
self.sourceMappingDecoder.getLineColumnPosition(rawPos, self.currentLineColumnLayout, function (error, pos) {
if (!error) {
self.highlight(pos, rawPos.file)
}
})
}
}
})
}
/*
* highlight the statement with the given @arg position
*
* @param {Object} position - the position to highlight { start: {line, column}, end: {line, column} }
*/
SourceHighlighter.prototype.highlight = function (position, fileIndex) {
var name = utils.fileNameFromKey(this.editor.getCacheFile()) // current opened tab
var source = this.compilationData.sourceList[parseInt(fileIndex)] // auto switch to that tab
this.removeCurrentMarker()
if (name !== source) {
this.switchToFile(source) // command the app to swicth to the curent file
}
this.currentRange = new Range(position.start.line, position.start.column, position.end.line, position.end.column)
this.currentMarker = this.editor.addMarker(this.currentRange, 'highlightcode')
}
function sourceMap (isConstructor, contractName, compilationData) {
if (isConstructor) {
return compilationData.contracts[contractName].srcmap
} else {
return srcmapRuntime(compilationData.contracts[contractName])
}
}
function contractName (executingAddress, self, cb) {
if (isContractCreation(executingAddress)) {
self.txdebugger.traceManager.getContractCreationCode(executingAddress, function (error, creationCode) {
if (!error) {
retrieveByteCode(creationCode, self.compilationData, 'bytecode', cb)
}
})
} else {
self.txdebugger.web3().eth.getCode(executingAddress, function (error, code) {
if (!error) {
retrieveByteCode(code, self.compilationData, 'runtimeBytecode', cb)
}
})
}
}
function retrieveByteCode (code, compilationData, prop, cb) {
for (var k in compilationData.contracts) {
if (code === '0x' + compilationData.contracts[k][prop]) {
cb(null, k)
return
}
cb('unable to retrieve contract name')
}
}
function srcmapRuntime (contract) {
return contract.srcmapRuntime ? contract.srcmapRuntime : contract['srcmap-runtime']
}
function isContractCreation (address) {
return address.indexOf('Contract Creation') !== -1
}
module.exports = SourceHighlighter
Loading…
Cancel
Save