|
|
|
@ -1,13 +1,6 @@ |
|
|
|
|
import React from 'react' |
|
|
|
|
import * as EventManager from '../../../../apps/remix-ide/src/lib/events' |
|
|
|
|
|
|
|
|
|
const { useState } = React |
|
|
|
|
const DebuggerUI = ({ debuggerModule, component, fetchContractAndCompile }) => { |
|
|
|
|
const [state, setState] = useState({ |
|
|
|
|
debuggerModule, |
|
|
|
|
fetchContractAndCompile, |
|
|
|
|
event |
|
|
|
|
}) |
|
|
|
|
const DebuggerUI = () => { |
|
|
|
|
return ( |
|
|
|
|
<div> |
|
|
|
|
<h1>Welcome to debugger-ui!</h1> |
|
|
|
@ -15,232 +8,4 @@ const DebuggerUI = ({ debuggerModule, component, fetchContractAndCompile }) => { |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export default DebuggerUi |
|
|
|
|
|
|
|
|
|
var TxBrowser = require('./debuggerUI/TxBrowser') |
|
|
|
|
var StepManagerUI = require('./debuggerUI/StepManager') |
|
|
|
|
var VmDebugger = require('./debuggerUI/VmDebugger') |
|
|
|
|
var toaster = require('../../ui/tooltip') |
|
|
|
|
|
|
|
|
|
var Debugger = require('@remix-project/remix-debug').TransactionDebugger |
|
|
|
|
|
|
|
|
|
var SourceHighlighter = require('../../editor/sourceHighlighter') |
|
|
|
|
|
|
|
|
|
var globalRegistry = require('../../../global/registry') |
|
|
|
|
|
|
|
|
|
var remixLib = require('@remix-project/remix-lib') |
|
|
|
|
|
|
|
|
|
var init = remixLib.init |
|
|
|
|
|
|
|
|
|
var yo = require('yo-yo') |
|
|
|
|
var csjs = require('csjs-inject') |
|
|
|
|
|
|
|
|
|
var css = csjs` |
|
|
|
|
.statusMessage { |
|
|
|
|
margin-left: 15px; |
|
|
|
|
} |
|
|
|
|
` |
|
|
|
|
|
|
|
|
|
class DebuggerUI { |
|
|
|
|
|
|
|
|
|
constructor (debuggerModule, component, fetchContractAndCompile) { |
|
|
|
|
this.fetchContractAndCompile = fetchContractAndCompile |
|
|
|
|
this.event = new EventManager() |
|
|
|
|
|
|
|
|
|
this.isActive = false |
|
|
|
|
|
|
|
|
|
this.sourceHighlighter = new SourceHighlighter() |
|
|
|
|
|
|
|
|
|
this.startTxBrowser() |
|
|
|
|
this.stepManager = null |
|
|
|
|
|
|
|
|
|
this.statusMessage = '' |
|
|
|
|
this.currentReceipt |
|
|
|
|
|
|
|
|
|
this.view |
|
|
|
|
|
|
|
|
|
component.appendChild(this.render()) |
|
|
|
|
|
|
|
|
|
this.setEditor() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
setEditor () { |
|
|
|
|
this.editor = globalRegistry.get('editor').api |
|
|
|
|
|
|
|
|
|
this.editor.event.register('breakpointCleared', (fileName, row) => { |
|
|
|
|
if (this.debugger) this.debugger.breakPointManager.remove({fileName: fileName, row: row}) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
this.editor.event.register('breakpointAdded', (fileName, row) => { |
|
|
|
|
if (this.debugger) this.debugger.breakPointManager.add({fileName: fileName, row: row}) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
this.editor.event.register('contentChanged', () => { |
|
|
|
|
if (this.debugger) this.debugger.unload() |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
listenToEvents () { |
|
|
|
|
if (!this.debugger) return |
|
|
|
|
|
|
|
|
|
this.debugger.event.register('debuggerStatus', async (isActive) => { |
|
|
|
|
await this.debuggerModule.call('editor', 'discardHighlight') |
|
|
|
|
this.isActive = isActive |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
this.debugger.event.register('newSourceLocation', async (lineColumnPos, rawLocation) => { |
|
|
|
|
const contracts = await this.fetchContractAndCompile( |
|
|
|
|
this.currentReceipt.contractAddress || this.currentReceipt.to, |
|
|
|
|
this.currentReceipt) |
|
|
|
|
if (contracts) { |
|
|
|
|
const path = contracts.getSourceName(rawLocation.file) |
|
|
|
|
if (path) { |
|
|
|
|
await this.debuggerModule.call('editor', 'discardHighlight') |
|
|
|
|
await this.debuggerModule.call('editor', 'highlight', lineColumnPos, path) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
this.debugger.event.register('debuggerUnloaded', () => this.unLoad()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
startTxBrowser () { |
|
|
|
|
let txBrowser = new TxBrowser() |
|
|
|
|
this.txBrowser = txBrowser |
|
|
|
|
|
|
|
|
|
txBrowser.event.register('requestDebug', (blockNumber, txNumber, tx) => { |
|
|
|
|
if (this.debugger) this.debugger.unload() |
|
|
|
|
this.startDebugging(blockNumber, txNumber, tx) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
txBrowser.event.register('unloadRequested', this, (blockNumber, txIndex, tx) => { |
|
|
|
|
if (this.debugger) this.debugger.unload() |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
isDebuggerActive () { |
|
|
|
|
return this.isActive |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getDebugWeb3 () { |
|
|
|
|
return new Promise((resolve, reject) => { |
|
|
|
|
this.debuggerModule.blockchain.detectNetwork((error, network) => { |
|
|
|
|
let web3 |
|
|
|
|
if (error || !network) { |
|
|
|
|
web3 = init.web3DebugNode(this.debuggerModule.blockchain.web3()) |
|
|
|
|
} else { |
|
|
|
|
const webDebugNode = init.web3DebugNode(network.name) |
|
|
|
|
web3 = !webDebugNode ? this.debuggerModule.blockchain.web3() : webDebugNode |
|
|
|
|
} |
|
|
|
|
init.extendWeb3(web3) |
|
|
|
|
resolve(web3) |
|
|
|
|
}) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async startDebugging (blockNumber, txNumber, tx) { |
|
|
|
|
if (this.debugger) this.unLoad() |
|
|
|
|
|
|
|
|
|
let web3 = await this.getDebugWeb3() |
|
|
|
|
this.currentReceipt = await web3.eth.getTransactionReceipt(txNumber) |
|
|
|
|
this.debugger = new Debugger({ |
|
|
|
|
web3, |
|
|
|
|
offsetToLineColumnConverter: globalRegistry.get('offsettolinecolumnconverter').api, |
|
|
|
|
compilationResult: async (address) => { |
|
|
|
|
try { |
|
|
|
|
return await this.fetchContractAndCompile(address, this.currentReceipt) |
|
|
|
|
} catch (e) { |
|
|
|
|
console.error(e) |
|
|
|
|
} |
|
|
|
|
return null |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
this.listenToEvents() |
|
|
|
|
this.debugger.debug(blockNumber, txNumber, tx, () => { |
|
|
|
|
this.stepManager = new StepManagerUI(this.debugger.step_manager) |
|
|
|
|
this.vmDebugger = new VmDebugger(this.debugger.vmDebuggerLogic) |
|
|
|
|
this.txBrowser.setState({ blockNumber, txNumber, debugging: true }) |
|
|
|
|
this.renderDebugger() |
|
|
|
|
}).catch((error) => { |
|
|
|
|
toaster(error) |
|
|
|
|
this.unLoad() |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getTrace (hash) { |
|
|
|
|
return new Promise(async (resolve, reject) => { |
|
|
|
|
const web3 = await this.getDebugWeb3() |
|
|
|
|
|
|
|
|
|
this.currentReceipt = await web3.eth.getTransactionReceipt(hash) |
|
|
|
|
const debug = new Debugger({ |
|
|
|
|
web3, |
|
|
|
|
offsetToLineColumnConverter: globalRegistry.get('offsettolinecolumnconverter').api, |
|
|
|
|
compilationResult: async (address) => { |
|
|
|
|
try { |
|
|
|
|
return await this.fetchContractAndCompile(address, this.currentReceipt) |
|
|
|
|
} catch (e) { |
|
|
|
|
console.error(e) |
|
|
|
|
} |
|
|
|
|
return null |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
debug.debugger.traceManager.traceRetriever.getTrace(hash, (error, trace) => { |
|
|
|
|
if (error) return reject(error) |
|
|
|
|
resolve(trace) |
|
|
|
|
}) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
debug (txHash) { |
|
|
|
|
this.startDebugging(null, txHash, null) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
render () { |
|
|
|
|
this.debuggerPanelsView = yo`<div class="px-2"></div>` |
|
|
|
|
this.debuggerHeadPanelsView = yo`<div class="px-2"></div>` |
|
|
|
|
this.stepManagerView = yo`<div class="px-2"></div>` |
|
|
|
|
|
|
|
|
|
var view = yo` |
|
|
|
|
<div> |
|
|
|
|
<div class="px-2"> |
|
|
|
|
${this.txBrowser.render()} |
|
|
|
|
${this.stepManagerView} |
|
|
|
|
${this.debuggerHeadPanelsView} |
|
|
|
|
</div> |
|
|
|
|
<div class="${css.statusMessage}">${this.statusMessage}</div> |
|
|
|
|
${this.debuggerPanelsView} |
|
|
|
|
</div> |
|
|
|
|
` |
|
|
|
|
if (!this.view) { |
|
|
|
|
this.view = view |
|
|
|
|
} |
|
|
|
|
return view |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async unLoad () { |
|
|
|
|
yo.update(this.debuggerHeadPanelsView, yo`<div></div>`) |
|
|
|
|
yo.update(this.debuggerPanelsView, yo`<div></div>`) |
|
|
|
|
yo.update(this.stepManagerView, yo`<div></div>`) |
|
|
|
|
if (this.vmDebugger) this.vmDebugger.remove() |
|
|
|
|
if (this.stepManager) this.stepManager.remove() |
|
|
|
|
if (this.txBrowser) this.txBrowser.setState({debugging: false}) |
|
|
|
|
this.vmDebugger = null |
|
|
|
|
this.stepManager = null |
|
|
|
|
if (this.debugger) delete this.debugger |
|
|
|
|
this.event.trigger('traceUnloaded') |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async deleteHighlights () { |
|
|
|
|
await this.debuggerModule.call('editor', 'discardHighlight') |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
renderDebugger () { |
|
|
|
|
yo.update(this.debuggerHeadPanelsView, this.vmDebugger.renderHead()) |
|
|
|
|
yo.update(this.debuggerPanelsView, this.vmDebugger.render()) |
|
|
|
|
yo.update(this.stepManagerView, this.stepManager.render()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
module.exports = DebuggerUI |
|
|
|
|
export default DebuggerUI |
|
|
|
|