istanbuljs / v8-to-istanbul

convert from v8 coverage format to istanbul's format
ISC License
114 stars 41 forks source link

Relative sourceRoot can cause issues with file discovery #99

Open j03m opened 4 years ago

j03m commented 4 years ago

The following is a legal sourceMap. Note the condition that causes a problem, is the combination of a relative sourceRoot along with a sources member that contains a path that an additional level deep in the directory structure. In this case, subdir/foo.ts.

{"version":3,"sources":["subdir/foo.ts"],"names":[ ... ],"mappings":" ... ","file":"foo.js","sourceRoot":"../../../../../../../../rootdir"}

Give the discovery of a covered file in c8 that was [somepath]/rootdir/subdir/foo.js when we attempt to resolve the location of the source file we will hit this block of code: https://github.com/istanbuljs/v8-to-istanbul/blob/master/lib/v8-to-istanbul.js#L79 we will end up creating a path that is: [somepath]/rootdir/subdir/subdir/foo.ts which is invalid.

Taking a look at this for a PR.

j03m commented 4 years ago

I think the correct code here would be:

this.path = join(resolve(dirname(this.path), sourceRoot), sourcePath)

Where dirname(this.path) would get the directory for the src file in question. resolve would then resolve against the relative sourceRoot getting the absolute path to the source directory. From there the join would attach the source file and be teh right path to the source file.

I'll need to test this though to make sure I'm not just fixing this case.

robpalme commented 4 years ago

Agreed - it looks like the bug is due to sourceRoot being ignored if it is relative. So an equivalent fix would be:

const candidatePath = join(sourceRoot, sourcePath)

if (isAbsolute(candidatePath)) {
  this.path = candidatePath
} else {
-  this.path = resolve(dirname(this.path), sourcePath)
+  this.path = resolve(dirname(this.path), candidatePath)
}