Iuri Matias 1d6da99e8f display last error found
display last line on tx

fix debugger call

listen to source event only after jumping to the end

keep track of last tx; add minimal debug feature; fix ast issue

initial debugger apis & ui integration

prevent crash when step is out of bounds; send all all available data in websocket

add debugger commands

fix line number tracking in editor; toggle breakpoints

replace timeouts with callbacks

add debugger manager & refactor

refactor debugger api

refactor cmd line debugger

reduce debugger decoupling

reduce debugger decoupling

fix debug buttons

trigger source update so api triggers ws event to update source location

move locals and contracts vars to a json view

improve debugger icons

simplify debugger data

update debug package

add command handler to get a contract given a tx; update debugger so it can get a contract by its tx instead of tracking latest txs only

update debugger package
2018-10-23 18:27:40 -04:00

213 lines
6.6 KiB
JavaScript

var RemixDebug = require('remix-debug-debugtest');
var CmdLine = RemixDebug.CmdLine;
var DebuggerManager = require('./debugger_manager.js');
class TransactionDebugger {
constructor(embark, _options) {
const self = this
this.embark = embark
this.debugger_manager = new DebuggerManager("http://localhost:8545")
embark.events.on('contracts:compile:solc', this.debugger_manager.setInputJson.bind(this.debugger_manager))
embark.events.on('contracts:compiled:solc', this.debugger_manager.setOutputJson.bind(this.debugger_manager))
this.tx_tracker = {}
this.last_tx = ""
this.isDebugging = false
this.listenToEvents()
this.listenToCommands()
this.listentoAPI()
}
listenToEvents() {
const self = this
this.embark.events.on('blockchain:tx', (tx) => {
this.embark.events.request("contracts:contract", tx.name, (contract) => {
self.tx_tracker[tx.transactionHash] = {tx: tx, contract: contract}
self.last_tx = tx.transactionHash
if (tx.status !== '0x0') return
self.embark.logger.info("Transaction failed");
self.debugger_manager.getLastLine(tx.transactionHash, contract.filename, (lines) => {
lines.forEach((line) => {
self.embark.logger.error(line)
})
})
})
})
}
listentoAPI() {
this.debuggerData = {}
this.apiDebugger = false
this.embark.registerAPICall('post', '/embark-api/debugger/start', (req, res) => {
let txHash = req.body.params.txHash
this.embark.events.request("contracts:contract:byTxHash", txHash, (err, contract) => {
if (err) {
this.embark.logger.error(err);
return res.send({error: err})
}
let filename = contract.filename
this.debuggerData = {}
this.apiDebugger = this.debugger_manager.createDebuggerSession(txHash, filename, () => {
})
res.send({ok :true})
})
});
this.embark.registerAPICall('post', '/embark-api/debugger/JumpBack', (req, res) => {
this.apiDebugger.stepJumpNextBreakpoint()
res.send({ok :true})
})
this.embark.registerAPICall('post', '/embark-api/debugger/JumpForward', (req, res) => {
this.apiDebugger.stepJumpPreviousBreakpoint()
res.send({ok :true})
})
this.embark.registerAPICall('post', '/embark-api/debugger/StepOverForward', (req, res) => {
this.apiDebugger.stepOverForward(true)
res.send({ok :true})
})
this.embark.registerAPICall('post', '/embark-api/debugger/StepOverBackward', (req, res) => {
this.apiDebugger.stepOverBack(true)
res.send({ok :true})
})
this.embark.registerAPICall('post', '/embark-api/debugger/StepIntoForward', (req, res) => {
this.apiDebugger.stepIntoForward(true)
res.send({ok :true})
})
this.embark.registerAPICall('post', '/embark-api/debugger/StepIntoBackward', (req, res) => {
this.apiDebugger.stepIntoBack(true)
res.send({ok :true})
});
this.embark.registerAPICall('post', '/embark-api/debugger/breakpoint', (req, res) => {
console.dir("new breakpoint")
res.send({ok :true})
});
this.embark.registerAPICall('ws', '/embark-api/debugger', (ws, _req) => {
if (!this.apiDebugger) return
this.apiDebugger.events.on("source", (lineColumnPos, rawLocation) => {
this.debuggerData.sources = {lineColumnPos, rawLocation}
ws.send(JSON.stringify(this.debuggerData), () => {})
})
this.apiDebugger.events.on("locals", (data) => {
this.debuggerData.locals = this.simplifyDebuggerVars(data)
ws.send(JSON.stringify(this.debuggerData), () => {})
})
this.apiDebugger.events.on("globals", (data) => {
this.debuggerData.globals = this.simplifyDebuggerVars(data)
ws.send(JSON.stringify(this.debuggerData), () => {})
})
});
}
simplifyDebuggerVars(data) {
let new_data = {};
for (let key in data) {
let field = data[key];
new_data[`${key} (${field.type})`] = field.value
}
return new_data
}
listenToCommands() {
const self = this
this.cmdDebugger = false
this.embark.registerConsoleCommand((cmd, _options) => {
let cmdName = cmd.split(" ")[0]
let txHash = cmd.split(" ")[1]
return {
match: () => cmdName === 'debug',
process: (cb) => {
if (txHash) {
this.embark.events.request("contracts:contract:byTxHash", txHash, (err, contract) => {
if (err) {
this.embark.logger.error(err);
return;
}
let filename = contract.filename
self.cmdDebugger = self.debugger_manager.createDebuggerSession(txHash, filename, () => {
self.cmdDebugger.getSource().forEach((line) => {
console.dir(line)
})
})
});
return
}
let filename = self.tx_tracker[self.last_tx].contract.filename
self.cmdDebugger = self.debugger_manager.createDebuggerSession(self.last_tx, filename, () => {
self.cmdDebugger.getSource().forEach((line) => {
console.dir(line)
})
})
}
};
})
this.embark.registerConsoleCommand((cmd, _options) => {
return {
match: () => (cmd === 'next' || cmd === 'n'),
process: (cb) => {
if (!self.cmdDebugger.currentStep()) {
console.dir("end of execution reached")
return self.cmdDebugger.unload()
}
self.cmdDebugger.stepOverForward(true)
self.cmdDebugger.getSource().forEach((line) => {
console.dir(line)
})
}
};
})
this.embark.registerConsoleCommand((cmd, _options) => {
return {
match: () => (cmd === 'previous' || cmd === 'p'),
process: (cb) => {
if (!self.cmdDebugger.currentStep()) {
console.dir("end of execution reached")
return self.cmdDebugger.unload()
}
self.cmdDebugger.stepOverBack(true)
self.cmdDebugger.getSource().forEach((line) => {
console.dir(line)
})
}
};
})
this.embark.registerConsoleCommand((cmd, _options) => {
return {
match: () => (cmd === 'var local' || cmd === 'v l' || cmd === 'vl'),
process: (cb) => {
self.cmdDebugger.displayLocals()
}
};
})
this.embark.registerConsoleCommand((cmd, _options) => {
return {
match: () => (cmd === 'var global' || cmd === 'v g' || cmd === 'vg'),
process: (cb) => {
self.cmdDebugger.displayGlobals()
}
};
})
}
}
module.exports = TransactionDebugger