From 2c39b5f7df8f91a5dd66d90b4c95114d23971362 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 24 Aug 2016 10:08:21 +0200 Subject: [PATCH] change findlowerbound behavior --- src/helpers/util.js | 41 ++++++----- src/util/sourceMappingDecoder.js | 17 ++--- test/util.js | 119 ++++++++++++++++++++----------- 3 files changed, 108 insertions(+), 69 deletions(-) diff --git a/src/helpers/util.js b/src/helpers/util.js index 408523cbd2..cfb5a023ad 100644 --- a/src/helpers/util.js +++ b/src/helpers/util.js @@ -44,32 +44,31 @@ module.exports = { /* Binary Search: Assumes that @arg array is sorted increasingly - return smallest i such that changes[i] <= target does not hold, - or changes.length if all elements are < target. - It returns the index where target could be inserted to maintain the order of the array + return largest i such that array[i] <= target; return -1 if array[0] > target || array is empty */ findLowerBound: function (target, array) { - return findLowerBoundInternal(target, array, 0, array.length) + var start = 0 + var length = array.length + while (length > 0) { + var half = length >> 1 + var middle = start + half + if (array[middle] <= target) { + length = length - 1 - half + start = middle + 1 + } else { + length = half + } + } + return start - 1 }, + /* + Binary Search: + Assumes that @arg array is sorted increasingly + return largest array[i] such that array[i] <= target; return null if array[0] > target || array is empty + */ findLowerBoundValue: function (target, array) { var index = this.findLowerBound(target, array) - return array[index] - } -} - -function findLowerBoundInternal (target, array, lowerbound, length) { - while (length > 1) { - var half = length >> 1 - var middle = lowerbound + half - if (array[middle] < target) { - length = length - (middle - lowerbound) - lowerbound = middle - } else if (array[middle] === target) { - return middle - } else { - length = half - } + return index >= 0 ? array[index] : null } - return lowerbound } diff --git a/src/util/sourceMappingDecoder.js b/src/util/sourceMappingDecoder.js index 188bde0a93..5b2e5aa133 100644 --- a/src/util/sourceMappingDecoder.js +++ b/src/util/sourceMappingDecoder.js @@ -18,6 +18,9 @@ function SourceMappingDecoder () { SourceMappingDecoder.prototype.atIndex = function (index, mapping) { var ret = {} var map = mapping.split(';') + if (index >= map.length) { + index = map.length - 1 + } for (var k = index; k >= 0; k--) { var current = map[k] if (!current.length) { @@ -84,7 +87,7 @@ SourceMappingDecoder.prototype.getLinebreakPositions = function (source) { * * @param {Object} sourceLocation - object containing attributes {source} and {length} * @param {Array} lineBreakPositions - array returned by the function 'getLinebreakPositions' - * @@return {Object} returns an object {start: {line, column}, end: {line, column}} (line count start at 0) + * @return {Object} returns an object {start: {line, column}, end: {line, column}} (line/column count start at 0) */ SourceMappingDecoder.prototype.convertOffsetToLineColumn = function (sourceLocation, lineBreakPositions) { if (sourceLocation.start >= 0 && sourceLocation.length >= 0) { @@ -94,21 +97,19 @@ SourceMappingDecoder.prototype.convertOffsetToLineColumn = function (sourceLocat } } else { return { - start: -1, - end: -1 + start: null, + end: null } } } function convertFromCharPosition (pos, lineBreakPositions) { var line = util.findLowerBound(pos, lineBreakPositions) - - if (lineBreakPositions[line] < pos) { + if (lineBreakPositions[line] !== pos) { line = line + 1 } - - var column = lineBreakPositions[line - 1] ? (pos - lineBreakPositions[line - 1] - 1) : pos - + var beginColumn = line === 0 ? 0 : (lineBreakPositions[line - 1] + 1) + var column = pos - beginColumn return { line: line, column: column diff --git a/test/util.js b/test/util.js index 962125d929..7113618e60 100644 --- a/test/util.js +++ b/test/util.js @@ -2,78 +2,117 @@ var sourceMapping = require('./resources/sourceMapping') var index = require('../src/index') var tape = require('tape') +var util = require('../src/helpers/util') tape('Util', function (t) { + t.test('lowerbound', function (st) { + st.plan(7) + var array = [2, 5, 8, 9, 45, 56, 78] + var lowerBound = util.findLowerBound(10, array) + st.equal(lowerBound, 3) + + lowerBound = util.findLowerBound(3, array) + st.equal(lowerBound, 0) + + lowerBound = util.findLowerBound(100, array) + st.equal(lowerBound, 6) + + lowerBound = util.findLowerBound(1, array) + st.equal(lowerBound, -1) + + lowerBound = util.findLowerBound(45, array) + st.equal(lowerBound, 4) + + array = [2, 5, 8, 9, 9, 45, 56, 78] + lowerBound = util.findLowerBound(9, array) + st.equal(lowerBound, 4) + + lowerBound = util.findLowerBound(9, []) + st.equal(lowerBound, -1) + }) + var testSourceMapping = {} t.test('sourceMappingDecoder', function (st) { st.plan(28) var sourceMappingDecoder = new index.util.SourceMappingDecoder() console.log('test decompressAll') var result = sourceMappingDecoder.decompressAll(sourceMapping.mapping) - st.ok(result[0].start === 0) - st.ok(result[0].length === 205) - st.ok(result[0].file === 4) - st.ok(result[0].jump === '-') - - st.ok(result[21].start === 0) - st.ok(result[21].length === 205) - st.ok(result[21].file === 4) - st.ok(result[21].jump === '-') + st.equal(result[0].start, 0) + st.equal(result[0].length, 205) + st.equal(result[0].file, 4) + st.equal(result[0].jump, '-') + + st.equal(result[21].start, 0) + st.equal(result[21].length, 205) + st.equal(result[21].file, 4) + st.equal(result[21].jump, '-') testSourceMapping[21] = result[21] - st.ok(result[22].start === 55) - st.ok(result[22].length === 74) - st.ok(result[22].file === 4) - st.ok(result[22].jump === '-') + st.equal(result[22].start, 55) + st.equal(result[22].length, 74) + st.equal(result[22].file, 4) + st.equal(result[22].jump, '-') var last = result.length - 1 - st.ok(result[last].start === 142) - st.ok(result[last].length === 61) - st.ok(result[last].file === 4) - st.ok(result[last].jump === 'o') + st.equal(result[last].start, 142) + st.equal(result[last].length, 61) + st.equal(result[last].file, 4) + st.equal(result[last].jump, 'o') testSourceMapping['last'] = result[last] console.log('test decompress') result = sourceMappingDecoder.atIndex(22, sourceMapping.mapping) console.log(result) - st.ok(result.start === 55) - st.ok(result.length === 74) - st.ok(result.file === 4) - st.ok(result.jump === '-') + st.equal(result.start, 55) + st.equal(result.length, 74) + st.equal(result.file, 4) + st.equal(result.jump, '-') testSourceMapping[22] = result result = sourceMappingDecoder.atIndex(82, sourceMapping.mapping) console.log(result) - st.ok(result.start === 103) - st.ok(result.length === 2) - st.ok(result.file === 4) - st.ok(result.jump === '-') + st.equal(result.start, 103) + st.equal(result.length, 2) + st.equal(result.file, 4) + st.equal(result.jump, '-') testSourceMapping[82] = result result = sourceMappingDecoder.atIndex(85, sourceMapping.mapping) console.log(result) - st.ok(result.start === 99) - st.ok(result.length === 6) - st.ok(result.file === 4) - st.ok(result.jump === '-') + st.equal(result.start, 99) + st.equal(result.length, 6) + st.equal(result.file, 4) + st.equal(result.jump, '-') testSourceMapping[85] = result }) t.test('sourceMappingLineColumnConverter', function (st) { - st.plan(10) + st.plan(14) var sourceMappingDecoder = new index.util.SourceMappingDecoder() var linesbreak = sourceMappingDecoder.getLinebreakPositions(sourceMapping.source) - st.ok(linesbreak[0] === 16) - st.ok(linesbreak[5] === 84) + st.equal(linesbreak[0], 16) + st.equal(linesbreak[5], 84) var result = sourceMappingDecoder.convertOffsetToLineColumn(testSourceMapping[21], linesbreak) - st.ok(result.start.line === 0) - st.ok(result.start.column === 0) - st.ok(result.end.line === 15) - st.ok(result.end.column === 1) + st.equal(result.start.line, 0) + st.equal(result.start.column, 0) + st.equal(result.end.line, 15) + st.equal(result.end.column, 1) result = sourceMappingDecoder.convertOffsetToLineColumn(testSourceMapping[82], linesbreak) - st.ok(result.start.line === 7) - st.ok(result.start.column === 12) - st.ok(result.end.line === 7) - st.ok(result.end.column === 14) + st.equal(result.start.line, 7) + st.equal(result.start.column, 12) + st.equal(result.end.line, 7) + st.equal(result.end.column, 14) + + var res = { // point to \n + start: 103, + length: 4, + file: 4, + jump: '-' + } + result = sourceMappingDecoder.convertOffsetToLineColumn(res, linesbreak) + st.equal(result.start.line, 7) + st.equal(result.start.column, 12) + st.equal(result.end.line, 7) + st.equal(result.end.column, 16) }) })