error management in debugger

pull/775/head
LianaHus 4 years ago committed by Liana Husikyan
parent 9067c636e4
commit b9bded4a0e
  1. 1
      apps/remix-ide/src/app/tabs/debugger-tab.js
  2. 65
      libs/remix-ui/debugger-ui/src/lib/DebuggerAPI.ts
  3. 3
      libs/remix-ui/debugger-ui/src/lib/debugger-ui.css
  4. 66
      libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
  5. 31
      libs/remix-ui/debugger-ui/src/lib/tx-browser/tx-browser.tsx

@ -5,6 +5,7 @@ import { ViewPlugin } from '@remixproject/engine-web'
import * as packageJson from '../../../../../package.json' import * as packageJson from '../../../../../package.json'
import React from 'react' // eslint-disable-line import React from 'react' // eslint-disable-line
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
import modalDialogCustom from '../ui/modal-dialog-custom'
const yo = require('yo-yo') const yo = require('yo-yo')
const css = require('./styles/debugger-tab-styles') const css = require('./styles/debugger-tab-styles')

@ -0,0 +1,65 @@
import type { CompilationResult, CompilationSource } from '@remix-project/remix-solidity-ts'
export interface DebuggerUIProps {
debuggerAPI: DebuggerAPI
}
interface EditorEvent {
event: {
register(eventName: 'breakpointCleared' | 'breakpointAdded' | 'contentChanged',
callback: (fileName: string, row: string | number) => void)
}
}
interface LineColumnLocation {
start: {
line: number, column: number
},
end: {
line: number, column: number
}
}
interface RawLocation {
start: number, length: number
}
interface Sources {
[fileName: string] : {content: string}
}
interface CompilationOutput {
source: { sources: Sources, target: string }
data: CompilationResult
getSourceName: (id: number) => string
}
interface Asts {
[fileName: string] : CompilationSource // ast
}
interface TransactionReceipt {
blockHash: string
blockNumber: number
transactionHash: string
transactionIndex: number
from: string
to: string
contractAddress: string | null
}
export interface DebuggerAPI {
offsetToLineColumnConverter: { offsetToLineColumn: (sourceLocation: RawLocation, file: number, contents: Sources, asts: Asts) => LineColumnLocation }
debugHash: string
debugHashRequest: string
removeHighlights: boolean
editor: EditorEvent
discardHighlight: () => void
highlight: (lineColumnPos: LineColumnLocation, path: string) => void
fetchContractAndCompile: (address: string, currentReceipt: TransactionReceipt) => CompilationOutput
getFile: (path: string) => string
setFile: (path: string, content: string) => void
getDebugWeb3: () => any // returns an instance of web3.js
showMessage: (title: string, message: string) => void
}

@ -13,4 +13,7 @@
} }
.debuggerConfig label { .debuggerConfig label {
margin: 0; margin: 0;
}
.validationError {
overflow-wrap: break-word;
} }

@ -26,7 +26,9 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
debugWithGeneratedSources: false debugWithGeneratedSources: false
}, },
toastMessage: '', toastMessage: '',
currentDebugTransaction: '' currentDebugTransaction: '',
validationError: '',
txNumberIsEmpty: true
}) })
useEffect(() => { useEffect(() => {
@ -85,7 +87,9 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
try { try {
content = await debuggerModule.getFile(path) content = await debuggerModule.getFile(path)
} catch (e) { } catch (e) {
console.log('unable to fetch generated sources, the file probably doesn\'t exist yet', e) const message = 'Unable to fetch generated sources, the file probably doesn\'t exist yet.'
debuggerModule.showMessage('Debugging error', message)
console.log(message, ' ', e)
} }
if (content !== source.contents) { if (content !== source.contents) {
await debuggerModule.setFile(path, source.contents) await debuggerModule.setFile(path, source.contents)
@ -108,6 +112,16 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
startDebugging(blockNumber, txNumber, tx) startDebugging(blockNumber, txNumber, tx)
} }
const updateTxNumberFlag = (empty: boolean) => {
setState(prevState => {
return {
...prevState,
txNumberIsEmpty: empty,
validationError: ''
}
})
}
const unloadRequested = (blockNumber, txIndex, tx) => { const unloadRequested = (blockNumber, txIndex, tx) => {
unLoad() unLoad()
} }
@ -144,7 +158,19 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
} }
}) })
const web3 = await debuggerModule.getDebugWeb3() const web3 = await debuggerModule.getDebugWeb3()
const currentReceipt = await web3.eth.getTransactionReceipt(txNumber) let currentReceipt
try {
currentReceipt = await web3.eth.getTransactionReceipt(txNumber)
} catch (e) {
setState(prevState => {
return {
...prevState,
validationError: e.message
}
})
console.log(e.message)
}
const debuggerInstance = new Debugger({ const debuggerInstance = new Debugger({
web3, web3,
offsetToLineColumnConverter: debuggerModule.offsetToLineColumnConverter, offsetToLineColumnConverter: debuggerModule.offsetToLineColumnConverter,
@ -153,6 +179,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
const ret = await debuggerModule.fetchContractAndCompile(address, currentReceipt) const ret = await debuggerModule.fetchContractAndCompile(address, currentReceipt)
return ret return ret
} catch (e) { } catch (e) {
debuggerModule.showMessage('Debugging error', 'Unable to fetch a transaction.')
console.error(e) console.error(e)
} }
return null return null
@ -169,21 +196,33 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
debugging: true, debugging: true,
currentReceipt, currentReceipt,
debugger: debuggerInstance, debugger: debuggerInstance,
toastMessage: `debugging ${txNumber}` toastMessage: `debugging ${txNumber}`,
validationError: ''
} }
}) })
}).catch((error) => { }).catch((error) => {
setState(prevState => { if (JSON.stringify(error) !== '{}') {
return { let message = 'Error: ' + JSON.stringify(error)
...prevState, message = message.split(`\\"`).join(`'`)
toastMessage: JSON.stringify(error) setState(prevState => {
} return {
}) ...prevState,
validationError: message
}
})
console.log(message)
}
unLoad() unLoad()
}) })
} }
const debug = (txHash) => { const debug = (txHash) => {
setState(prevState => {
return {
...prevState,
validationError: ''
}
})
startDebugging(null, txHash, null) startDebugging(null, txHash, null)
} }
@ -208,8 +247,8 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
<div> <div>
<Toaster message={state.toastMessage} /> <Toaster message={state.toastMessage} />
<div className="px-2"> <div className="px-2">
<div className="mt-3"> <div>
<p className="mt-2 debuggerLabel">Debugger Configuration</p> <p className="my-2 debuggerLabel">Debugger Configuration</p>
<div className="mt-2 debuggerConfig custom-control custom-checkbox"> <div className="mt-2 debuggerConfig custom-control custom-checkbox">
<input className="custom-control-input" id="debugGeneratedSourcesInput" onChange={({ target: { checked } }) => { <input className="custom-control-input" id="debugGeneratedSourcesInput" onChange={({ target: { checked } }) => {
setState(prevState => { setState(prevState => {
@ -218,8 +257,9 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
}} type="checkbox" title="Debug with generated sources" /> }} type="checkbox" title="Debug with generated sources" />
<label data-id="debugGeneratedSourcesLabel" className="form-check-label custom-control-label" htmlFor="debugGeneratedSourcesInput">Use generated sources (from Solidity v0.7.2)</label> <label data-id="debugGeneratedSourcesLabel" className="form-check-label custom-control-label" htmlFor="debugGeneratedSourcesInput">Use generated sources (from Solidity v0.7.2)</label>
</div> </div>
{ (state.validationError && !state.txNumberIsEmpty) && <span className="w-100 py-1 text-danger validationError">{state.validationError}</span> }
</div> </div>
<TxBrowser requestDebug={ requestDebug } unloadRequested={ unloadRequested } transactionNumber={ state.txNumber } debugging={ state.debugging } /> <TxBrowser requestDebug={ requestDebug } unloadRequested={ unloadRequested } updateTxNumberFlag={ updateTxNumberFlag } transactionNumber={ state.txNumber } debugging={ state.debugging } />
{ state.debugging && <StepManager stepManager={ stepManager } /> } { state.debugging && <StepManager stepManager={ stepManager } /> }
{ state.debugging && <VmDebuggerHead vmDebugger={ vmDebugger } /> } { state.debugging && <VmDebuggerHead vmDebugger={ vmDebugger } /> }
</div> </div>

@ -1,11 +1,12 @@
import React, { useState, useEffect } from 'react' // eslint-disable-line import React, { useState, useEffect, useRef } from 'react'
import './tx-browser.css' import './tx-browser.css'
export const TxBrowser = ({ requestDebug, unloadRequested, transactionNumber, debugging }) => { export const TxBrowser = ({ requestDebug, updateTxNumberFlag, unloadRequested, transactionNumber, debugging }) => {
const [state, setState] = useState({ const [state, setState] = useState({
txNumber: '' txNumber: ''
}) })
const inputValue = useRef(null)
useEffect(() => { useEffect(() => {
setState(prevState => { setState(prevState => {
return { return {
@ -41,35 +42,41 @@ export const TxBrowser = ({ requestDebug, unloadRequested, transactionNumber, de
}) })
} }
const txInputOnInput = () => {
updateTxNumberFlag(!inputValue.current.value)
}
return ( return (
<div className="container px-0"> <div className='container px-0'>
<div className="txContainer"> <div className='txContainer'>
<div className="py-1 d-flex justify-content-center w-100 input-group"> <div className='py-1 d-flex justify-content-center w-100 input-group'>
<input <input
ref={inputValue}
value={state.txNumber} value={state.txNumber}
className="form-control m-0 txinput" className='form-control m-0 txinput'
id='txinput' id='txinput'
type='text' type='text'
onChange={({ target: { value } }) => txInputChanged(value)} onChange={({ target: { value } }) => txInputChanged(value)}
onInput={txInputOnInput}
placeholder={'Transaction hash, should start with 0x'} placeholder={'Transaction hash, should start with 0x'}
data-id="debuggerTransactionInput" data-id='debuggerTransactionInput'
disabled={debugging} disabled={debugging}
/> />
</div> </div>
<div className="d-flex justify-content-center w-100 btn-group py-1"> <div className='d-flex justify-content-center w-100 btn-group py-1'>
<button <button
className="btn btn-primary btn-sm txbutton" className='btn btn-primary btn-sm txbutton'
id="load" id='load'
title={debugging ? 'Stop debugging' : 'Start debugging'} title={debugging ? 'Stop debugging' : 'Start debugging'}
onClick={handleSubmit} onClick={handleSubmit}
data-id="debuggerTransactionStartButton" data-id='debuggerTransactionStartButton'
disabled={!state.txNumber } disabled={!state.txNumber }
> >
{ debugging ? 'Stop' : 'Start' } debugging { debugging ? 'Stop' : 'Start' } debugging
</button> </button>
</div> </div>
</div> </div>
<span id='error'></span> <span id='error' />
</div> </div>
) )
} }

Loading…
Cancel
Save