Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: address path related bugs with 1:many source maps #108

Merged
merged 2 commits into from
Aug 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 28 additions & 16 deletions lib/v8-to-istanbul.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -64,24 +66,23 @@ 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 {
this.covSources = [{ source: new CovSource(rawSource, this.wrapperLength), path: this.path }]
}
}

_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)
}
}

Expand Down Expand Up @@ -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).
Expand All @@ -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)
Expand Down
12 changes: 6 additions & 6 deletions tap-snapshots/test-v8-to-istanbul.js-TAP.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 [
Expand Down Expand Up @@ -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 [
Expand Down Expand Up @@ -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 [
Expand Down Expand Up @@ -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 [
Expand Down Expand Up @@ -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 [
Expand Down Expand Up @@ -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 {},
Expand Down
4 changes: 2 additions & 2 deletions test/v8-to-istanbul.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'])
})
})

Expand Down Expand Up @@ -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'])
})
})

Expand Down