diff --git a/libs/remix-core-plugin/src/lib/compiler-fetch-and-compile.ts b/libs/remix-core-plugin/src/lib/compiler-fetch-and-compile.ts index 769e679ad4..b9cffb64a6 100644 --- a/libs/remix-core-plugin/src/lib/compiler-fetch-and-compile.ts +++ b/libs/remix-core-plugin/src/lib/compiler-fetch-and-compile.ts @@ -57,8 +57,9 @@ export class FetchAndCompile extends Plugin { optimize: UUPSOptimize, runs: UUPSRuns } + const proxyUrl = 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.0/contracts/proxy/ERC1967/ERC1967Proxy.sol' const compilationTargets = { - 'proxy.sol': { content: 'import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.0/contracts/proxy/ERC1967/ERC1967Proxy.sol";' } + 'proxy.sol': { content: `import "${proxyUrl}";` } } const compData = await compile( compilationTargets, diff --git a/libs/remix-debug/src/Ethdebugger.ts b/libs/remix-debug/src/Ethdebugger.ts index 071ff4c74e..483fc9bfc7 100644 --- a/libs/remix-debug/src/Ethdebugger.ts +++ b/libs/remix-debug/src/Ethdebugger.ts @@ -44,7 +44,11 @@ export class Ethdebugger { this.event = new EventManager() this.traceManager = new TraceManager({ web3: this.web3 }) this.codeManager = new CodeManager(this.traceManager) - this.solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: this.traceManager.getCurrentCalledAddressAt.bind(this.traceManager), getCode: this.codeManager.getCode.bind(this.codeManager) }) + this.solidityProxy = new SolidityProxy({ + getCurrentCalledAddressAt: this.traceManager.getCurrentCalledAddressAt.bind(this.traceManager), + getCode: this.codeManager.getCode.bind(this.codeManager), + compilationResult: this.compilationResult + }) this.storageResolver = null const includeLocalVariables = true @@ -59,7 +63,11 @@ export class Ethdebugger { setManagers () { this.traceManager = new TraceManager({ web3: this.web3 }) this.codeManager = new CodeManager(this.traceManager) - this.solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: this.traceManager.getCurrentCalledAddressAt.bind(this.traceManager), getCode: this.codeManager.getCode.bind(this.codeManager) }) + this.solidityProxy = new SolidityProxy({ + getCurrentCalledAddressAt: this.traceManager.getCurrentCalledAddressAt.bind(this.traceManager), + getCode: this.codeManager.getCode.bind(this.codeManager), + compilationResult: this.compilationResult + }) this.storageResolver = null const includeLocalVariables = true @@ -75,20 +83,19 @@ export class Ethdebugger { this.codeManager.resolveStep(index, this.tx) } - setCompilationResult (compilationResult) { - this.solidityProxy.reset((compilationResult && compilationResult.data) || {}, (compilationResult && compilationResult.source && compilationResult.source.sources) || {}) - } - async sourceLocationFromVMTraceIndex (address, stepIndex) { - return this.callTree.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, stepIndex, this.solidityProxy.contracts) + const compilationResult = await this.compilationResult(address) + return this.callTree.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, stepIndex, compilationResult.data.contracts) } async getValidSourceLocationFromVMTraceIndex (address, stepIndex) { - return this.callTree.sourceLocationTracker.getValidSourceLocationFromVMTraceIndex(address, stepIndex, this.solidityProxy.contracts) + const compilationResult = await this.compilationResult(address) + return this.callTree.sourceLocationTracker.getValidSourceLocationFromVMTraceIndex(address, stepIndex, compilationResult.data.contracts) } async sourceLocationFromInstructionIndex (address, instIndex, callback) { - return this.callTree.sourceLocationTracker.getSourceLocationFromInstructionIndex(address, instIndex, this.solidityProxy.contracts) + const compilationResult = await this.compilationResult(address) + return this.callTree.sourceLocationTracker.getSourceLocationFromInstructionIndex(address, instIndex, compilationResult.data.contracts) } /* breakpoint */ @@ -145,7 +152,7 @@ export class Ethdebugger { /* decode state */ async extractStateAt (step) { - return this.solidityProxy.extractStateVariablesAt(step) + return await this.solidityProxy.extractStateVariablesAt(step) } async decodeStateAt (step, stateVars, callback?) { @@ -184,7 +191,6 @@ export class Ethdebugger { this.tx = tx await this.traceManager.resolveTrace(tx) - this.setCompilationResult(await this.compilationResult(tx.to)) this.event.trigger('newTraceLoaded', [this.traceManager.trace]) if (this.breakpointManager && this.breakpointManager.hasBreakpoint()) { this.breakpointManager.jumpNextBreakpoint(false) diff --git a/libs/remix-debug/src/code/breakpointManager.ts b/libs/remix-debug/src/code/breakpointManager.ts index 252eed4596..abaec65332 100644 --- a/libs/remix-debug/src/code/breakpointManager.ts +++ b/libs/remix-debug/src/code/breakpointManager.ts @@ -88,6 +88,7 @@ export class BreakpointManager { this.event.trigger('locatingBreakpoint', []) let sourceLocation let lineColumn + let contractAddress let previousSourceLocation let currentStep = fromStep + direction let lineHadBreakpoint = false @@ -98,6 +99,7 @@ export class BreakpointManager { const stepInfo = this.callTree.locationAndOpcodePerVMTraceIndex[currentStep] sourceLocation = stepInfo.sourceLocation lineColumn = stepInfo.lineColumnPos + contractAddress = stepInfo.contractAddress } catch (e) { console.log('cannot jump to breakpoint ' + e) currentStep += direction @@ -112,7 +114,7 @@ export class BreakpointManager { return } } - if (this.hasBreakpointAtLine(sourceLocation.file, lineColumn.start.line)) { + if (await this.hasBreakpointAtLine(sourceLocation.file, lineColumn.start.line, contractAddress)) { lineHadBreakpoint = true if (this.hitLine(currentStep, sourceLocation, previousSourceLocation, trace)) { return @@ -139,8 +141,9 @@ export class BreakpointManager { * @param {Int} line - line number where looking for breakpoint * @return {Bool} return true if the given @arg fileIndex @arg line refers to a breakpoint */ - hasBreakpointAtLine (fileIndex, line) { - const filename = this.solidityProxy.fileNameFromIndex(fileIndex) + async hasBreakpointAtLine (fileIndex, line, contractAddress) { + const compResult = await this.solidityProxy.compilationResult(contractAddress) + const filename = Object.keys(compResult.data.contracts)[fileIndex] if (!(filename && this.breakpoints[filename])) { return false } diff --git a/libs/remix-debug/src/debugger/solidityState.ts b/libs/remix-debug/src/debugger/solidityState.ts index 43a8349c85..237be4e7da 100644 --- a/libs/remix-debug/src/debugger/solidityState.ts +++ b/libs/remix-debug/src/debugger/solidityState.ts @@ -32,10 +32,7 @@ export class DebuggerSolidityState { } if (this.stepManager.currentStepIndex !== index) return - if (!this.solidityProxy.loaded()) { - return this.event.trigger('solidityStateMessage', ['invalid step index']) - } - + if (!this.storageResolver) { return } diff --git a/libs/remix-debug/src/debugger/stepManager.ts b/libs/remix-debug/src/debugger/stepManager.ts index 004d1bc3f3..8c0e6512d5 100644 --- a/libs/remix-debug/src/debugger/stepManager.ts +++ b/libs/remix-debug/src/debugger/stepManager.ts @@ -34,17 +34,35 @@ export class DebuggerStepManager { this.traceLength = newLength this.codeTraceLength = this.calculateCodeLength() } - setTimeout(() => { - this.jumpTo(0) // wait for the ui to render - }, 500) - }) }) + this.debugger.callTree.event.register('callTreeBuildFailed', () => { + setTimeout(() => { + this.jumpTo(0) + }, 500) + }) + + this.debugger.callTree.event.register('callTreeNotReady', () => { + setTimeout(() => { + this.jumpTo(0) + }, 500) + }) + + this.debugger.callTree.event.register('noCallTreeAvailable', () => { + setTimeout(() => { + this.jumpTo(0) + }, 500) + }) + this.debugger.callTree.event.register('callTreeReady', () => { if (this.debugger.callTree.functionCallStack.length) { setTimeout(() => { - this.jumpTo(this.debugger.callTree.functionCallStack[0]) // wait for the ui to be render + this.jumpTo(this.debugger.callTree.functionCallStack[0]) + }, 500) + } else { + setTimeout(() => { + this.jumpTo(0) }, 500) } }) diff --git a/libs/remix-debug/src/solidity-decoder/internalCallTree.ts b/libs/remix-debug/src/solidity-decoder/internalCallTree.ts index 20a619174e..c194f5640c 100644 --- a/libs/remix-debug/src/solidity-decoder/internalCallTree.ts +++ b/libs/remix-debug/src/solidity-decoder/internalCallTree.ts @@ -67,20 +67,21 @@ export class InternalCallTree { this.traceManager = traceManager this.offsetToLineColumnConverter = offsetToLineColumnConverter this.sourceLocationTracker = new SourceLocationTracker(codeManager, { debugWithGeneratedSources: opts.debugWithGeneratedSources }) - debuggerEvent.register('newTraceLoaded', (trace) => { + debuggerEvent.register('newTraceLoaded', async (trace) => { const time = Date.now() this.reset() - if (!this.solidityProxy.loaded()) { - this.event.trigger('callTreeBuildFailed', ['compilation result not loaded. Cannot build internal call tree']) - } else { - // each recursive call to buildTree represent a new context (either call, delegatecall, internal function) - const calledAddress = traceManager.getCurrentCalledAddressAt(0) - const isCreation = isContractCreation(calledAddress) + // each recursive call to buildTree represent a new context (either call, delegatecall, internal function) + const calledAddress = traceManager.getCurrentCalledAddressAt(0) + const isCreation = isContractCreation(calledAddress) - const scopeId = '1' - this.scopeStarts[0] = scopeId - this.scopes[scopeId] = { firstStep: 0, locals: {}, isCreation, gasCost: 0 } + const scopeId = '1' + this.scopeStarts[0] = scopeId + this.scopes[scopeId] = { firstStep: 0, locals: {}, isCreation, gasCost: 0 } + const compResult = await this.solidityProxy.compilationResult(calledAddress) + if (!compResult) { + this.event.trigger('noCallTreeAvailable', []) + } else { buildTree(this, 0, scopeId, isCreation).then((result) => { if (result.error) { this.event.trigger('callTreeBuildFailed', [result.error]) @@ -182,7 +183,8 @@ export class InternalCallTree { async extractSourceLocation (step: number, address?: string) { try { if (!address) address = this.traceManager.getCurrentCalledAddressAt(step) - return await this.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, step, this.solidityProxy.contracts) + const compilationResult = await this.solidityProxy.compilationResult(address) + return await this.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, step, compilationResult.data.contracts) } catch (error) { throw new Error('InternalCallTree - Cannot retrieve sourcelocation for step ' + step + ' ' + error) } @@ -191,7 +193,8 @@ export class InternalCallTree { async extractValidSourceLocation (step: number, address?: string) { try { if (!address) address = this.traceManager.getCurrentCalledAddressAt(step) - return await this.sourceLocationTracker.getValidSourceLocationFromVMTraceIndex(address, step, this.solidityProxy.contracts) + const compilationResult = await this.solidityProxy.compilationResult(address) + return await this.sourceLocationTracker.getValidSourceLocationFromVMTraceIndex(address, step, compilationResult.data.contracts) } catch (error) { throw new Error('InternalCallTree - Cannot retrieve valid sourcelocation for step ' + step + ' ' + error) } @@ -216,7 +219,8 @@ export class InternalCallTree { async function buildTree (tree, step, scopeId, isCreation, functionDefinition?, contractObj?, sourceLocation?, validSourceLocation?) { let subScope = 1 if (functionDefinition) { - await registerFunctionParameters(tree, functionDefinition, step, scopeId, contractObj, validSourceLocation) + const address = tree.traceManager.getCurrentCalledAddressAt(step) + await registerFunctionParameters(tree, functionDefinition, step, scopeId, contractObj, validSourceLocation, address) } function callDepthChange (step, trace) { @@ -238,10 +242,13 @@ async function buildTree (tree, step, scopeId, isCreation, functionDefinition?, let currentSourceLocation = sourceLocation || { start: -1, length: -1, file: -1, jump: '-' } let previousSourceLocation = currentSourceLocation let previousValidSourceLocation = validSourceLocation || currentSourceLocation + let compilationResult + let currentAddress = '' while (step < tree.traceManager.trace.length) { let sourceLocation let validSourceLocation let address + try { address = tree.traceManager.getCurrentCalledAddressAt(step) sourceLocation = await tree.extractSourceLocation(step, address) @@ -250,8 +257,11 @@ async function buildTree (tree, step, scopeId, isCreation, functionDefinition?, tree.reducedTrace.push(step) currentSourceLocation = sourceLocation } - - const amountOfSources = tree.sourceLocationTracker.getTotalAmountOfSources(address, tree.solidityProxy.contracts) + if (currentAddress !== address) { + compilationResult = await tree.solidityProxy.compilationResult(address) + currentAddress = address + } + const amountOfSources = tree.sourceLocationTracker.getTotalAmountOfSources(address, compilationResult.data.contracts) if (tree.sourceLocationTracker.isInvalidSourceLocation(currentSourceLocation, amountOfSources)) { // file is -1 or greater than amount of sources validSourceLocation = previousValidSourceLocation } else @@ -274,8 +284,8 @@ async function buildTree (tree, step, scopeId, isCreation, functionDefinition?, if (tree.offsetToLineColumnConverter) { try { const generatedSources = tree.sourceLocationTracker.getGeneratedSourcesFromAddress(address) - const astSources = Object.assign({}, tree.solidityProxy.sources) - const sources = Object.assign({}, tree.solidityProxy.sourcesCode) + const astSources = Object.assign({}, compilationResult.data.sources) + const sources = Object.assign({}, compilationResult.source.sources) if (generatedSources) { for (const genSource of generatedSources) { astSources[genSource.name] = { id: genSource.id, ast: genSource.ast } @@ -298,12 +308,12 @@ async function buildTree (tree, step, scopeId, isCreation, functionDefinition?, } } - tree.locationAndOpcodePerVMTraceIndex[step] = { sourceLocation, stepDetail, lineColumnPos } + tree.locationAndOpcodePerVMTraceIndex[step] = { sourceLocation, stepDetail, lineColumnPos, contractAddress: address } tree.scopes[scopeId].gasCost += stepDetail.gasCost const contractObj = await tree.solidityProxy.contractObjectAtAddress(address) const generatedSources = getGeneratedSources(tree, scopeId, contractObj) - const functionDefinition = resolveFunctionDefinition(tree, sourceLocation, generatedSources) + const functionDefinition = await resolveFunctionDefinition(tree, sourceLocation, generatedSources, address) const isInternalTxInstrn = isCallInstruction(stepDetail) const isCreateInstrn = isCreateInstruction(stepDetail) @@ -329,7 +339,7 @@ async function buildTree (tree, step, scopeId, isCreation, functionDefinition?, tree.constructorsStartExecution[tree.pendingConstructorId] = tree.pendingConstructorExecutionAt tree.pendingConstructorExecutionAt = -1 tree.pendingConstructorId = -1 - await registerFunctionParameters(tree, tree.pendingConstructor, step, newScopeId, contractObj, previousValidSourceLocation) + await registerFunctionParameters(tree, tree.pendingConstructor, step, newScopeId, contractObj, previousValidSourceLocation, address) tree.pendingConstructor = null } const externalCallResult = await buildTree(tree, nextStep, newScopeId, isCreateInstrn, functionDefinition, contractObj, sourceLocation, validSourceLocation) @@ -350,7 +360,7 @@ async function buildTree (tree, step, scopeId, isCreation, functionDefinition?, // if not, we are in the current scope. // We check in `includeVariableDeclaration` if there is a new local variable in scope for this specific `step` if (tree.includeLocalVariables) { - await includeVariableDeclaration(tree, step, sourceLocation, scopeId, contractObj, generatedSources) + await includeVariableDeclaration(tree, step, sourceLocation, scopeId, contractObj, generatedSources, address) } previousSourceLocation = sourceLocation previousValidSourceLocation = validSourceLocation @@ -372,14 +382,14 @@ function getGeneratedSources (tree, scopeId, contractObj) { return null } -async function registerFunctionParameters (tree, functionDefinition, step, scopeId, contractObj, sourceLocation) { +async function registerFunctionParameters (tree, functionDefinition, step, scopeId, contractObj, sourceLocation, address) { tree.functionCallStack.push(step) const functionDefinitionAndInputs = { functionDefinition, inputs: [] } // means: the previous location was a function definition && JUMPDEST // => we are at the beginning of the function and input/output are setup try { const stack = tree.traceManager.getStackAt(step) - const states = tree.solidityProxy.extractStatesDefinitions() + const states = await tree.solidityProxy.extractStatesDefinitions(address) if (functionDefinition.parameters) { const inputs = functionDefinition.parameters const outputs = functionDefinition.returnParameters @@ -397,9 +407,9 @@ async function registerFunctionParameters (tree, functionDefinition, step, scope tree.functionDefinitionsByScope[scopeId] = functionDefinitionAndInputs } -async function includeVariableDeclaration (tree, step, sourceLocation, scopeId, contractObj, generatedSources) { +async function includeVariableDeclaration (tree, step, sourceLocation, scopeId, contractObj, generatedSources, address) { let states = null - const variableDeclarations = resolveVariableDeclaration(tree, sourceLocation, generatedSources) + const variableDeclarations = await resolveVariableDeclaration(tree, sourceLocation, generatedSources, address) // using the vm trace step, the current source location and the ast, // we check if the current vm trace step target a new ast node of type VariableDeclaration // that way we know that there is a new local variable from here. @@ -411,7 +421,7 @@ async function includeVariableDeclaration (tree, step, sourceLocation, scopeId, // the stack length at this point is where the value of the new local variable will be stored. // so, either this is the direct value, or the offset in memory. That depends on the type. if (variableDeclaration.name !== '') { - states = tree.solidityProxy.extractStatesDefinitions() + states = await tree.solidityProxy.extractStatesDefinitions(address) let location = extractLocationFromAstVariable(variableDeclaration) location = location === 'default' ? 'storage' : location // we push the new local variable in our tree @@ -434,9 +444,9 @@ async function includeVariableDeclaration (tree, step, sourceLocation, scopeId, // this extract all the variable declaration for a given ast and file // and keep this in a cache -function resolveVariableDeclaration (tree, sourceLocation, generatedSources) { +async function resolveVariableDeclaration (tree, sourceLocation, generatedSources, address) { if (!tree.variableDeclarationByFile[sourceLocation.file]) { - const ast = tree.solidityProxy.ast(sourceLocation, generatedSources) + const ast = await tree.solidityProxy.ast(sourceLocation, generatedSources, address) if (ast) { tree.variableDeclarationByFile[sourceLocation.file] = extractVariableDeclarations(ast, tree.astWalker) } else { @@ -448,9 +458,9 @@ function resolveVariableDeclaration (tree, sourceLocation, generatedSources) { // this extract all the function definition for a given ast and file // and keep this in a cache -function resolveFunctionDefinition (tree, sourceLocation, generatedSources) { +async function resolveFunctionDefinition (tree, sourceLocation, generatedSources, address) { if (!tree.functionDefinitionByFile[sourceLocation.file]) { - const ast = tree.solidityProxy.ast(sourceLocation, generatedSources) + const ast = await tree.solidityProxy.ast(sourceLocation, generatedSources, address) if (ast) { tree.functionDefinitionByFile[sourceLocation.file] = extractFunctionDefinitions(ast, tree.astWalker) } else { diff --git a/libs/remix-debug/src/solidity-decoder/solidityProxy.ts b/libs/remix-debug/src/solidity-decoder/solidityProxy.ts index 0ec4029020..92a8712565 100644 --- a/libs/remix-debug/src/solidity-decoder/solidityProxy.ts +++ b/libs/remix-debug/src/solidity-decoder/solidityProxy.ts @@ -13,32 +13,11 @@ export class SolidityProxy { compilationResult sourcesCode - constructor ({ getCurrentCalledAddressAt, getCode }) { + constructor ({ getCurrentCalledAddressAt, getCode, compilationResult }) { this.cache = new Cache() - this.reset({}) this.getCurrentCalledAddressAt = getCurrentCalledAddressAt this.getCode = getCode - } - - /** - * reset the cache and apply a new @arg compilationResult - * - * @param {Object} compilationResult - result os a compilatiion (diectly returned by the compiler) - */ - reset (compilationResult, sources?) { - this.sources = compilationResult.sources // ast - this.contracts = compilationResult.contracts - if (sources) this.sourcesCode = sources - this.cache.reset() - } - - /** - * check if the object has been properly loaded - * - * @return {Bool} - returns true if a compilation result has been applied - */ - loaded () { - return this.contracts !== undefined + this.compilationResult = compilationResult } /** @@ -63,7 +42,8 @@ export class SolidityProxy { return this.cache.contractObjectByAddress[address] } const code = await this.getCode(address) - const contract = contractObjectFromCode(this.contracts, code.bytecode, address) + const compilationResult = await this.compilationResult(address) + const contract = contractObjectFromCode(compilationResult.data.contracts, code.bytecode, address) this.cache.contractObjectByAddress[address] = contract return contract } @@ -74,14 +54,15 @@ export class SolidityProxy { * @param {String} contractName - name of the contract to retrieve state variables from * @return {Object} - returns state variables of @args contractName */ - extractStatesDefinitions () { - if (!this.cache.contractDeclarations) { - this.cache.contractDeclarations = extractContractDefinitions(this.sources) + async extractStatesDefinitions (address: string) { + const compilationResult = await this.compilationResult(address) + if (!this.cache.contractDeclarations[address]) { + this.cache.contractDeclarations[address] = extractContractDefinitions(compilationResult.data.sources) } - if (!this.cache.statesDefinitions) { - this.cache.statesDefinitions = extractStatesDefinitions(this.sources, this.cache.contractDeclarations) + if (!this.cache.statesDefinitions[address]) { + this.cache.statesDefinitions[address] = extractStatesDefinitions(compilationResult.data.sources, this.cache.contractDeclarations) } - return this.cache.statesDefinitions + return this.cache.statesDefinitions[address] } /** @@ -90,9 +71,10 @@ export class SolidityProxy { * @param {String} contractName - name of the contract to retrieve state variables from * @return {Object} - returns state variables of @args contractName */ - extractStateVariables (contractName) { + async extractStateVariables (contractName, address) { if (!this.cache.stateVariablesByContractName[contractName]) { - this.cache.stateVariablesByContractName[contractName] = extractStateVariables(contractName, this.sources) + const compilationResult = await this.compilationResult(address) + this.cache.stateVariablesByContractName[contractName] = extractStateVariables(contractName, compilationResult.data.sources) } return this.cache.stateVariablesByContractName[contractName] } @@ -103,9 +85,9 @@ export class SolidityProxy { * @param {Int} vmTraceIndex - index in the vm trave where to resolve the state variables * @return {Object} - returns state variables of @args vmTraceIndex */ - async extractStateVariablesAt (vmtraceIndex) { + async extractStateVariablesAt (vmtraceIndex, address) { const contract = await this.contractObjectAt(vmtraceIndex) - return this.extractStateVariables(contract.name) + return await this.extractStateVariables(contract.name, address) } /** @@ -114,14 +96,15 @@ export class SolidityProxy { * @param {Object} sourceLocation - source location containing the 'file' to retrieve the AST from * @return {Object} - AST of the current file */ - ast (sourceLocation, generatedSources) { - const file = this.fileNameFromIndex(sourceLocation.file) + async ast (sourceLocation, generatedSources, address) { + const compilationResult = await this.compilationResult(address) + const file = this.fileNameFromIndex(sourceLocation.file, compilationResult.data) if (!file && generatedSources && generatedSources.length) { for (const source of generatedSources) { if (source.id === sourceLocation.file) return source.ast } - } else if (this.sources[file]) { - return this.sources[file].ast + } else if (compilationResult.data.sources[file]) { + return compilationResult.data.sources[file].ast } return null } @@ -132,8 +115,8 @@ export class SolidityProxy { * @param {Int} index - index of the filename * @return {String} - filename */ - fileNameFromIndex (index) { - return Object.keys(this.contracts)[index] + fileNameFromIndex (index, compilationResult) { + return Object.keys(compilationResult.contracts)[index] } } @@ -163,7 +146,7 @@ class Cache { reset () { this.contractObjectByAddress = {} this.stateVariablesByContractName = {} - this.contractDeclarations = null - this.statesDefinitions = null + this.contractDeclarations = {} + this.statesDefinitions = {} } } diff --git a/libs/remix-debug/test/decoder/localsTests/calldata.ts b/libs/remix-debug/test/decoder/localsTests/calldata.ts index 2cab6ced8d..8728fad736 100644 --- a/libs/remix-debug/test/decoder/localsTests/calldata.ts +++ b/libs/remix-debug/test/decoder/localsTests/calldata.ts @@ -31,8 +31,11 @@ module.exports = async function (st, privateKey, contractBytecode, compilationRe var traceManager = new TraceManager({ web3 }) var codeManager = new CodeManager(traceManager) codeManager.clear() - var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) }) - solidityProxy.reset(compilationResult) + var solidityProxy = new SolidityProxy({ + getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), + getCode: codeManager.getCode.bind(codeManager), + compilationResult: () => compilationResult + }) var debuggerEvent = new EventManager() var callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true }) callTree.event.register('callTreeBuildFailed', (error) => { diff --git a/libs/remix-debug/test/decoder/localsTests/int.ts b/libs/remix-debug/test/decoder/localsTests/int.ts index c36a217df3..c91a535c41 100644 --- a/libs/remix-debug/test/decoder/localsTests/int.ts +++ b/libs/remix-debug/test/decoder/localsTests/int.ts @@ -25,8 +25,11 @@ module.exports = function (st, privateKey, contractBytecode, compilationResult, var traceManager = new TraceManager({ web3 }) var codeManager = new CodeManager(traceManager) codeManager.clear() - var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) }) - solidityProxy.reset(compilationResult) + var solidityProxy = new SolidityProxy({ + getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), + getCode: codeManager.getCode.bind(codeManager), + compilationResult: () => compilationResult + }) var debuggerEvent = new EventManager() const offsetToLineColumnConverter = { offsetToLineColumn: (rawLocation) => { diff --git a/libs/remix-debug/test/decoder/localsTests/misc.ts b/libs/remix-debug/test/decoder/localsTests/misc.ts index 6caaa01311..359b8b9874 100644 --- a/libs/remix-debug/test/decoder/localsTests/misc.ts +++ b/libs/remix-debug/test/decoder/localsTests/misc.ts @@ -23,8 +23,11 @@ module.exports = function (st, privateKey, contractBytecode, compilationResult) var traceManager = new TraceManager({ web3 }) var codeManager = new CodeManager(traceManager) codeManager.clear() - var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) }) - solidityProxy.reset(compilationResult) + var solidityProxy = new SolidityProxy({ + getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), + getCode: codeManager.getCode.bind(codeManager), + compilationResult: () => compilationResult + }) var debuggerEvent = new EventManager() var callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true }) callTree.event.register('callTreeBuildFailed', (error) => { diff --git a/libs/remix-debug/test/decoder/localsTests/misc2.ts b/libs/remix-debug/test/decoder/localsTests/misc2.ts index 813db7542a..52ef1f632f 100644 --- a/libs/remix-debug/test/decoder/localsTests/misc2.ts +++ b/libs/remix-debug/test/decoder/localsTests/misc2.ts @@ -23,8 +23,11 @@ module.exports = function (st, privateKey, contractBytecode, compilationResult) var traceManager = new TraceManager({ web3 }) var codeManager = new CodeManager(traceManager) codeManager.clear() - var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) }) - solidityProxy.reset(compilationResult) + var solidityProxy = new SolidityProxy({ + getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), + getCode: codeManager.getCode.bind(codeManager), + compilationResult: () => compilationResult + }) var debuggerEvent = new EventManager() var callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true }) callTree.event.register('callTreeBuildFailed', (error) => { diff --git a/libs/remix-debug/test/decoder/localsTests/structArray.ts b/libs/remix-debug/test/decoder/localsTests/structArray.ts index 725674ee8c..d7a82abdd0 100644 --- a/libs/remix-debug/test/decoder/localsTests/structArray.ts +++ b/libs/remix-debug/test/decoder/localsTests/structArray.ts @@ -23,8 +23,11 @@ module.exports = function (st, privateKey, contractBytecode, compilationResult) var traceManager = new TraceManager({ web3 }) var codeManager = new CodeManager(traceManager) codeManager.clear() - var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) }) - solidityProxy.reset(compilationResult) + var solidityProxy = new SolidityProxy({ + getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), + getCode: codeManager.getCode.bind(codeManager), + compilationResult: () => compilationResult + }) var debuggerEvent = new EventManager() var callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true }) callTree.event.register('callTreeBuildFailed', (error) => { diff --git a/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx b/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx index 0f0d76d29c..c2ece6a9bb 100644 --- a/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx +++ b/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx @@ -141,6 +141,7 @@ export const EditorUI = (props: EditorUIProps) => { const editorRef = useRef(null) const monacoRef = useRef(null) const currentFileRef = useRef('') + const currentUrlRef = useRef('') // const currentDecorations = useRef({ sourceAnnotationsPerFile: {}, markerPerFile: {} }) // decorations that are currently in use by the editor // const registeredDecorations = useRef({}) // registered decorations @@ -295,6 +296,8 @@ export const EditorUI = (props: EditorUIProps) => { useEffect(() => { if (!editorRef.current || !props.currentFile) return currentFileRef.current = props.currentFile + props.plugin.call('fileManager', 'getUrlFromPath', currentFileRef.current).then((url) => currentUrlRef.current = url.file) + const file = editorModelsState[props.currentFile] editorRef.current.setModel(file.model) editorRef.current.updateOptions({ readOnly: editorModelsState[props.currentFile].readOnly }) @@ -512,7 +515,7 @@ export const EditorUI = (props: EditorUIProps) => { const model = editorRef.current.getModel() if (model) { setCurrentBreakpoints(prevState => { - const currentFile = currentFileRef.current + const currentFile = currentUrlRef.current if (!prevState[currentFile]) prevState[currentFile] = {} const decoration = Object.keys(prevState[currentFile]).filter((line) => parseInt(line) === position.lineNumber) if (decoration.length) {