Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/remix-ide/src/app/compiler/compiler-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { canUseWorker, urlFromVersion } from './compiler-utils'
import { Compiler } from '@remix-project/remix-solidity'
import CompilerAbstract from './compiler-abstract'

export const compile = async (compilationTargets, settings) => {
export const compile = async (compilationTargets, settings, contentResolverCallback) => {
const res = await (() => {
return new Promise((resolve, reject) => {
const compiler = new Compiler(() => {})
const compiler = new Compiler(contentResolverCallback)
compiler.set('evmVersion', settings.evmVersion)
compiler.set('optimize', settings.optimize)
compiler.set('language', settings.language)
Expand Down
7 changes: 6 additions & 1 deletion apps/remix-ide/src/app/compiler/compiler-imports.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const profile = {
name: 'contentImport',
displayName: 'content import',
version: packageJson.version,
methods: ['resolve', 'resolveAndSave']
methods: ['resolve', 'resolveAndSave', 'isExternalUrl']
}

module.exports = class CompilerImports extends Plugin {
Expand Down Expand Up @@ -105,6 +105,11 @@ module.exports = class CompilerImports extends Plugin {
return /^([^/]+)/.exec(url)
}

isExternalUrl (url) {
const handlers = this.handlers()
return handlers.some(handler => handler.match.exec(url))
}

/**
* resolve the content of @arg url. This only resolves external URLs.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,14 @@ export default class FetchAndCompile extends Plugin {
if (url.includes('ipfs')) {
const stdUrl = `ipfs://${url.split('/')[2]}`
const source = await this.call('contentImport', 'resolve', stdUrl)
file = file.replace('browser/', '') // should be fixed in the remix IDE end.
const path = `${targetPath}/${name}/${contractAddress}/${file}`
await this.call('fileManager', 'setFile', path, source.content)
compilationTargets[path] = { content: source.content }
if (await this.call('contentImport', 'isExternalUrl', file)) {
// nothing to do, the compiler callback will handle those
} else {
file = file.replace('browser/', '') // should be fixed in the remix IDE end.
const path = `${targetPath}/${name}/${contractAddress}/${file}`
await this.call('fileManager', 'setFile', path, source.content)
compilationTargets[path] = { content: source.content }
}
break
}
}
Expand All @@ -111,7 +115,10 @@ export default class FetchAndCompile extends Plugin {
}
try {
setTimeout(_ => this.emit('compiling', settings), 0)
const compData = await compile(compilationTargets, settings)
const compData = await compile(
compilationTargets,
settings,
(url, cb) => this.call('contentImport', 'resolveAndSave', url).then((result) => cb(null, result)).catch((error) => cb(error.message)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like callback hell here ^^.
When you've to a callback in a promise in a callback, you start loosing people XD

compilersartefacts.addResolvedContract(contractAddress, compData)
return compData
} catch (e) {
Expand Down
4 changes: 2 additions & 2 deletions apps/remix-ide/src/app/tabs/debugger-tab.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ class DebuggerTab extends ViewPlugin {

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())
const targetAddress = target || receipt.contractAddress || receipt.to
return this.call('fetchAndCompile', 'resolve', targetAddress, 'browser/.debug', this.blockchain.web3())
}

// debugger () {
Expand Down
13 changes: 8 additions & 5 deletions libs/remix-debug/src/code/breakpointManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ export class BreakpointManager {
solidityProxy
breakpoints
locationToRowConverter
previousLine


/**
* constructor
*
Expand Down Expand Up @@ -92,22 +91,26 @@ export class BreakpointManager {
let previousSourceLocation
let currentStep = fromStep + direction
let lineHadBreakpoint = false
let initialLine
while (currentStep > 0 && currentStep < trace.length) {
try {
previousSourceLocation = sourceLocation
sourceLocation = await this.callTree.extractValidSourceLocation(currentStep)
} catch (e) {
return console.log('cannot jump to breakpoint ' + e)
console.log('cannot jump to breakpoint ' + e)
currentStep += direction
continue
}
const lineColumn = await this.locationToRowConverter(sourceLocation)
if (this.previousLine !== lineColumn.start.line) {
if (!initialLine) initialLine = lineColumn

if (initialLine.start.line !== lineColumn.start.line) {
if (direction === -1 && lineHadBreakpoint) { // TODO : improve this when we will build the correct structure before hand
lineHadBreakpoint = false
if (this.hitLine(currentStep + 1, previousSourceLocation, sourceLocation, trace)) {
return
}
}
this.previousLine = lineColumn.start.line
if (this.hasBreakpointAtLine(sourceLocation.file, lineColumn.start.line)) {
lineHadBreakpoint = true
if (direction === 1 && this.hitLine(currentStep, sourceLocation, previousSourceLocation, trace)) {
Expand Down
2 changes: 1 addition & 1 deletion libs/remix-debug/src/debugger/debugger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export class Debugger {
}
}
var lineColumnPos = this.offsetToLineColumnConverter.offsetToLineColumn(rawLocation, rawLocation.file, sources, astSources)
this.event.trigger('newSourceLocation', [lineColumnPos, rawLocation, generatedSources])
this.event.trigger('newSourceLocation', [lineColumnPos, rawLocation, generatedSources, address])
} else {
this.event.trigger('newSourceLocation', [null])
}
Expand Down
48 changes: 27 additions & 21 deletions libs/remix-debug/src/solidity-decoder/internalCallTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ async function buildTree (tree, step, scopeId, isExternalCall, isCreation) {
// 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) {
includeVariableDeclaration(tree, step, sourceLocation, scopeId, newLocation, previousSourceLocation)
await includeVariableDeclaration(tree, step, sourceLocation, scopeId, newLocation, previousSourceLocation)
}
previousSourceLocation = sourceLocation
step++
Expand All @@ -249,32 +249,36 @@ async function includeVariableDeclaration (tree, step, sourceLocation, scopeId,
const contractObj = await tree.solidityProxy.contractObjectAt(step)
let states = null
const generatedSources = getGeneratedSources(tree, scopeId, contractObj)

const variableDeclaration = resolveVariableDeclaration(tree, sourceLocation, generatedSources)
const variableDeclarations = resolveVariableDeclaration(tree, sourceLocation, generatedSources)
// 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.
if (variableDeclaration && !tree.scopes[scopeId].locals[variableDeclaration.name]) {
try {
const stack = tree.traceManager.getStackAt(step)
// 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()
var location = extractLocationFromAstVariable(variableDeclaration)
location = location === 'default' ? 'storage' : location
// we push the new local variable in our tree
tree.scopes[scopeId].locals[variableDeclaration.name] = {
name: variableDeclaration.name,
type: parseType(variableDeclaration.typeDescriptions.typeString, states, contractObj.name, location),
stackDepth: stack.length,
sourceLocation: sourceLocation
if (variableDeclarations && variableDeclarations.length) {
for (const variableDeclaration of variableDeclarations) {
if (variableDeclaration && !tree.scopes[scopeId].locals[variableDeclaration.name]) {
try {
const stack = tree.traceManager.getStackAt(step)
// 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()
var location = extractLocationFromAstVariable(variableDeclaration)
location = location === 'default' ? 'storage' : location
// we push the new local variable in our tree
tree.scopes[scopeId].locals[variableDeclaration.name] = {
name: variableDeclaration.name,
type: parseType(variableDeclaration.typeDescriptions.typeString, states, contractObj.name, location),
stackDepth: stack.length,
sourceLocation: sourceLocation
}
}
} catch (error) {
console.log(error)
}
}
} catch (error) {
console.log(error)
}
}

// we check here if we are at the beginning inside a new function.
// if that is the case, we have to add to locals tree the inputs and output params
const functionDefinition = resolveFunctionDefinition(tree, previousSourceLocation, generatedSources)
Expand Down Expand Up @@ -351,8 +355,10 @@ function extractVariableDeclarations (ast, astWalker) {
const ret = {}
astWalker.walkFull(ast, (node) => {
if (node.nodeType === 'VariableDeclaration' || node.nodeType === 'YulVariableDeclaration') {
ret[node.src] = node
ret[node.src] = [node]
}
const hasChild = node.initialValue && (node.nodeType === 'VariableDeclarationStatement' || node.nodeType === 'YulVariableDeclarationStatement')
if (hasChild) ret[node.initialValue.src] = node.declarations
})
return ret
}
Expand Down
2 changes: 1 addition & 1 deletion libs/remix-debug/src/trace/traceHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function resolveCalledAddress (vmTraceIndex, trace) {
}

export function isCallInstruction (step) {
return step.op === 'CALL' || step.op === 'CALLCODE' || step.op === 'CREATE' || step.op === 'DELEGATECALL'
return ['CALL', 'STATICCALL', 'CALLCODE', 'CREATE', 'DELEGATECALL'].includes(step.op)
}

export function isCreateInstruction (step) {
Expand Down
8 changes: 4 additions & 4 deletions libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,11 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
})
})

debuggerInstance.event.register('newSourceLocation', async (lineColumnPos, rawLocation, generatedSources) => {
debuggerInstance.event.register('newSourceLocation', async (lineColumnPos, rawLocation, generatedSources, address) => {
if (!lineColumnPos) return
const contracts = await debuggerModule.fetchContractAndCompile(
currentReceipt.contractAddress || currentReceipt.to,
address || currentReceipt.contractAddress || currentReceipt.to,
currentReceipt)

if (contracts) {
let path = contracts.getSourceName(rawLocation.file)
if (!path) {
Expand Down Expand Up @@ -152,7 +151,8 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
offsetToLineColumnConverter: debuggerModule.offsetToLineColumnConverter,
compilationResult: async (address) => {
try {
return await debuggerModule.fetchContractAndCompile(address, currentReceipt)
const ret = await debuggerModule.fetchContractAndCompile(address, currentReceipt)
return ret
} catch (e) {
console.error(e)
}
Expand Down