diff --git a/README.md b/README.md index 5c8c6791..7e9bf696 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,10 @@ converter.applyCoverage([ // output coverage information in a form that can // be consumed by Istanbul. console.info(JSON.stringify(converter.toIstanbul())) + +// cleanup resources allocated in "load" (i.e. by the source-map dependency), +// the converter may not be used anymore afterwards +converter.destroy() ``` ## Ignoring Uncovered Lines diff --git a/index.d.ts b/index.d.ts index 7bf9966f..3470f4e8 100644 --- a/index.d.ts +++ b/index.d.ts @@ -15,6 +15,7 @@ declare type Sources = } declare class V8ToIstanbul { load(): Promise + destroy(): void applyCoverage(blocks: ReadonlyArray): void toIstanbul(): CoverageMapData } diff --git a/lib/v8-to-istanbul.js b/lib/v8-to-istanbul.js index 46fefb89..2a8dc408 100644 --- a/lib/v8-to-istanbul.js +++ b/lib/v8-to-istanbul.js @@ -83,6 +83,13 @@ module.exports = class V8ToIstanbul { } } + destroy () { + if (this.sourceMap) { + this.sourceMap.destroy() + this.sourceMap = undefined + } + } + _resolveSource (rawSourceMap, sourcePath) { if (sourcePath.startsWith('file://')) { return fileURLToPath(sourcePath) diff --git a/test/v8-to-istanbul.js b/test/v8-to-istanbul.js index 78f95a26..f9eaad58 100644 --- a/test/v8-to-istanbul.js +++ b/test/v8-to-istanbul.js @@ -10,7 +10,7 @@ const sourcemap = require('source-map') const assert = require('assert') require('tap').mochaGlobals() -require('should') +const should = require('should') describe('V8ToIstanbul', async () => { describe('constructor', () => { @@ -22,6 +22,8 @@ describe('V8ToIstanbul', async () => { v8ToIstanbul.covSources[0].source.lines.length.should.equal(48) v8ToIstanbul.covSources.length.should.equal(1) v8ToIstanbul.wrapperLength.should.equal(0) // common-js header. + + v8ToIstanbul.destroy() }) it('handles ESM style paths', async () => { @@ -33,6 +35,8 @@ describe('V8ToIstanbul', async () => { v8ToIstanbul.covSources[0].source.lines.length.should.equal(48) v8ToIstanbul.covSources.length.should.equal(1) v8ToIstanbul.wrapperLength.should.equal(0) // ESM header. + + v8ToIstanbul.destroy() }) it('handles source maps with sourceRoot', async () => { @@ -60,6 +64,8 @@ ${'//'}${'#'} sourceMappingURL=data:application/json;base64,${base64Sourcemap} await v8ToIstanbul.load() v8ToIstanbul.path.should.equal(absoluteSourceFilePath) + + v8ToIstanbul.destroy() }) it('handles sourceContent', async () => { @@ -91,6 +97,8 @@ ${'//'}${'#'} sourceMappingURL=data:application/json;base64,${base64Sourcemap} // if the source is transpiled and since we didn't inline the source map into the transpiled source file // that means it was bale to access the content via the provided sources object v8ToIstanbul.sourceTranspiled.should.not.be.undefined() + + v8ToIstanbul.destroy() }) it('should clamp line source column >= 0', async () => { @@ -121,6 +129,8 @@ ${'//'}${'#'} sourceMappingURL=data:application/json;base64,${base64Sourcemap} endOffset: matchedNewLineChar + 10 }] }]) + + v8ToIstanbul.destroy() }) it('should exclude files when passing excludePath', async () => { @@ -139,6 +149,8 @@ ${'//'}${'#'} sourceMappingURL=data:application/json;base64,${base64Sourcemap} }] }]) Object.keys(v8ToIstanbul.toIstanbul()).should.eql(['/src/index.ts', '/src/utils.ts'].map(path.normalize)) + + v8ToIstanbul.destroy() }) }) @@ -157,6 +169,7 @@ ${'//'}${'#'} sourceMappingURL=data:application/json;base64,${base64Sourcemap} 0 ) await v8ToIstanbul.load() + v8ToIstanbul.destroy() }) it('should handle relative sourceRoots correctly', async () => { @@ -166,6 +179,7 @@ ${'//'}${'#'} sourceMappingURL=data:application/json;base64,${base64Sourcemap} ) await v8ToIstanbul.load() assert(v8ToIstanbul.path.includes(path.normalize('v8-to-istanbul/test/fixtures/one-up/relative-source-root.js'))) + v8ToIstanbul.destroy() }) it('should handles source maps with multiple sources', async () => { @@ -177,9 +191,25 @@ ${'//'}${'#'} sourceMappingURL=data:application/json;base64,${base64Sourcemap} v8ToIstanbul.covSources.length.should.equal(3) Object.keys(v8ToIstanbul.toIstanbul()).should.eql(['/webpack/bootstrap', '/src/index.ts', '/src/utils.ts'].map(path.normalize)) + + v8ToIstanbul.destroy() }) }) + it('destroy cleans up source map', async () => { + const v8ToIstanbul = new V8ToIstanbul( + pathToFileURL(require.resolve('./fixtures/scripts/empty.compiled.js')).href + ) + await v8ToIstanbul.load() + // assertion only to check test data and setup - source map must be loaded, + // otherwise destroy would have no effect anyway + assert(v8ToIstanbul.sourceMap !== undefined, 'Test fixture must load a source map') + + v8ToIstanbul.destroy() + + should.not.exist(v8ToIstanbul.sourceMap) + }) + // execute JavaScript files in fixtures directory; these // files contain the raw v8 output along with a set of // assertions. the original scripts can be found in the