From d452874962936d95649aeb42147d070442b8f5ce Mon Sep 17 00:00:00 2001 From: Fabian Wiles Date: Sat, 22 Jun 2019 08:56:54 +1200 Subject: [PATCH] feat: allow sourceMaps with sourceRoot (#31) --- lib/v8-to-istanbul.js | 8 ++++++-- test/v8-to-istanbul.js | 26 +++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/lib/v8-to-istanbul.js b/lib/v8-to-istanbul.js index 145e3496..76517f2f 100644 --- a/lib/v8-to-istanbul.js +++ b/lib/v8-to-istanbul.js @@ -1,7 +1,7 @@ const { relativeTo } = require('./pathutils') const assert = require('assert') const convertSourceMap = require('convert-source-map') -const { dirname } = require('path') +const { dirname, join } = require('path') const CovBranch = require('./branch') const CovFunction = require('./function') const CovSource = require('./source') @@ -37,7 +37,11 @@ module.exports = class V8ToIstanbul { console.warn('v8-to-istanbul: source-mappings from one to many files not yet supported') this.source = new CovSource(rawSource, this.wrapperLength) } else { - this.path = relativeTo(rawSourceMap.sourcemap.sources[0], this.path) + if(rawSourceMap.sourcemap.sourceRoot) { + this.path = join(rawSourceMap.sourcemap.sourceRoot, rawSourceMap.sourcemap.sources[0]) + } else { + this.path = relativeTo(rawSourceMap.sourcemap.sources[0], this.path) + } this.sourceMap = await new SourceMapConsumer(rawSourceMap.sourcemap) const originalRawSource = readFileSync(this.path, 'utf8') diff --git a/test/v8-to-istanbul.js b/test/v8-to-istanbul.js index 58614390..431bbed9 100644 --- a/test/v8-to-istanbul.js +++ b/test/v8-to-istanbul.js @@ -1,9 +1,11 @@ /* global describe, it */ -const { readdirSync, lstatSync } = require('fs') +const { readdirSync, lstatSync, writeFileSync } = require('fs') const path = require('path') const runFixture = require('./utils/run-fixture') const V8ToIstanbul = require('../lib/v8-to-istanbul') +const crypto = require('crypto') +const os = require('os') require('tap').mochaGlobals() require('should') @@ -28,6 +30,28 @@ describe('V8ToIstanbul', () => { v8ToIstanbul.source.lines.length.should.equal(48) v8ToIstanbul.wrapperLength.should.equal(0) // ESM header. }) + + fit('should respect absolute sourceRoot', async () => { + // since we're testing an absolute dir here, we have to write this out as the program is executing + // this source map matches up with branches.covered + const sourceRoot = require.resolve('./fixtures/scripts') + const sourceMap = `{"version":3,"sourceRoot": "${sourceRoot}", "sources":["./branches.js"],"names":["a","b","c","d","console","info","e","f","g"],"mappings":"yyFAAA;AACA,KAAMA,CAAAA,CAAC,wBAAG,yDAAM,EAAN,CAAH,CAAP,CAEA;AACA,KAAMC,CAAAA,CAAC,wBAAG,gCAAQ,OAAR,4BAAkB,SAAlB,CAAH,CAAP,CAEA;AACA,KAAMC,CAAAA,CAAC,wBAAG,0BAAAF,CAAC,6BAAIC,CAAJ,CAAD,4BAAU,KAAV,6BAAmB,EAAnB,CAAH,CAAP,CAEA;sBACA,GAAI,KAAJ,CAAW,0BACT,KAAME,CAAAA,CAAC,wBAAG,EAAH,CAAP,CACD,CAFD,IAGO,gDACHC,OAAO,CAACC,IAAR,CAAa,OAAb,EACD,CAEH;AACA,QAASC,CAAAA,CAAT,EAAc,6CACZ,GAAI,IAAJ,CAAU,gDACRF,OAAO,CAACC,IAAR,CAAa,KAAb,EACD,CAFD,IAEO,0BACL,KAAME,CAAAA,CAAC,wBAAG,EAAH,CAAP,CACD,CACF,C,sBAEDD,CAAC,GAED;AACA,KAAME,CAAAA,CAAC,yBAAG,yDACR,EADQ,6BACF,EADE,CAAH,CAAP","sourcesContent":["// basic binary operation.\nconst a = 99 || 33\n\n// basic conditional operation.\nconst b = false ? 'hello' : 'goodbye'\n\n// nary operation.\nconst c = a && b && false && 33\n\n// if statement.\nif (false) {\n const d = 99\n}\n else {\n console.info('hello')\n }\n\n// if statement in function.\nfunction e () {\n if (true) {\n console.info('hey')\n } else {\n const f = 99\n }\n}\n\ne()\n\n// binary operation that spans multiple lines.\nconst g = 99 &&\n 33 || 13\n"]}`; + const source =`var cov_1myqaytex8=function(){var path="./test/fixtures/scripts/branches.js";var hash="05fd1c5758177cf8534c86e9665d000812274ffa";var global=new Function("return this")();var gcv="__coverage__";var coverageData={path:"./test/fixtures/scripts/branches.js",statementMap:{"0":{start:{line:2,column:10},end:{line:2,column:18}},"1":{start:{line:5,column:10},end:{line:5,column:37}},"2":{start:{line:8,column:10},end:{line:8,column:31}},"3":{start:{line:11,column:0},end:{line:16,column:3}},"4":{start:{line:12,column:12},end:{line:12,column:14}},"5":{start:{line:15,column:4},end:{line:15,column:25}},"6":{start:{line:20,column:2},end:{line:24,column:3}},"7":{start:{line:21,column:4},end:{line:21,column:23}},"8":{start:{line:23,column:14},end:{line:23,column:16}},"9":{start:{line:27,column:0},end:{line:27,column:3}},"10":{start:{line:30,column:10},end:{line:31,column:10}}},fnMap:{"0":{name:"e",decl:{start:{line:19,column:9},end:{line:19,column:10}},loc:{start:{line:19,column:14},end:{line:25,column:1}},line:19}},branchMap:{"0":{loc:{start:{line:2,column:10},end:{line:2,column:18}},type:"binary-expr",locations:[{start:{line:2,column:10},end:{line:2,column:12}},{start:{line:2,column:16},end:{line:2,column:18}}],line:2},"1":{loc:{start:{line:5,column:10},end:{line:5,column:37}},type:"cond-expr",locations:[{start:{line:5,column:18},end:{line:5,column:25}},{start:{line:5,column:28},end:{line:5,column:37}}],line:5},"2":{loc:{start:{line:8,column:10},end:{line:8,column:31}},type:"binary-expr",locations:[{start:{line:8,column:10},end:{line:8,column:11}},{start:{line:8,column:15},end:{line:8,column:16}},{start:{line:8,column:20},end:{line:8,column:25}},{start:{line:8,column:29},end:{line:8,column:31}}],line:8},"3":{loc:{start:{line:11,column:0},end:{line:16,column:3}},type:"if",locations:[{start:{line:11,column:0},end:{line:16,column:3}},{start:{line:11,column:0},end:{line:16,column:3}}],line:11},"4":{loc:{start:{line:20,column:2},end:{line:24,column:3}},type:"if",locations:[{start:{line:20,column:2},end:{line:24,column:3}},{start:{line:20,column:2},end:{line:24,column:3}}],line:20},"5":{loc:{start:{line:30,column:10},end:{line:31,column:10}},type:"binary-expr",locations:[{start:{line:30,column:10},end:{line:30,column:12}},{start:{line:31,column:2},end:{line:31,column:4}},{start:{line:31,column:8},end:{line:31,column:10}}],line:30}},s:{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0},f:{"0":0},b:{"0":[0,0],"1":[0,0],"2":[0,0,0,0],"3":[0,0],"4":[0,0],"5":[0,0,0]},_coverageSchema:"43e27e138ebf9cfc5966b082cf9a028302ed4184",hash:"05fd1c5758177cf8534c86e9665d000812274ffa"};var coverage=global[gcv]||(global[gcv]={});if(coverage[path]&&coverage[path].hash===hash){return coverage[path];}return coverage[path]=coverageData;}();// basic binary operation. +const a=(cov_1myqaytex8.s[0]++,(cov_1myqaytex8.b[0][0]++,99)||(cov_1myqaytex8.b[0][1]++,33));// basic conditional operation. +const b=(cov_1myqaytex8.s[1]++,false?(cov_1myqaytex8.b[1][0]++,'hello'):(cov_1myqaytex8.b[1][1]++,'goodbye'));// nary operation. +const c=(cov_1myqaytex8.s[2]++,(cov_1myqaytex8.b[2][0]++,a)&&(cov_1myqaytex8.b[2][1]++,b)&&(cov_1myqaytex8.b[2][2]++,false)&&(cov_1myqaytex8.b[2][3]++,33));// if statement. +cov_1myqaytex8.s[3]++;if(false){cov_1myqaytex8.b[3][0]++;const d=(cov_1myqaytex8.s[4]++,99);}else{cov_1myqaytex8.b[3][1]++;cov_1myqaytex8.s[5]++;console.info('hello');}// if statement in function. +function e(){cov_1myqaytex8.f[0]++;cov_1myqaytex8.s[6]++;if(true){cov_1myqaytex8.b[4][0]++;cov_1myqaytex8.s[7]++;console.info('hey');}else{cov_1myqaytex8.b[4][1]++;const f=(cov_1myqaytex8.s[8]++,99);}}cov_1myqaytex8.s[9]++;e();// binary operation that spans multiple lines. +const g=(cov_1myqaytex8.s[10]++,(cov_1myqaytex8.b[5][0]++,99)&&(cov_1myqaytex8.b[5][1]++,33)||(cov_1myqaytex8.b[5][2]++,13)); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,${btoa(sourceMap)} +` + const tmpPath = path.join(os.tmpdir(), crypto.randomBytes(4).readUInt32LE(0) + '.js'); + writeFileSync(tmpPath, source); + + // if either of these statements threw an exception then it wasn't able to resolve the absolute path + const v8ToIstanbul = new V8ToIstanbul(tmpPath) + await v8ToIstanbul.load() + }) }) // execute JavaScript files in fixtures directory; these