diff --git a/lib/v8-to-istanbul.js b/lib/v8-to-istanbul.js index d6af42e9..7d23ed17 100644 --- a/lib/v8-to-istanbul.js +++ b/lib/v8-to-istanbul.js @@ -31,26 +31,28 @@ module.exports = class V8ToIstanbul { this.branches = {} this.functions = {} this.covSources = [] + this.rawSourceMap = undefined this.sourceMap = undefined this.sourceTranspiled = undefined } async load () { const rawSource = this.sources.source || await readFile(this.path, 'utf8') - const rawSourceMap = this.sources.sourceMap || + this.rawSourceMap = this.sources.sourceMap || // if we find a source-map (either inline, or a .map file) we load // both the transpiled and original source, both of which are used during // the backflips we perform to remap absolute to relative positions. convertSourceMap.fromSource(rawSource) || convertSourceMap.fromMapFileSource(rawSource, dirname(this.path)) - if (rawSourceMap) { - if (rawSourceMap.sourcemap.sources.length > 1) { - this.sourceMap = await new SourceMapConsumer(rawSourceMap.sourcemap) + if (this.rawSourceMap) { + if (this.rawSourceMap.sourcemap.sources.length > 1) { + this.sourceMap = await new SourceMapConsumer(this.rawSourceMap.sourcemap) this.covSources = this.sourceMap.sourcesContent.map((rawSource, i) => ({ source: new CovSource(rawSource, this.wrapperLength), path: this.sourceMap.sources[i] })) this.sourceTranspiled = new CovSource(rawSource, this.wrapperLength) } else { - this._rewritePath(rawSourceMap) - this.sourceMap = await new SourceMapConsumer(rawSourceMap.sourcemap) + const candidatePath = this.rawSourceMap.sourcemap.sources.length >= 1 ? this.rawSourceMap.sourcemap.sources[0] : this.rawSourceMap.sourcemap.file + this.path = this._resolveSource(this.rawSourceMap, candidatePath) + this.sourceMap = await new SourceMapConsumer(this.rawSourceMap.sourcemap) let originalRawSource // If the source map has inline source content then it should be here @@ -64,8 +66,7 @@ module.exports = class V8ToIstanbul { } else { originalRawSource = await readFile(this.path, 'utf8') } - - this.covSources = [{ source: new CovSource(originalRawSource, this.wrapperLength), path: this.sourceMap.sources[0] }] + this.covSources = [{ source: new CovSource(originalRawSource, this.wrapperLength), path: this.path }] this.sourceTranspiled = new CovSource(rawSource, this.wrapperLength) } } else { @@ -73,15 +74,15 @@ module.exports = class V8ToIstanbul { } } - _rewritePath (rawSourceMap) { + _resolveSource (rawSourceMap, sourcePath) { + sourcePath = sourcePath.replace(/(^file:\/\/)|(^webpack:\/\/)/, '') const sourceRoot = rawSourceMap.sourcemap.sourceRoot ? rawSourceMap.sourcemap.sourceRoot.replace('file://', '') : '' - const sourcePath = rawSourceMap.sourcemap.sources.length >= 1 ? rawSourceMap.sourcemap.sources[0].replace('file://', '') : rawSourceMap.sourcemap.file const candidatePath = join(sourceRoot, sourcePath) if (isAbsolute(candidatePath)) { - this.path = candidatePath + return candidatePath } else { - this.path = resolve(dirname(this.path), candidatePath) + return resolve(dirname(this.path), candidatePath) } } @@ -181,7 +182,7 @@ module.exports = class V8ToIstanbul { const matchingSource = this.covSources.find(covSource => covSource.path === source) covSource = matchingSource ? matchingSource.source : this.covSources[0].source - path = matchingSource ? matchingSource.path : this.covSources[0].path; + path = matchingSource ? matchingSource.path : this.covSources[0].path // next we convert these relative positions back to absolute positions // in the original source (which is the format expected in the next step). @@ -198,13 +199,24 @@ module.exports = class V8ToIstanbul { } getInnerIstanbul (source, path) { - if (this.excludePath(path)) { + // We apply the "Resolving Sources" logic (as defined in + // sourcemaps.info/spec.html) as a final step for 1:many source maps. + // for 1:1 source maps, the resolve logic is applied while loading. + // + // TODO: could we move the resolving logic for 1:1 source maps to the final + // step as well? currently this breaks some tests in c8. + let resolvedPath = path + if (this.rawSourceMap && this.rawSourceMap.sourcemap.sources.length > 1) { + resolvedPath = this._resolveSource(this.rawSourceMap, path) + } + + if (this.excludePath(resolvedPath)) { return } return { - [path]: { - path, + [resolvedPath]: { + path: resolvedPath, ...this._statementsToIstanbul(source, path), ...this._branchesToIstanbul(source, path), ...this._functionsToIstanbul(source, path) diff --git a/tap-snapshots/test-v8-to-istanbul.js-TAP.test.js b/tap-snapshots/test-v8-to-istanbul.js-TAP.test.js index 71b50fcb..51c0399e 100644 --- a/tap-snapshots/test-v8-to-istanbul.js-TAP.test.js +++ b/tap-snapshots/test-v8-to-istanbul.js-TAP.test.js @@ -5,7 +5,7 @@ * Make sure to inspect the output below. Do not ignore changes! */ 'use strict' -exports[`test/v8-to-istanbul.js TAP > must match branches snapshot 1`] = ` +exports['test/v8-to-istanbul.js TAP > must match branches snapshot 1'] = ` Object { "b": Object { "0": Array [ @@ -620,7 +620,7 @@ Object { } ` -exports[`test/v8-to-istanbul.js TAP > must match functions snapshot 1`] = ` +exports['test/v8-to-istanbul.js TAP > must match functions snapshot 1'] = ` Object { "b": Object { "0": Array [ @@ -1601,7 +1601,7 @@ Object { } ` -exports[`test/v8-to-istanbul.js TAP > must match mixed new lines snapshot 1`] = ` +exports['test/v8-to-istanbul.js TAP > must match mixed new lines snapshot 1'] = ` Object { "b": Object { "0": Array [ @@ -1707,7 +1707,7 @@ Object { } ` -exports[`test/v8-to-istanbul.js TAP > must match shebang snapshot 1`] = ` +exports['test/v8-to-istanbul.js TAP > must match shebang snapshot 1'] = ` Object { "b": Object { "0": Array [ @@ -1868,7 +1868,7 @@ Object { } ` -exports[`test/v8-to-istanbul.js TAP > must match source-map and minified source snapshot 1`] = ` +exports['test/v8-to-istanbul.js TAP > must match source-map and minified source snapshot 1'] = ` Object { "b": Object { "0": Array [ @@ -2570,7 +2570,7 @@ Object { } ` -exports[`test/v8-to-istanbul.js TAP > must match source-map with multiple source files snapshot 1`] = ` +exports['test/v8-to-istanbul.js TAP > must match source-map with multiple source files snapshot 1'] = ` Object { "b": Object {}, "branchMap": Object {}, diff --git a/test/v8-to-istanbul.js b/test/v8-to-istanbul.js index dbda9c4a..6765966d 100644 --- a/test/v8-to-istanbul.js +++ b/test/v8-to-istanbul.js @@ -137,7 +137,7 @@ ${'//'}${'#'} sourceMappingURL=data:application/json;base64,${base64Sourcemap} endOffset: 1 }] }]) - Object.keys(v8ToIstanbul.toIstanbul()).should.eql(['webpack:///src/index.ts', 'webpack:///src/utils.ts']) + Object.keys(v8ToIstanbul.toIstanbul()).should.eql(['/src/index.ts', '/src/utils.ts']) }) }) @@ -175,7 +175,7 @@ ${'//'}${'#'} sourceMappingURL=data:application/json;base64,${base64Sourcemap} await v8ToIstanbul.load() v8ToIstanbul.covSources.length.should.equal(3) - Object.keys(v8ToIstanbul.toIstanbul()).should.eql(['webpack:///webpack/bootstrap', 'webpack:///src/index.ts', 'webpack:///src/utils.ts']) + Object.keys(v8ToIstanbul.toIstanbul()).should.eql(['/webpack/bootstrap', '/src/index.ts', '/src/utils.ts']) }) })