diff --git a/apps/remix-ide-e2e/src/tests/debugger.test.ts b/apps/remix-ide-e2e/src/tests/debugger.test.ts index 7a8cf034a0f..2cdef15587a 100644 --- a/apps/remix-ide-e2e/src/tests/debugger.test.ts +++ b/apps/remix-ide-e2e/src/tests/debugger.test.ts @@ -178,6 +178,33 @@ module.exports = { .getEditorValue((content) => { browser.assert.ok(content.indexOf('if slt(sub(dataEnd, headStart), 32) { revert(0, 0) }') != -1, 'current displayed content is not a generated source') }) + .click('*[data-id="debuggerTransactionStartButton"]') + }, + + 'Should call the debugger api: getTrace': function (browser: NightwatchBrowser) { + browser + .addFile('test_jsGetTrace.js', { content: jsGetTrace }) + .executeScript('remix.exeCurrent()') + .pause(3000) + .journalChildIncludes(`{ "gas": "0x2dc6c0", "return": "0x", "structLogs":`) + }, + + 'Should call the debugger api: debug': function (browser: NightwatchBrowser) { + browser + .addFile('test_jsDebug.js', { content: jsDebug }) + .executeScript('remix.exeCurrent()') + .pause(3000) + .clickLaunchIcon('debugger') + .waitForElementVisible('*[data-id="slider"]') + .click('*[data-id="slider"]') + .setValue('*[data-id="slider"]', '5') + .pause(1000) + /* + setting the slider to 5 leads to "vm trace step: 91" for chrome and "vm trace step: 92" for firefox + => There is something going wrong with the nightwatch API here. + As we are only testing if debugger is active, this is ok to keep that for now. + */ + .assert.containsText('*[data-id="stepdetail"]', 'vm trace step:\n9') .end() }, @@ -335,3 +362,21 @@ const localVariable_step717_ABIEncoder = { "type": "bytes" } } + +const jsGetTrace = `(async () => { + try { + const result = await remix.call('debugger', 'getTrace', '0xb175c3c9a9cd6bee3b6cc8be3369a945ac9611516005f8cba27a43486ff2bc50') + console.log('result ', result) + } catch (e) { + console.log(e.message) + } +})()` + +const jsDebug = `(async () => { + try { + const result = await remix.call('debugger', 'debug', '0xb175c3c9a9cd6bee3b6cc8be3369a945ac9611516005f8cba27a43486ff2bc50') + console.log('result ', result) + } catch (e) { + console.log(e.message) + } +})()` diff --git a/apps/remix-ide/src/app.js b/apps/remix-ide/src/app.js index b6e4ac88865..420b40f95df 100644 --- a/apps/remix-ide/src/app.js +++ b/apps/remix-ide/src/app.js @@ -370,7 +370,10 @@ Please make a backup of your contracts and start using http://remix.ethereum.org registry.get('fileproviders/browser').api, ) const analysis = new AnalysisTab(registry) - const debug = new DebuggerTab(blockchain) + const debug = new DebuggerTab( + blockchain, + registry.get('editor').api, + registry.get('offsettolinecolumnconverter').api) const test = new TestTab( registry.get('filemanager').api, registry.get('offsettolinecolumnconverter').api, diff --git a/apps/remix-ide/src/app/tabs/debugger-tab.js b/apps/remix-ide/src/app/tabs/debugger-tab.js index 3ad33d5a171..7438ab8883f 100644 --- a/apps/remix-ide/src/app/tabs/debugger-tab.js +++ b/apps/remix-ide/src/app/tabs/debugger-tab.js @@ -3,6 +3,7 @@ const css = require('./styles/debugger-tab-styles') import toaster from '../ui/tooltip' import { DebuggerUI } from '@remix-ui/debugger-ui' import { ViewPlugin } from '@remixproject/engine' +import remixDebug, { TransactionDebugger as Debugger } from '@remix-project/remix-debug' import * as packageJson from '../../../../../package.json' import React from 'react' import ReactDOM from 'react-dom' @@ -22,13 +23,15 @@ const profile = { class DebuggerTab extends ViewPlugin { - constructor (blockchain) { + constructor (blockchain, editor, offsetToLineColumnConverter) { super(profile) this.el = null + this.editor = editor + this.offsetToLineColumnConverter = offsetToLineColumnConverter this.blockchain = blockchain this.debugHash = null - this.getTraceHash = null this.removeHighlights = false + this.debugHashRequest = 0 } render () { @@ -81,12 +84,55 @@ class DebuggerTab extends ViewPlugin { debug (hash) { this.debugHash = hash + this.debugHashRequest++ // so we can trigger a debug using the same hash 2 times in a row. that's needs to be improved this.renderComponent() } - getTrace (hash) { - this.getTraceHash = hash - this.renderComponent() + getDebugWeb3 () { + return new Promise((resolve, reject) => { + this.blockchain.detectNetwork((error, network) => { + let web3 + if (error || !network) { + web3 = remixDebug.init.web3DebugNode(this.blockchain.web3()) + } else { + const webDebugNode = remixDebug.init.web3DebugNode(network.name) + web3 = !webDebugNode ? this.blockchain.web3() : webDebugNode + } + remixDebug.init.extendWeb3(web3) + resolve(web3) + }) + }) + } + + async getTrace (hash) { + if (!hash) return + try { + const web3 = await this.getDebugWeb3() + const currentReceipt = await web3.eth.getTransactionReceipt(hash) + const debug = new Debugger({ + web3, + offsetToLineColumnConverter: this.offsetToLineColumnConverter, + compilationResult: async (address) => { + try { + return await this.fetchContractAndCompile(address, currentReceipt) + } catch (e) { + console.error(e) + } + return null + }, + debugWithGeneratedSources: false + }) + + return await debug.debugger.traceManager.getTrace(hash) + } catch (e) { + throw e + } + } + + fetchContractAndCompile (address, receipt) { + const target = (address && remixDebug.traceHelper.isContractCreation(address)) ? receipt.contractAddress : address + + return this.call('fetchAndCompile', 'resolve', target || receipt.contractAddress || receipt.to, '.debug', this.blockchain.web3()) } // debugger () { diff --git a/libs/remix-debug/src/code/codeManager.js b/libs/remix-debug/src/code/codeManager.js index f997ce8ff73..56d9972bbf1 100644 --- a/libs/remix-debug/src/code/codeManager.js +++ b/libs/remix-debug/src/code/codeManager.js @@ -142,7 +142,11 @@ function retrieveIndexAndTrigger (codeMananger, address, step, code) { } catch (error) { return console.log(error) } - codeMananger.event.trigger('changed', [code, address, result]) + try { + codeMananger.event.trigger('changed', [code, address, result]) + } catch (e) { + console.log('dispatching event failed', e) + } } module.exports = CodeManager diff --git a/libs/remix-debug/src/solidity-decoder/internalCallTree.js b/libs/remix-debug/src/solidity-decoder/internalCallTree.js index 9053caaf32a..4f58adbf5c1 100644 --- a/libs/remix-debug/src/solidity-decoder/internalCallTree.js +++ b/libs/remix-debug/src/solidity-decoder/internalCallTree.js @@ -292,7 +292,7 @@ async function includeVariableDeclaration (tree, step, sourceLocation, scopeId, // } // } // input params - if (inputs) { + if (inputs && inputs.parameters) { functionDefinitionAndInputs.inputs = addParams(inputs, tree, scopeId, states, contractObj.name, previousSourceLocation, stack.length, inputs.parameters.length, -1) } // output params diff --git a/libs/remix-debug/src/trace/traceRetriever.js b/libs/remix-debug/src/trace/traceRetriever.js deleted file mode 100644 index 4d3b78a697d..00000000000 --- a/libs/remix-debug/src/trace/traceRetriever.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict' - -function TraceRetriever (options) { - this.web3 = options.web3 -} - -TraceRetriever.prototype.getTrace = function (txHash, callback) { - const options = { - disableStorage: true, - disableMemory: false, - disableStack: false, - fullStorage: false - } - this.web3.debug.traceTransaction(txHash, options, function (error, result) { - callback(error, result) - }) -} - -module.exports = TraceRetriever diff --git a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx index c8799fa148a..f99bd89698f 100644 --- a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx @@ -5,11 +5,9 @@ import VmDebugger from './vm-debugger/vm-debugger' import VmDebuggerHead from './vm-debugger/vm-debugger-head' import remixDebug, { TransactionDebugger as Debugger } from '@remix-project/remix-debug' /* eslint-disable-next-line */ -import globalRegistry from '../../../../../apps/remix-ide/src/global/registry' import './debugger-ui.css' export const DebuggerUI = ({ debuggerModule }) => { - const init = remixDebug.init const [state, setState] = useState({ isActive: false, statusMessage: '', @@ -31,12 +29,10 @@ export const DebuggerUI = ({ debuggerModule }) => { }, []) useEffect(() => { - debug(debuggerModule.debugHash) - }, [debuggerModule.debugHash]) - - useEffect(() => { - getTrace(debuggerModule.getTraceHash) - }, [debuggerModule.getTraceHash]) + if (debuggerModule.debugHash) { + debug(debuggerModule.debugHash) + } + }, [debuggerModule.debugHashRequest]) useEffect(() => { if (debuggerModule.removeHighlights) deleteHighlights() @@ -44,7 +40,7 @@ export const DebuggerUI = ({ debuggerModule }) => { useEffect(() => { const setEditor = () => { - const editor = globalRegistry.get('editor').api + const editor = debuggerModule.editor editor.event.register('breakpointCleared', (fileName, row) => { if (state.debugger) state.debugger.breakPointManager.remove({fileName: fileName, row: row}) @@ -64,12 +60,6 @@ export const DebuggerUI = ({ debuggerModule }) => { setEditor() }, [state.debugger]) - const fetchContractAndCompile = (address, receipt) => { - const target = (address && remixDebug.traceHelper.isContractCreation(address)) ? receipt.contractAddress : address - - return debuggerModule.call('fetchAndCompile', 'resolve', target || receipt.contractAddress || receipt.to, '.debug', debuggerModule.blockchain.web3()) - } - const listenToEvents = (debuggerInstance, currentReceipt) => { if (!debuggerInstance) return @@ -82,7 +72,7 @@ export const DebuggerUI = ({ debuggerModule }) => { debuggerInstance.event.register('newSourceLocation', async (lineColumnPos, rawLocation, generatedSources) => { if (!lineColumnPos) return - const contracts = await fetchContractAndCompile( + const contracts = await debuggerModule.fetchContractAndCompile( currentReceipt.contractAddress || currentReceipt.to, currentReceipt) @@ -128,22 +118,6 @@ export const DebuggerUI = ({ debuggerModule }) => { return state.isActive } - const getDebugWeb3 = (): Promise => { - return new Promise((resolve, reject) => { - debuggerModule.blockchain.detectNetwork((error, network) => { - let web3 - if (error || !network) { - web3 = init.web3DebugNode(debuggerModule.blockchain.web3()) - } else { - const webDebugNode = init.web3DebugNode(network.name) - web3 = !webDebugNode ? debuggerModule.blockchain.web3() : webDebugNode - } - init.extendWeb3(web3) - resolve(web3) - }) - }) - } - const unLoad = () => { if (state.debugger) state.debugger.unload() setState(prevState => { @@ -169,14 +143,14 @@ export const DebuggerUI = ({ debuggerModule }) => { const startDebugging = async (blockNumber, txNumber, tx) => { if (state.debugger) unLoad() if (!txNumber) return - const web3 = await getDebugWeb3() + const web3 = await debuggerModule.getDebugWeb3() const currentReceipt = await web3.eth.getTransactionReceipt(txNumber) const debuggerInstance = new Debugger({ web3, - offsetToLineColumnConverter: globalRegistry.get('offsettolinecolumnconverter').api, + offsetToLineColumnConverter: debuggerModule.offsetToLineColumnConverter, compilationResult: async (address) => { try { - return await fetchContractAndCompile(address, currentReceipt) + return await debuggerModule.fetchContractAndCompile(address, currentReceipt) } catch (e) { console.error(e) } @@ -206,35 +180,7 @@ const debug = (txHash) => { startDebugging(null, txHash, null) } -const getTrace = (hash) => { - if (!hash) return - return new Promise(async (resolve, reject) => { /* eslint-disable-line */ - const web3 = await getDebugWeb3() - const currentReceipt = await web3.eth.getTransactionReceipt(hash) - const debug = new Debugger({ - web3, - offsetToLineColumnConverter: globalRegistry.get('offsettolinecolumnconverter').api, - compilationResult: async (address) => { - try { - return await fetchContractAndCompile(address, currentReceipt) - } catch (e) { - console.error(e) - } - return null - }, - debugWithGeneratedSources: false - }) - setState(prevState => { - return { ...prevState, currentReceipt } - }) - - debug.debugger.traceManager.traceRetriever.getTrace(hash, (error, trace) => { - if (error) return reject(error) - resolve(trace) - }) - }) -} const deleteHighlights = async () => { await debuggerModule.call('editor', 'discardHighlight') diff --git a/package-lock.json b/package-lock.json index 26d5b3827ff..ddfb52a0683 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28127,6 +28127,7 @@ }, "dezalgo": { "version": "1.0.3", + "resolved": false, "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", "requires": { "asap": "^2.0.0", @@ -28755,6 +28756,7 @@ }, "normalize-git-url": { "version": "3.0.2", + "resolved": false, "integrity": "sha1-jl8Uvgva7bc+ByADEKpBbCc1D8Q=" }, "normalize-package-data": { @@ -28792,6 +28794,7 @@ }, "npm-install-checks": { "version": "3.0.0", + "resolved": false, "integrity": "sha1-1K7N/VGlPjcjt7L5Oy7ijjB7wNc=", "requires": { "semver": "^2.3.0 || 3.x || 4 || 5" @@ -29138,6 +29141,7 @@ }, "realize-package-specifier": { "version": "3.0.3", + "resolved": false, "integrity": "sha1-0N74gpUrjeP2frpekRmWYScfQfQ=", "requires": { "dezalgo": "^1.0.1", @@ -29674,6 +29678,7 @@ "dependencies": { "unique-slug": { "version": "2.0.0", + "resolved": false, "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", "requires": { "imurmurhash": "^0.1.4"