From 26d1da3d95a6a1bee8eecef03e618e99bd340dda Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Mon, 14 Dec 2020 15:21:52 +0530 Subject: [PATCH] source src updated --- .../src/source/offsetToLineColumnConverter.ts | 50 ++--- .../src/source/sourceLocationTracker.ts | 183 +++++++++--------- .../src/source/sourceMappingDecoder.ts | 83 ++++---- 3 files changed, 156 insertions(+), 160 deletions(-) diff --git a/libs/remix-debug/src/source/offsetToLineColumnConverter.ts b/libs/remix-debug/src/source/offsetToLineColumnConverter.ts index 5bf63774b7..ac943d514c 100644 --- a/libs/remix-debug/src/source/offsetToLineColumnConverter.ts +++ b/libs/remix-debug/src/source/offsetToLineColumnConverter.ts @@ -1,33 +1,37 @@ 'use strict' const SourceMappingDecoder = require('./sourceMappingDecoder') -function offsetToColumnConverter (compilerEvent) { - this.lineBreakPositionsByContent = {} - this.sourceMappingDecoder = new SourceMappingDecoder() - if (compilerEvent) { - compilerEvent.register('compilationFinished', (success, data, source) => { - this.clear() - }) +export class OffsetToColumnConverter { + + lineBreakPositionsByContent + sourceMappingDecoder + + constructor(compilerEvent) { + this.lineBreakPositionsByContent = {} + this.sourceMappingDecoder = new SourceMappingDecoder() + if (compilerEvent) { + compilerEvent.register('compilationFinished', (success, data, source) => { + this.clear() + }) + } } -} -offsetToColumnConverter.prototype.offsetToLineColumn = function (rawLocation, file, sources, asts) { - if (!this.lineBreakPositionsByContent[file]) { - for (let filename in asts) { - const source = asts[filename] - // source id was string before. in newer versions it has been changed to an integer so we need to check the type here - if (typeof source.id === 'string') source.id = parseInt(source.id, 10) - if (source.id === file) { - this.lineBreakPositionsByContent[file] = this.sourceMappingDecoder.getLinebreakPositions(sources[filename].content) - break + offsetToLineColumn (rawLocation, file, sources, asts) { + if (!this.lineBreakPositionsByContent[file]) { + for (let filename in asts) { + const source = asts[filename] + // source id was string before. in newer versions it has been changed to an integer so we need to check the type here + if (typeof source.id === 'string') source.id = parseInt(source.id, 10) + if (source.id === file) { + this.lineBreakPositionsByContent[file] = this.sourceMappingDecoder.getLinebreakPositions(sources[filename].content) + break + } } } + return this.sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, this.lineBreakPositionsByContent[file]) } - return this.sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, this.lineBreakPositionsByContent[file]) -} -offsetToColumnConverter.prototype.clear = function () { - this.lineBreakPositionsByContent = {} + clear () { + this.lineBreakPositionsByContent = {} + } } - -module.exports = offsetToColumnConverter diff --git a/libs/remix-debug/src/source/sourceLocationTracker.ts b/libs/remix-debug/src/source/sourceLocationTracker.ts index 349a6741cc..f491c0697b 100644 --- a/libs/remix-debug/src/source/sourceLocationTracker.ts +++ b/libs/remix-debug/src/source/sourceLocationTracker.ts @@ -9,106 +9,113 @@ const util = remixLib.util /** * Process the source code location for the current executing bytecode */ -function SourceLocationTracker (_codeManager, { debugWithGeneratedSources }) { - this.opts = { - debugWithGeneratedSources: debugWithGeneratedSources || false +export class SourceLocationTracker { + + opts + codeManager + event + sourceMappingDecoder + sourceMapByAddress + + constructor (_codeManager, { debugWithGeneratedSources }) { + this.opts = { + debugWithGeneratedSources: debugWithGeneratedSources || false + } + this.codeManager = _codeManager + this.event = new EventManager() + this.sourceMappingDecoder = new SourceMappingDecoder() + this.sourceMapByAddress = {} } - this.codeManager = _codeManager - this.event = new EventManager() - this.sourceMappingDecoder = new SourceMappingDecoder() - this.sourceMapByAddress = {} -} -/** - * Return the source location associated with the given @arg index (instruction index) - * - * @param {String} address - contract address from which the source location is retrieved - * @param {Int} index - index in the instruction list from where the source location is retrieved - * @param {Object} contractDetails - AST of compiled contracts - */ -SourceLocationTracker.prototype.getSourceLocationFromInstructionIndex = async function (address, index, contracts) { - const sourceMap = await extractSourceMap(this, this.codeManager, address, contracts) - return this.sourceMappingDecoder.atIndex(index, sourceMap.map) -} + /** + * Return the source location associated with the given @arg index (instruction index) + * + * @param {String} address - contract address from which the source location is retrieved + * @param {Int} index - index in the instruction list from where the source location is retrieved + * @param {Object} contractDetails - AST of compiled contracts + */ + async getSourceLocationFromInstructionIndex (address, index, contracts) { + const sourceMap = await this.extractSourceMap(this, this.codeManager, address, contracts) + return this.sourceMappingDecoder.atIndex(index, sourceMap['map']) + } -/** - * Return the source location associated with the given @arg vmTraceIndex - * - * @param {String} address - contract address from which the source location is retrieved - * @param {Int} vmtraceStepIndex - index of the current code in the vmtrace - * @param {Object} contractDetails - AST of compiled contracts - */ -SourceLocationTracker.prototype.getSourceLocationFromVMTraceIndex = async function (address, vmtraceStepIndex, contracts) { - const sourceMap = await extractSourceMap(this, this.codeManager, address, contracts) - const index = this.codeManager.getInstructionIndex(address, vmtraceStepIndex) - return this.sourceMappingDecoder.atIndex(index, sourceMap.map) -} + /** + * Return the source location associated with the given @arg vmTraceIndex + * + * @param {String} address - contract address from which the source location is retrieved + * @param {Int} vmtraceStepIndex - index of the current code in the vmtrace + * @param {Object} contractDetails - AST of compiled contracts + */ + async getSourceLocationFromVMTraceIndex (address, vmtraceStepIndex, contracts) { + const sourceMap = await this.extractSourceMap(this, this.codeManager, address, contracts) + const index = this.codeManager.getInstructionIndex(address, vmtraceStepIndex) + return this.sourceMappingDecoder.atIndex(index, sourceMap['map']) + } -/** - * Returns the generated sources from a specific @arg address - * - * @param {String} address - contract address from which has generated sources - * @param {Object} generatedSources - Object containing the sourceid, ast and the source code. - */ -SourceLocationTracker.prototype.getGeneratedSourcesFromAddress = function (address) { - if (!this.opts.debugWithGeneratedSources) return null - if (this.sourceMapByAddress[address]) return this.sourceMapByAddress[address].generatedSources - return null -} + /** + * Returns the generated sources from a specific @arg address + * + * @param {String} address - contract address from which has generated sources + * @param {Object} generatedSources - Object containing the sourceid, ast and the source code. + */ + getGeneratedSourcesFromAddress (address) { + if (!this.opts.debugWithGeneratedSources) return null + if (this.sourceMapByAddress[address]) return this.sourceMapByAddress[address].generatedSources + return null + } -/** - * Return a valid source location associated with the given @arg vmTraceIndex - * - * @param {String} address - contract address from which the source location is retrieved - * @param {Int} vmtraceStepIndex - index of the current code in the vmtrace - * @param {Object} contractDetails - AST of compiled contracts - */ -SourceLocationTracker.prototype.getValidSourceLocationFromVMTraceIndex = async function (address, vmtraceStepIndex, contracts) { - let map = { file: -1} - while (vmtraceStepIndex >= 0 && map.file === -1) { - map = await this.getSourceLocationFromVMTraceIndex(address, vmtraceStepIndex, contracts) - vmtraceStepIndex = vmtraceStepIndex - 1 + /** + * Return a valid source location associated with the given @arg vmTraceIndex + * + * @param {String} address - contract address from which the source location is retrieved + * @param {Int} vmtraceStepIndex - index of the current code in the vmtrace + * @param {Object} contractDetails - AST of compiled contracts + */ + async getValidSourceLocationFromVMTraceIndex (address, vmtraceStepIndex, contracts) { + let map = { file: -1} + while (vmtraceStepIndex >= 0 && map.file === -1) { + map = await this.getSourceLocationFromVMTraceIndex(address, vmtraceStepIndex, contracts) + vmtraceStepIndex = vmtraceStepIndex - 1 + } + return map } - return map -} -SourceLocationTracker.prototype.clearCache = function () { - this.sourceMapByAddress = {} -} + clearCache () { + this.sourceMapByAddress = {} + } -function getSourceMap (address, code, contracts) { - const isCreation = helper.isContractCreation(address) - let bytes - for (let file in contracts) { - for (let contract in contracts[file]) { - const bytecode = contracts[file][contract].evm.bytecode - const deployedBytecode = contracts[file][contract].evm.deployedBytecode - if (!deployedBytecode) continue + private getSourceMap (address, code, contracts) { + const isCreation = helper.isContractCreation(address) + let bytes + for (let file in contracts) { + for (let contract in contracts[file]) { + const bytecode = contracts[file][contract].evm.bytecode + const deployedBytecode = contracts[file][contract].evm.deployedBytecode + if (!deployedBytecode) continue - bytes = isCreation ? bytecode.object : deployedBytecode.object - if (util.compareByteCode(code, '0x' + bytes)) { - const generatedSources = isCreation ? bytecode.generatedSources : deployedBytecode.generatedSources - const map = isCreation ? bytecode.sourceMap : deployedBytecode.sourceMap - return { generatedSources, map } + bytes = isCreation ? bytecode.object : deployedBytecode.object + if (util.compareByteCode(code, '0x' + bytes)) { + const generatedSources = isCreation ? bytecode.generatedSources : deployedBytecode.generatedSources + const map = isCreation ? bytecode.sourceMap : deployedBytecode.sourceMap + return { generatedSources, map } + } } } + return null } - return null -} -function extractSourceMap (self, codeManager, address, contracts) { - return new Promise((resolve, reject) => { - if (self.sourceMapByAddress[address]) return resolve(self.sourceMapByAddress[address]) + private extractSourceMap (self, codeManager, address, contracts) { + return new Promise((resolve, reject) => { + if (self.sourceMapByAddress[address]) return resolve(self.sourceMapByAddress[address]) - codeManager.getCode(address).then((result) => { - const sourceMap = getSourceMap(address, result.bytecode, contracts) - if (sourceMap) { - if (!helper.isContractCreation(address)) self.sourceMapByAddress[address] = sourceMap - return resolve(sourceMap) - } - reject('no sourcemap associated with the code ' + address) - }).catch(reject) - }) + codeManager.getCode(address).then((result) => { + const sourceMap = this.getSourceMap(address, result.bytecode, contracts) + if (sourceMap) { + if (!helper.isContractCreation(address)) self.sourceMapByAddress[address] = sourceMap + return resolve(sourceMap) + } + reject('no sourcemap associated with the code ' + address) + }).catch(reject) + }) + } } - -module.exports = SourceLocationTracker diff --git a/libs/remix-debug/src/source/sourceMappingDecoder.ts b/libs/remix-debug/src/source/sourceMappingDecoder.ts index 988471823d..90762d07a2 100644 --- a/libs/remix-debug/src/source/sourceMappingDecoder.ts +++ b/libs/remix-debug/src/source/sourceMappingDecoder.ts @@ -5,28 +5,8 @@ const util = remixLib.util /** * Decompress the source mapping given by solc-bin.js + * s:l:f:j */ -function SourceMappingDecoder () { - // s:l:f:j -} - -/** - * get a list of nodes that are at the given @arg position - * - * @param {String} astNodeType - type of node to return - * @param {Int} position - cursor position - * @return {Object} ast object given by the compiler - */ -SourceMappingDecoder.prototype.nodesAtPosition = nodesAtPosition - -/** - * Decode the source mapping for the given @arg index - * - * @param {Integer} index - source mapping index to decode - * @param {String} mapping - compressed source mapping given by solc-bin - * @return {Object} returns the decompressed source mapping for the given index {start, length, file, jump} - */ -SourceMappingDecoder.prototype.atIndex = atIndex /** * Decode the given @arg value @@ -34,7 +14,7 @@ SourceMappingDecoder.prototype.atIndex = atIndex * @param {string} value - source location to decode ( should be start:length:file ) * @return {Object} returns the decompressed source mapping {start, length, file} */ -SourceMappingDecoder.prototype.decode = function (value) { +export function decode (value) { if (value) { value = value.split(':') return { @@ -51,7 +31,7 @@ SourceMappingDecoder.prototype.decode = function (value) { * @param {String} mapping - compressed source mapping given by solc-bin * @return {Array} returns the decompressed source mapping. Array of {start, length, file, jump} */ -SourceMappingDecoder.prototype.decompressAll = function (mapping) { +export function decompressAll (mapping) { const map = mapping.split(';') const ret = [] for (let k in map) { @@ -73,7 +53,7 @@ SourceMappingDecoder.prototype.decompressAll = function (mapping) { * @param {String} source - contract source code * @return {Array} returns an array containing offset of line breaks */ -SourceMappingDecoder.prototype.getLinebreakPositions = function (source) { +export function getLinebreakPositions (source) { const ret = [] for (let pos = source.indexOf('\n'); pos >= 0; pos = source.indexOf('\n', pos + 1)) { ret.push(pos) @@ -88,7 +68,7 @@ SourceMappingDecoder.prototype.getLinebreakPositions = function (source) { * @param {Array} lineBreakPositions - array returned by the function 'getLinebreakPositions' * @return {Object} returns an object {start: {line, column}, end: {line, column}} (line/column count start at 0) */ -SourceMappingDecoder.prototype.convertOffsetToLineColumn = function (sourceLocation, lineBreakPositions) { +export function convertOffsetToLineColumn (sourceLocation, lineBreakPositions) { if (sourceLocation.start >= 0 && sourceLocation.length >= 0) { return { start: convertFromCharPosition(sourceLocation.start, lineBreakPositions), @@ -98,15 +78,6 @@ SourceMappingDecoder.prototype.convertOffsetToLineColumn = function (sourceLocat return {start: null, end: null} } -/** - * Retrieve the first @arg astNodeType that include the source map at arg instIndex - * - * @param {String} astNodeType - node type that include the source map instIndex - * @param {String} instIndex - instruction index used to retrieve the source map - * @param {String} sourceMap - source map given by the compilation result - * @param {Object} ast - ast given by the compilation result - */ -SourceMappingDecoder.prototype.findNodeAtInstructionIndex = findNodeAtInstructionIndex function convertFromCharPosition (pos, lineBreakPositions) { let line = util.findLowerBound(pos, lineBreakPositions) @@ -130,8 +101,16 @@ function sourceLocationFromAstNode (astNode) { return null } -function findNodeAtInstructionIndex (astNodeType, instIndex, sourceMap, ast) { - const sourceLocation = atIndex(instIndex, sourceMap) +/** + * Retrieve the first @arg astNodeType that include the source map at arg instIndex + * + * @param {String} astNodeType - node type that include the source map instIndex + * @param {String} instIndex - instruction index used to retrieve the source map + * @param {String} sourceMap - source map given by the compilation result + * @param {Object} ast - ast given by the compilation result + */ +export function findNodeAtInstructionIndex (astNodeType, instIndex, sourceMap, ast) { + const sourceLocation = this.atIndex(instIndex, sourceMap) return findNodeAtSourceLocation(astNodeType, sourceLocation, ast) } @@ -153,7 +132,15 @@ function findNodeAtSourceLocation (astNodeType, sourceLocation, ast) { return found } -function nodesAtPosition (astNodeType, position, ast) { +/** + * get a list of nodes that are at the given @arg position + * + * @param {String} astNodeType - type of node to return + * @param {Int} position - cursor position + * @return {Object} ast object given by the compiler + */ + +export function nodesAtPosition (astNodeType, position, ast) { const astWalker = new AstWalker() const found = [] const callback = function (node) { @@ -186,7 +173,7 @@ function nodesAtPosition (astNodeType, position, ast) { * @param Array mapping - source maps returned by the compiler. e.g 121:3741:0:-:0;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;121:3741:0;;;;;;; * @return Object { start, length, file, jump } */ -function atIndex (index, mapping) { +export function atIndex (index, mapping) { let ret = {} const map = mapping.split(';') if (index >= map.length) { @@ -198,23 +185,21 @@ function atIndex (index, mapping) { continue } current = current.split(':') - if (ret.start === undefined && current[0] && current[0] !== '-1' && current[0].length) { - ret.start = parseInt(current[0]) + if (ret['start'] === undefined && current[0] && current[0] !== '-1' && current[0].length) { + ret['start'] = parseInt(current[0]) } - if (ret.length === undefined && current[1] && current[1] !== '-1' && current[1].length) { - ret.length = parseInt(current[1]) + if (ret['length'] === undefined && current[1] && current[1] !== '-1' && current[1].length) { + ret['length'] = parseInt(current[1]) } - if (ret.file === undefined && current[2] && current[2].length) { - ret.file = parseInt(current[2]) + if (ret['file'] === undefined && current[2] && current[2].length) { + ret['file'] = parseInt(current[2]) } - if (ret.jump === undefined && current[3] && current[3].length) { - ret.jump = current[3] + if (ret['jump'] === undefined && current[3] && current[3].length) { + ret['jump'] = current[3] } - if (ret.start !== undefined && ret.length !== undefined && ret.file !== undefined && ret.jump !== undefined) { + if (ret['start'] !== undefined && ret['length'] !== undefined && ret['file'] !== undefined && ret['jump'] !== undefined) { break } } return ret } - -module.exports = SourceMappingDecoder