Created
April 13, 2022 04:50
-
-
Save rohit-gohri/5fdef21c9ae60c6941b6bc7493478316 to your computer and use it in GitHub Desktop.
Get runtime coverage from V8 in istanbul format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable global-require, import/no-extraneous-dependencies, @typescript-eslint/no-use-before-define */ | |
/** | |
* @see https://github.com/bcoe/c8/issues/376 | |
* @see https://github.com/tapjs/processinfo/blob/33c72e547139630cde35a4126bb4575ad7157065/lib/register-coverage.cjs | |
*/ | |
if (process.env.V8_COVERAGE) { | |
process.setSourceMapsEnabled(true); | |
const inspector = require('inspector'); | |
const session = new inspector.Session(); | |
module.exports.session = session; | |
session.connect(); | |
session.post('Profiler.enable'); | |
session.post('Runtime.enable'); | |
session.post('Profiler.startPreciseCoverage', { | |
callCount: true, | |
detailed: true, | |
}); | |
const { fileURLToPath } = require('url'); | |
const v8toIstanbul = require('v8-to-istanbul'); | |
const libCoverage = require('istanbul-lib-coverage'); | |
const { findSourceMap } = require('module'); | |
const lineLengths = (f) => | |
readFileSync(f, 'utf8') | |
.split(/\n|\u2028|\u2029/) | |
.map((l) => l.length); | |
const { readFileSync } = require('fs'); | |
const getCoverage = async () => { | |
const map = libCoverage.createCoverageMap(); | |
await new Promise((resolve, reject) => { | |
session.post('Profiler.takePreciseCoverage', async (er, cov) => { | |
/* istanbul ignore next - something very strange and bad happened */ | |
if (er) { | |
reject(er); | |
return; | |
} | |
// eslint-disable-next-line no-multi-assign,no-param-reassign | |
const sourceMapCache = (cov['source-map-cache'] = {}); | |
await Promise.all( | |
cov.result.map(async (obj) => { | |
if (!/^file:/.test(obj.url)) { | |
return false; | |
} | |
if (obj.url.includes('/node_modules/')) { | |
return false; | |
} | |
const f = fileURLToPath(obj.url); | |
// see if it has a source map | |
const s = findSourceMap(f); | |
if (s) { | |
const { payload } = s; | |
sourceMapCache[obj.url] = Object.assign(Object.create(null), { | |
lineLengths: lineLengths(f), | |
data: payload, | |
}); | |
} | |
const sources = {}; | |
const sourceMapAndLineLengths = sourceMapCache[obj.url]; | |
if (sourceMapAndLineLengths) { | |
// See: https://github.com/nodejs/node/pull/34305 | |
if (!sourceMapAndLineLengths.data) return; | |
sources.sourceMap = { | |
sourcemap: sourceMapAndLineLengths.data, | |
}; | |
if (sourceMapAndLineLengths.lineLengths) { | |
let source = ''; | |
sourceMapAndLineLengths.lineLengths.forEach((length) => { | |
source += `${''.padEnd(length, '.')}\n`; | |
}); | |
sources.source = source; | |
} | |
} | |
const converter = v8toIstanbul(f, undefined, sources); | |
await converter.load(); | |
converter.applyCoverage(obj.functions); | |
const coverage = converter.toIstanbul(); | |
converter.destroy(); | |
map.merge(coverage); | |
}), | |
); | |
resolve(null); | |
}); | |
}); | |
return map.toJSON(); | |
}; | |
global.__getCoverage__ = getCoverage; | |
module.exports = { coverageOnProcessEnd: getCoverage }; | |
} else { | |
module.exports = { coverageOnProcessEnd: () => {} }; | |
global.__getCoverage__ = () => {}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment