diff --git a/apps/debugger/src/app/debugger-api.ts b/apps/debugger/src/app/debugger-api.ts index 13238c6add..9c268e1360 100644 --- a/apps/debugger/src/app/debugger-api.ts +++ b/apps/debugger/src/app/debugger-api.ts @@ -41,8 +41,9 @@ export const DebuggerApiMixin = (Base) => class extends Base { await this.call('editor', 'discardHighlight') } - async highlight (lineColumnPos, path) { + async highlight (lineColumnPos, path, rawLocation) { await this.call('editor', 'highlight', lineColumnPos, path, '', { focus: true }) + this.call('') } async getFile (path) { diff --git a/libs/remix-debug/src/debugger/debugger.ts b/libs/remix-debug/src/debugger/debugger.ts index 41c846b937..14a0dcd0ed 100644 --- a/libs/remix-debug/src/debugger/debugger.ts +++ b/libs/remix-debug/src/debugger/debugger.ts @@ -76,7 +76,7 @@ export class Debugger { return } - this.debugger.callTree.sourceLocationTracker.getValidSourceLocationFromVMTraceIndex(address, index, compilationResultForAddress.data.contracts).then(async (rawLocation) => { + this.debugger.callTree.getValidSourceLocationFromVMTraceIndexFromCache(address, index, compilationResultForAddress.data.contracts).then(async (rawLocation) => { if (compilationResultForAddress && compilationResultForAddress.data) { const generatedSources = this.debugger.callTree.sourceLocationTracker.getGeneratedSourcesFromAddress(address) const astSources = Object.assign({}, compilationResultForAddress.data.sources) diff --git a/libs/remix-debug/src/solidity-decoder/internalCallTree.ts b/libs/remix-debug/src/solidity-decoder/internalCallTree.ts index b5440d2d7d..7900e50104 100644 --- a/libs/remix-debug/src/solidity-decoder/internalCallTree.ts +++ b/libs/remix-debug/src/solidity-decoder/internalCallTree.ts @@ -6,6 +6,17 @@ import { EventManager } from '../eventManager' import { parseType } from './decodeInfo' import { isContractCreation, isCallInstruction, isCreateInstruction, isJumpDestInstruction } from '../trace/traceHelper' import { extractLocationFromAstVariable } from './types/util' +import { Uint } from './types/Uint' + +export type StepDetail = { + depth: number, + gas: number, + gasCost: number, + memory: number[], + op: string, + pc: number, + stack: number[], +} /** * Tree representing internal jump into function. @@ -27,6 +38,9 @@ export class InternalCallTree { functionDefinitionByFile astWalker reducedTrace + locationAndOpcodePerVMTraceIndex: { + [Key: number]: any + } /** * constructor @@ -89,6 +103,7 @@ export class InternalCallTree { this.functionDefinitionByFile = {} this.astWalker = new AstWalker() this.reducedTrace = [] + this.locationAndOpcodePerVMTraceIndex = {} } /** @@ -145,6 +160,7 @@ export class InternalCallTree { try { const address = this.traceManager.getCurrentCalledAddressAt(step) const location = await this.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, step, this.solidityProxy.contracts) + return location } catch (error) { throw new Error('InternalCallTree - Cannot retrieve sourcelocation for step ' + step + ' ' + error) @@ -160,6 +176,10 @@ export class InternalCallTree { throw new Error('InternalCallTree - Cannot retrieve valid sourcelocation for step ' + step + ' ' + error) } } + + async getValidSourceLocationFromVMTraceIndexFromCache (address: string, step: number, contracts: any) { + return await this.sourceLocationTracker.getValidSourceLocationFromVMTraceIndexFromCache(address, step, contracts, this.locationAndOpcodePerVMTraceIndex) + } } async function buildTree (tree, step, scopeId, isExternalCall, isCreation) { @@ -201,8 +221,11 @@ async function buildTree (tree, step, scopeId, isExternalCall, isCreation) { if (!sourceLocation) { return { outStep: step, error: 'InternalCallTree - No source Location. ' + step } } - const isCallInstrn = isCallInstruction(tree.traceManager.trace[step]) - const isCreateInstrn = isCreateInstruction(tree.traceManager.trace[step]) + const stepDetail: StepDetail = tree.traceManager.trace[step] + tree.locationAndOpcodePerVMTraceIndex[step] = { ...sourceLocation, ...stepDetail } + console.log('locationAndOpcodePerVMTraceIndex', stepDetail) + const isCallInstrn = isCallInstruction(stepDetail) + const isCreateInstrn = isCreateInstruction(stepDetail) // we are checking if we are jumping in a new CALL or in an internal function if (isCallInstrn || sourceLocation.jump === 'i') { try { diff --git a/libs/remix-debug/src/source/sourceLocationTracker.ts b/libs/remix-debug/src/source/sourceLocationTracker.ts index f9967b5e98..d870f6c2d4 100644 --- a/libs/remix-debug/src/source/sourceLocationTracker.ts +++ b/libs/remix-debug/src/source/sourceLocationTracker.ts @@ -94,6 +94,21 @@ export class SourceLocationTracker { return map } + async getValidSourceLocationFromVMTraceIndexFromCache (address: string, vmtraceStepIndex: number, contracts: any, cache: Map) { + const amountOfSources = this.getTotalAmountOfSources(address, contracts) + let map: Record = { file: -1 } + /* + (map.file === -1) this indicates that it isn't associated with a known source code + (map.file > amountOfSources - 1) this indicates the current file index exceed the total number of files. + this happens when generated sources should not be considered. + */ + while (vmtraceStepIndex >= 0 && (map.file === -1 || map.file > amountOfSources - 1)) { + map = cache[vmtraceStepIndex] + vmtraceStepIndex = vmtraceStepIndex - 1 + } + return map + } + clearCache () { this.sourceMapByAddress = {} } 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 f7135f74bb..2a1be745d1 100644 --- a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx @@ -158,7 +158,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => { return { ...prevState, sourceLocationStatus: '' } }) await debuggerModule.discardHighlight() - await debuggerModule.highlight(lineColumnPos, path) + await debuggerModule.highlight(lineColumnPos, path, rawLocation) } } }) diff --git a/libs/remix-ui/debugger-ui/src/lib/idebugger-api.ts b/libs/remix-ui/debugger-ui/src/lib/idebugger-api.ts index 3b3fa55d11..c0065558c9 100644 --- a/libs/remix-ui/debugger-ui/src/lib/idebugger-api.ts +++ b/libs/remix-ui/debugger-ui/src/lib/idebugger-api.ts @@ -44,7 +44,7 @@ export interface IDebuggerApi { onEditorContentChanged: (listener: onEditorContentChanged) => void onEnvChanged: (listener: onEnvChangedListener) => void discardHighlight: () => Promise - highlight: (lineColumnPos: LineColumnLocation, path: string) => Promise + highlight: (lineColumnPos: LineColumnLocation, path: string, rawLocation: any) => Promise fetchContractAndCompile: (address: string, currentReceipt: TransactionReceipt) => Promise getFile: (path: string) => Promise setFile: (path: string, content: string) => Promise