Comparing version 7.13.0 to 8.0.0
@@ -37,3 +37,4 @@ const { checkCoverages } = require('./check-coverage') | ||
skipFull: argv.skipFull, | ||
excludeNodeModules: argv.excludeNodeModules | ||
excludeNodeModules: argv.excludeNodeModules, | ||
mergeAsync: argv.mergeAsync | ||
}) | ||
@@ -40,0 +41,0 @@ await report.run() |
@@ -155,2 +155,8 @@ const defaultExclude = require('@istanbuljs/schema/default-exclude') | ||
}) | ||
.options('merge-async', { | ||
default: false, | ||
type: 'boolean', | ||
describe: 'supplying --merge-async will merge all v8 coverage reports asynchronously and incrementally. ' + | ||
'This is to avoid OOM issues with Node.js runtime.' | ||
}) | ||
.pkgConf('c8') | ||
@@ -157,0 +163,0 @@ .demandCommand(1) |
@@ -5,2 +5,8 @@ const Exclude = require('test-exclude') | ||
const reports = require('istanbul-reports') | ||
let readFile | ||
try { | ||
;({ readFile } = require('fs/promises')) | ||
} catch (err) { | ||
;({ readFile } = require('fs').promises) | ||
} | ||
const { readdirSync, readFileSync, statSync } = require('fs') | ||
@@ -34,3 +40,4 @@ const { isAbsolute, resolve, extname } = require('path') | ||
skipFull, | ||
excludeNodeModules | ||
excludeNodeModules, | ||
mergeAsync | ||
}) { | ||
@@ -58,2 +65,3 @@ this.reporter = reporter | ||
this.skipFull = skipFull | ||
this.mergeAsync = mergeAsync | ||
} | ||
@@ -96,3 +104,9 @@ | ||
const map = libCoverage.createCoverageMap() | ||
const v8ProcessCov = this._getMergedProcessCov() | ||
let v8ProcessCov | ||
if (this.mergeAsync) { | ||
v8ProcessCov = await this._getMergedProcessCovAsync() | ||
} else { | ||
v8ProcessCov = this._getMergedProcessCov() | ||
} | ||
const resultCountPerPath = new Map() | ||
@@ -195,42 +209,105 @@ const possibleCjsEsmBridges = new Map() | ||
if (this.all) { | ||
const emptyReports = [] | ||
const emptyReports = this._includeUncoveredFiles(fileIndex) | ||
v8ProcessCovs.unshift({ | ||
result: emptyReports | ||
}) | ||
const workingDirs = this.src | ||
const { extension } = this.exclude | ||
for (const workingDir of workingDirs) { | ||
this.exclude.globSync(workingDir).forEach((f) => { | ||
const fullPath = resolve(workingDir, f) | ||
if (!fileIndex.has(fullPath)) { | ||
const ext = extname(fullPath) | ||
if (extension.includes(ext)) { | ||
const stat = statSync(fullPath) | ||
const sourceMap = getSourceMapFromFile(fullPath) | ||
if (sourceMap) { | ||
this.sourceMapCache[pathToFileURL(fullPath)] = { data: sourceMap } | ||
} | ||
emptyReports.push({ | ||
scriptId: 0, | ||
url: resolve(fullPath), | ||
functions: [{ | ||
functionName: '(empty-report)', | ||
ranges: [{ | ||
startOffset: 0, | ||
endOffset: stat.size, | ||
count: 0 | ||
}], | ||
isBlockCoverage: true | ||
}] | ||
}) | ||
} | ||
} | ||
return mergeProcessCovs(v8ProcessCovs) | ||
} | ||
/** | ||
* Returns the merged V8 process coverage. | ||
* | ||
* It asynchronously and incrementally reads and merges individual process coverages | ||
* generated by Node. This can be used via the `--merge-async` CLI arg. It's intended | ||
* to be used across a large multi-process test run. | ||
* | ||
* @return {ProcessCov} Merged V8 process coverage. | ||
* @private | ||
*/ | ||
async _getMergedProcessCovAsync () { | ||
const { mergeProcessCovs } = require('@bcoe/v8-coverage') | ||
const fileIndex = new Set() // Set<string> | ||
let mergedCov = null | ||
for (const file of readdirSync(this.tempDirectory)) { | ||
try { | ||
const rawFile = await readFile( | ||
resolve(this.tempDirectory, file), | ||
'utf8' | ||
) | ||
let report = JSON.parse(rawFile) | ||
if (this._isCoverageObject(report)) { | ||
if (report['source-map-cache']) { | ||
Object.assign(this.sourceMapCache, this._normalizeSourceMapCache(report['source-map-cache'])) | ||
} | ||
}) | ||
report = this._normalizeProcessCov(report, fileIndex) | ||
if (mergedCov) { | ||
mergedCov = mergeProcessCovs([mergedCov, report]) | ||
} else { | ||
mergedCov = mergeProcessCovs([report]) | ||
} | ||
} | ||
} catch (err) { | ||
debuglog(`${err.stack}`) | ||
} | ||
} | ||
return mergeProcessCovs(v8ProcessCovs) | ||
if (this.all) { | ||
const emptyReports = this._includeUncoveredFiles(fileIndex) | ||
const emptyReport = { | ||
result: emptyReports | ||
} | ||
mergedCov = mergeProcessCovs([emptyReport, mergedCov]) | ||
} | ||
return mergedCov | ||
} | ||
/** | ||
* Adds empty coverage reports to account for uncovered/untested code. | ||
* This is only done when the `--all` flag is present. | ||
* | ||
* @param {Set} fileIndex list of files that have coverage | ||
* @returns {Array} list of empty coverage reports | ||
*/ | ||
_includeUncoveredFiles (fileIndex) { | ||
const emptyReports = [] | ||
const workingDirs = this.src | ||
const { extension } = this.exclude | ||
for (const workingDir of workingDirs) { | ||
this.exclude.globSync(workingDir).forEach((f) => { | ||
const fullPath = resolve(workingDir, f) | ||
if (!fileIndex.has(fullPath)) { | ||
const ext = extname(fullPath) | ||
if (extension.includes(ext)) { | ||
const stat = statSync(fullPath) | ||
const sourceMap = getSourceMapFromFile(fullPath) | ||
if (sourceMap) { | ||
this.sourceMapCache[pathToFileURL(fullPath)] = { data: sourceMap } | ||
} | ||
emptyReports.push({ | ||
scriptId: 0, | ||
url: resolve(fullPath), | ||
functions: [{ | ||
functionName: '(empty-report)', | ||
ranges: [{ | ||
startOffset: 0, | ||
endOffset: stat.size, | ||
count: 0 | ||
}], | ||
isBlockCoverage: true | ||
}] | ||
}) | ||
} | ||
} | ||
}) | ||
} | ||
return emptyReports | ||
} | ||
/** | ||
* Make sure v8ProcessCov actually contains coverage information. | ||
@@ -237,0 +314,0 @@ * |
{ | ||
"name": "c8", | ||
"version": "7.13.0", | ||
"version": "8.0.0", | ||
"description": "output coverage reports using Node.js' built in coverage", | ||
@@ -60,3 +60,3 @@ "main": "./index.js", | ||
"engines": { | ||
"node": ">=10.12.0" | ||
"node": ">=12" | ||
}, | ||
@@ -63,0 +63,0 @@ "files": [ |
@@ -170,3 +170,3 @@ # c8 - native V8 code-coverage | ||
c8 uses [native V8 coverage](https://github.com/nodejs/node/pull/22527), | ||
make sure you're running Node.js `>= 10.12.0`. | ||
make sure you're running Node.js `>= 12`. | ||
@@ -173,0 +173,0 @@ ## Contributing to `c8` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
38642
881
9