diff --git a/docs/guide/coverage.md b/docs/guide/coverage.md index f840ff2ceffe..4bb054b638c0 100644 --- a/docs/guide/coverage.md +++ b/docs/guide/coverage.md @@ -350,6 +350,10 @@ Comments which are considered as [legal comments](https://esbuild.github.io/api/ You can include a `@preserve` keyword in the ignore hint. Beware that these ignore hints may now be included in final production build as well. +::: tip +Follow https://github.com/vitest-dev/vitest/issues/2021 for updates about `@preserve` usage. +::: + ```diff -/* istanbul ignore if */ +/* istanbul ignore if -- @preserve */ @@ -364,6 +368,30 @@ if (condition) { ::: code-group +```ts [lines: start/stop] +/* istanbul ignore start -- @preserve */ +if (parameter) { // [!code error] + console.log('Ignored') // [!code error] +} // [!code error] +else { // [!code error] + console.log('Ignored') // [!code error] +} // [!code error] +/* istanbul ignore stop -- @preserve */ + +console.log('Included') + +/* v8 ignore start -- @preserve */ +if (parameter) { // [!code error] + console.log('Ignored') // [!code error] +} // [!code error] +else { // [!code error] + console.log('Ignored') // [!code error] +} // [!code error] +/* v8 ignore stop -- @preserve */ + +console.log('Included') +``` + ```ts [if else] /* v8 ignore if -- @preserve */ if (parameter) { // [!code error] diff --git a/packages/coverage-istanbul/package.json b/packages/coverage-istanbul/package.json index 7e59e963c767..a5d2bd02d3ef 100644 --- a/packages/coverage-istanbul/package.json +++ b/packages/coverage-istanbul/package.json @@ -44,11 +44,11 @@ "vitest": "workspace:*" }, "dependencies": { + "@babel/core": "^7.23.9", "@istanbuljs/schema": "^0.1.3", "@jridgewell/gen-mapping": "^0.3.13", "@jridgewell/trace-mapping": "catalog:", "istanbul-lib-coverage": "catalog:", - "istanbul-lib-instrument": "^6.0.3", "istanbul-lib-report": "catalog:", "istanbul-reports": "catalog:", "magicast": "catalog:", @@ -61,6 +61,7 @@ "@types/istanbul-lib-report": "catalog:", "@types/istanbul-lib-source-maps": "catalog:", "@types/istanbul-reports": "catalog:", + "istanbul-lib-instrument": "^6.0.3", "istanbul-lib-source-maps": "catalog:", "pathe": "catalog:", "vitest": "workspace:*" diff --git a/packages/coverage-istanbul/rollup.config.js b/packages/coverage-istanbul/rollup.config.js index 33df8efd1507..6be6a7765b34 100644 --- a/packages/coverage-istanbul/rollup.config.js +++ b/packages/coverage-istanbul/rollup.config.js @@ -19,6 +19,9 @@ const external = [ ...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {}), /^@?vitest(\/|$)/, + + // We bundle istanbul-lib-instrument but don't want to bundle its babel dependency + '@babel/core', ] const dtsUtils = createDtsUtils() @@ -29,6 +32,7 @@ const plugins = [ json(), commonjs({ // "istanbul-lib-source-maps > @jridgewell/trace-mapping" is not CJS + // "istanbul-lib-instrument > @jridgewell/trace-mapping" is not CJS esmExternals: ['@jridgewell/trace-mapping'], }), oxc({ diff --git a/packages/coverage-istanbul/src/provider.ts b/packages/coverage-istanbul/src/provider.ts index 2934ee82e486..832621a56111 100644 --- a/packages/coverage-istanbul/src/provider.ts +++ b/packages/coverage-istanbul/src/provider.ts @@ -48,6 +48,9 @@ export class IstanbulCoverageProvider extends BaseCoverageProvider ++ * ++ * ``` ++ */ ++function getIgnoredLines(text) { ++ if (!text) { ++ return new Set(); ++ } ++ ++ const ranges = []; ++ let lineNumber = 0; ++ ++ for (const line of text.split(EOL_PATTERN)) { ++ lineNumber++; ++ ++ const match = line.match(IGNORE_LINES_PATTERN); ++ if (match) { ++ const type = match[1]; ++ ++ if (type === 'stop') { ++ const previous = ranges.at(-1); ++ ++ // Ignore whole "ignore stop" if no previous start was found ++ if (previous && previous.stop === Infinity) { ++ previous.stop = lineNumber; ++ } ++ ++ continue; ++ } ++ ++ ranges.push({ start: lineNumber, stop: Infinity }); ++ } ++ } ++ ++ const ignoredLines = new Set(); ++ ++ for (const range of ranges) { ++ for (let line = range.start; line <= range.stop; line++) { ++ ignoredLines.add(line); ++ ++ if (line >= lineNumber) { ++ break; ++ } ++ } ++ } ++ ++ return ignoredLines; ++} ++ ++module.exports = { getIgnoredLines }; +diff --git a/src/instrumenter.js b/src/instrumenter.js +index ffc4387b9ba9477bdce3823760400fddb021637d..39f5ee8fede4a6d724b28050e1dd1e1942bd665a 100644 +--- a/src/instrumenter.js ++++ b/src/instrumenter.js +@@ -21,6 +21,7 @@ const readInitialCoverage = require('./read-coverage'); + * @param {boolean} [opts.autoWrap=false] set to true to allow `return` statements outside of functions. + * @param {boolean} [opts.produceSourceMap=false] set to true to produce a source map for the instrumented code. + * @param {Array} [opts.ignoreClassMethods=[]] set to array of class method names to ignore for coverage. ++ * @param {Array} [opts.ignoreLines=false] enable ignore hints for lines (start, end). + * @param {Function} [opts.sourceMapUrlCallback=null] a callback function that is called when a source map URL + * is found in the original code. This function is called with the source file name and the source map URL. + * @param {boolean} [opts.debug=false] - turn debugging on. +@@ -83,6 +84,7 @@ class Instrumenter { + coverageGlobalScopeFunc: + opts.coverageGlobalScopeFunc, + ignoreClassMethods: opts.ignoreClassMethods, ++ ignoreLines: opts.ignoreLines, + inputSourceMap + }); + +diff --git a/src/visitor.js b/src/visitor.js +index 04e3115f832799fad6d141e8b0aeaa61ac5c98f9..88f8d2420daabecef2ad2def18c8be245b60e253 100644 +--- a/src/visitor.js ++++ b/src/visitor.js +@@ -1,8 +1,17 @@ ++const { readFileSync } = require('fs'); + const { createHash } = require('crypto'); + const { template } = require('@babel/core'); ++const { ++ originalPositionFor, ++ TraceMap, ++ GREATEST_LOWER_BOUND, ++ LEAST_UPPER_BOUND, ++ sourceContentFor ++} = require('@jridgewell/trace-mapping'); + const { defaults } = require('@istanbuljs/schema'); + const { SourceCoverage } = require('./source-coverage'); + const { SHA, MAGIC_KEY, MAGIC_VALUE } = require('./constants'); ++const { getIgnoredLines } = require('./ignored-lines'); + + // pattern for istanbul to ignore a section + const COMMENT_RE = /^\s*istanbul\s+ignore\s+(if|else|next)(?=\W|$)/; +@@ -26,7 +35,8 @@ class VisitState { + sourceFilePath, + inputSourceMap, + ignoreClassMethods = [], +- reportLogic = false ++ reportLogic = false, ++ ignoreLines = false + ) { + this.varName = genVar(sourceFilePath); + this.attrs = {}; +@@ -35,8 +45,13 @@ class VisitState { + + if (typeof inputSourceMap !== 'undefined') { + this.cov.inputSourceMap(inputSourceMap); ++ ++ if (ignoreLines) { ++ this.traceMap = new TraceMap(inputSourceMap); ++ } + } + this.ignoreClassMethods = ignoreClassMethods; ++ this.ignoredLines = new Map(); + this.types = types; + this.sourceMappingURL = null; + this.reportLogic = reportLogic; +@@ -45,7 +60,42 @@ class VisitState { + // should we ignore the node? Yes, if specifically ignoring + // or if the node is generated. + shouldIgnore(path) { +- return this.nextIgnore || !path.node.loc; ++ if (this.nextIgnore || !path.node.loc) { ++ return true; ++ } ++ ++ if (!this.traceMap) { ++ return false; ++ } ++ ++ // Anything that starts between the line ignore hints is ignored ++ const start = originalPositionTryBoth( ++ this.traceMap, ++ path.node.loc.start ++ ); ++ ++ // Generated code ++ if (start.line == null) { ++ return false; ++ } ++ ++ const filename = start.source; ++ let ignoredLines = this.ignoredLines.get(filename); ++ ++ if (!ignoredLines) { ++ const sources = sourceContentFor(this.traceMap, filename); ++ ignoredLines = getIgnoredLines( ++ sources || tryReadFileSync(filename) ++ ); ++ ++ this.ignoredLines.set(filename, ignoredLines); ++ } ++ ++ if (ignoredLines.has(start.line)) { ++ return true; ++ } ++ ++ return false; + } + + // extract the ignore comment hint (next|if|else) or null +@@ -742,6 +792,7 @@ function shouldIgnoreFile(programNode) { + * @param {string} [opts.coverageGlobalScope=this] the global coverage variable scope. + * @param {boolean} [opts.coverageGlobalScopeFunc=true] use an evaluated function to find coverageGlobalScope. + * @param {Array} [opts.ignoreClassMethods=[]] names of methods to ignore by default on classes. ++ * @param {Array} [opts.ignoreLines=false] enable ignore hints for lines (start, end). + * @param {object} [opts.inputSourceMap=undefined] the input source map, that maps the uninstrumented code back to the + * original code. + */ +@@ -756,7 +807,8 @@ function programVisitor(types, sourceFilePath = 'unknown.js', opts = {}) { + sourceFilePath, + opts.inputSourceMap, + opts.ignoreClassMethods, +- opts.reportLogic ++ opts.reportLogic, ++ opts.ignoreLines + ); + return { + enter(path) { +@@ -840,4 +892,29 @@ function programVisitor(types, sourceFilePath = 'unknown.js', opts = {}) { + }; + } + ++function originalPositionTryBoth(sourceMap, { line, column }) { ++ const mapping = originalPositionFor(sourceMap, { ++ line, ++ column, ++ bias: GREATEST_LOWER_BOUND ++ }); ++ if (mapping.source === null) { ++ return originalPositionFor(sourceMap, { ++ line, ++ column, ++ bias: LEAST_UPPER_BOUND ++ }); ++ } else { ++ return mapping; ++ } ++} ++ ++function tryReadFileSync(filename) { ++ try { ++ return readFileSync(filename, 'utf8'); ++ } catch (_) { ++ return undefined; ++ } ++} ++ + module.exports = programVisitor; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 22de00989349..3302d3c177c1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -150,6 +150,9 @@ patchedDependencies: cac@6.7.14: hash: a8f0f3517a47ce716ed90c0cfe6ae382ab763b021a664ada2a608477d0621588 path: patches/cac@6.7.14.patch + istanbul-lib-instrument: + hash: fa76adf262fdb0bf545d5c529c5420e0ae33df7f5e344a6c8a727a2ffc0b0b11 + path: patches/istanbul-lib-instrument.patch istanbul-lib-source-maps: hash: be977704c4b9838da456619fe2421b5e24df2103a25967bd383b2246c88ddf6e path: patches/istanbul-lib-source-maps.patch @@ -596,6 +599,9 @@ importers: packages/coverage-istanbul: dependencies: + '@babel/core': + specifier: ^7.23.9 + version: 7.28.5 '@istanbuljs/schema': specifier: ^0.1.3 version: 0.1.3 @@ -608,9 +614,6 @@ importers: istanbul-lib-coverage: specifier: 'catalog:' version: 3.2.2 - istanbul-lib-instrument: - specifier: ^6.0.3 - version: 6.0.3 istanbul-lib-report: specifier: 'catalog:' version: 3.0.1 @@ -642,6 +645,9 @@ importers: '@types/istanbul-reports': specifier: 'catalog:' version: 3.0.4 + istanbul-lib-instrument: + specifier: ^6.0.3 + version: 6.0.3(patch_hash=fa76adf262fdb0bf545d5c529c5420e0ae33df7f5e344a6c8a727a2ffc0b0b11) istanbul-lib-source-maps: specifier: 'catalog:' version: 5.0.6(patch_hash=be977704c4b9838da456619fe2421b5e24df2103a25967bd383b2246c88ddf6e) @@ -1580,10 +1586,6 @@ packages: '@adobe/css-tools@4.4.0': resolution: {integrity: sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==} - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - '@antfu/eslint-config@6.7.3': resolution: {integrity: sha512-0tYYzY59uLnxWgbP9xpuxpvodTcWDacj439kTAJZB3sn7O0BnPfVxTnRvleGYaKCEALBZkzdC/wCho9FD7ICLw==} hasBin: true @@ -1669,18 +1671,10 @@ packages: resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.26.8': - resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} - engines: {node: '>=6.9.0'} - '@babel/compat-data@7.28.5': resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} engines: {node: '>=6.9.0'} - '@babel/core@7.26.10': - resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==} - engines: {node: '>=6.9.0'} - '@babel/core@7.28.5': resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} engines: {node: '>=6.9.0'} @@ -1693,10 +1687,6 @@ packages: resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.27.0': - resolution: {integrity: sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==} - engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.27.2': resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} engines: {node: '>=6.9.0'} @@ -1726,20 +1716,10 @@ packages: resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.25.9': - resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} - engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.27.1': resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.26.0': - resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - '@babel/helper-module-transforms@7.28.3': resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} engines: {node: '>=6.9.0'} @@ -1782,10 +1762,6 @@ packages: resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.25.9': - resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} - engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.27.1': resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} @@ -1794,10 +1770,6 @@ packages: resolution: {integrity: sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.27.0': - resolution: {integrity: sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==} - engines: {node: '>=6.9.0'} - '@babel/helpers@7.28.4': resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} engines: {node: '>=6.9.0'} @@ -5418,11 +5390,6 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.24.4: - resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - browserslist@4.28.1: resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -5506,9 +5473,6 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001702: - resolution: {integrity: sha512-LoPe/D7zioC0REI5W73PeR1e1MLCipRGq/VkovJnd6Df+QVqT+vT33OXCp8QUd7kA7RZrHWxb1B36OQKI/0gOA==} - caniuse-lite@1.0.30001761: resolution: {integrity: sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==} @@ -6036,9 +6000,6 @@ packages: engines: {node: '>=0.10.0'} hasBin: true - electron-to-chromium@1.5.113: - resolution: {integrity: sha512-wjT2O4hX+wdWPJ76gWSkMhcHAV2PTMX+QetUCPYEdCIe+cxmgzzSSiGRCKW8nuh4mwKZlpv0xvoW7OF2X+wmHg==} - electron-to-chromium@1.5.267: resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} @@ -7818,9 +7779,6 @@ packages: resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - node-releases@2.0.19: - resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} - node-releases@2.0.27: resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} @@ -9374,12 +9332,6 @@ packages: resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} engines: {node: '>=4'} - update-browserslist-db@1.1.1: - resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - update-browserslist-db@1.2.3: resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} hasBin: true @@ -9877,11 +9829,6 @@ snapshots: '@adobe/css-tools@4.4.0': {} - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - '@antfu/eslint-config@6.7.3(@vue/compiler-sfc@3.5.26)(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)(vitest@packages+vitest)': dependencies: '@antfu/install-pkg': 1.1.0 @@ -9974,30 +9921,8 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.26.8': {} - '@babel/compat-data@7.28.5': {} - '@babel/core@7.26.10': - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.5 - '@babel/helper-compilation-targets': 7.27.0 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) - '@babel/helpers': 7.27.0 - '@babel/parser': 7.28.5 - '@babel/template': 7.27.2 - '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 - convert-source-map: 2.0.0 - debug: 4.4.3 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - '@babel/core@7.28.5': dependencies: '@babel/code-frame': 7.27.1 @@ -10030,14 +9955,6 @@ snapshots: dependencies: '@babel/types': 7.28.5 - '@babel/helper-compilation-targets@7.27.0': - dependencies: - '@babel/compat-data': 7.26.8 - '@babel/helper-validator-option': 7.25.9 - browserslist: 4.24.4 - lru-cache: 5.1.1 - semver: 6.3.1 - '@babel/helper-compilation-targets@7.27.2': dependencies: '@babel/compat-data': 7.28.5 @@ -10086,13 +10003,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-module-imports@7.25.9': - dependencies: - '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 - transitivePeerDependencies: - - supports-color - '@babel/helper-module-imports@7.27.1': dependencies: '@babel/traverse': 7.28.5 @@ -10100,15 +10010,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-module-imports': 7.25.9 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.28.5 - transitivePeerDependencies: - - supports-color - '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': dependencies: '@babel/core': 7.28.5 @@ -10155,8 +10056,6 @@ snapshots: '@babel/helper-validator-identifier@7.28.5': {} - '@babel/helper-validator-option@7.25.9': {} - '@babel/helper-validator-option@7.27.1': {} '@babel/helper-wrap-function@7.28.3': @@ -10167,11 +10066,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helpers@7.27.0': - dependencies: - '@babel/template': 7.27.2 - '@babel/types': 7.28.5 - '@babel/helpers@7.28.4': dependencies: '@babel/template': 7.27.2 @@ -13585,13 +13479,6 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.24.4: - dependencies: - caniuse-lite: 1.0.30001702 - electron-to-chromium: 1.5.113 - node-releases: 2.0.19 - update-browserslist-db: 1.1.1(browserslist@4.24.4) - browserslist@4.28.1: dependencies: baseline-browser-mapping: 2.9.11 @@ -13706,8 +13593,6 @@ snapshots: callsites@3.1.0: {} - caniuse-lite@1.0.30001702: {} - caniuse-lite@1.0.30001761: {} ccount@2.0.1: {} @@ -14235,8 +14120,6 @@ snapshots: dependencies: jake: 10.9.4 - electron-to-chromium@1.5.113: {} - electron-to-chromium@1.5.267: {} emoji-regex@8.0.0: {} @@ -15587,9 +15470,9 @@ snapshots: istanbul-lib-coverage@3.2.2: {} - istanbul-lib-instrument@6.0.3: + istanbul-lib-instrument@6.0.3(patch_hash=fa76adf262fdb0bf545d5c529c5420e0ae33df7f5e344a6c8a727a2ffc0b0b11): dependencies: - '@babel/core': 7.26.10 + '@babel/core': 7.28.5 '@babel/parser': 7.27.2 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 @@ -16435,8 +16318,6 @@ snapshots: fetch-blob: 3.2.0 formdata-polyfill: 4.0.10 - node-releases@2.0.19: {} - node-releases@2.0.27: {} nopt@7.2.1: @@ -18260,12 +18141,6 @@ snapshots: upath@1.2.0: {} - update-browserslist-db@1.1.1(browserslist@4.24.4): - dependencies: - browserslist: 4.24.4 - escalade: 3.2.0 - picocolors: 1.1.1 - update-browserslist-db@1.2.3(browserslist@4.28.1): dependencies: browserslist: 4.28.1 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 211f2338cd64..329776cf8cbe 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -41,6 +41,7 @@ patchedDependencies: '@sinonjs/fake-timers@15.0.0': patches/@sinonjs__fake-timers@15.0.0.patch acorn@8.11.3: patches/acorn@8.11.3.patch cac@6.7.14: patches/cac@6.7.14.patch + istanbul-lib-instrument: patches/istanbul-lib-instrument.patch istanbul-lib-source-maps: patches/istanbul-lib-source-maps.patch catalog: diff --git a/test/coverage-test/fixtures/src/ignore-hints.ts b/test/coverage-test/fixtures/src/ignore-hints.ts index 59425a5f452a..c852b4487dbe 100644 --- a/test/coverage-test/fixtures/src/ignore-hints.ts +++ b/test/coverage-test/fixtures/src/ignore-hints.ts @@ -8,6 +8,16 @@ export function second() { return "Second" } +/* istanbul ignore start */ +export function third() { + return "Third" +} + +export function fourth() { + return "fourh" +} +/* istanbul ignore stop */ + // Covered line second() @@ -16,3 +26,5 @@ second() /* istanbul ignore next -- @preserve, Uncovered line istanbul */ second() + +fourth() diff --git a/test/coverage-test/fixtures/src/untested-file.ts b/test/coverage-test/fixtures/src/untested-file.ts index a1304245ad5d..c42d891948fa 100644 --- a/test/coverage-test/fixtures/src/untested-file.ts +++ b/test/coverage-test/fixtures/src/untested-file.ts @@ -35,12 +35,12 @@ export function math(a: number, b: number, operator: '*' | '+') { return multiply(a, b) } - /* todo fix in https://github.com/vitest-dev/vitest/pull/9204 */ + /* istanbul ignore start */ if (operator === '+') { // This line should be excluded return add(a, b) } - /* todo fix in https://github.com/vitest-dev/vitest/pull/9204 */ + /* istanbul ignore stop */ // This line should NOT be covered throw new Error('Unsupported operator') diff --git a/test/coverage-test/test/ignore-hints.test.ts b/test/coverage-test/test/ignore-hints.test.ts index b6d8b26f3f26..84a2a5fbb8f5 100644 --- a/test/coverage-test/test/ignore-hints.test.ts +++ b/test/coverage-test/test/ignore-hints.test.ts @@ -16,15 +16,30 @@ test('ignore hints work', async () => { const fileCoverage = coverageMap.fileCoverageFor('/fixtures/src/ignore-hints.ts') const lines = fileCoverage.getLineCoverage() + // Covered expect(lines[8]).toBeGreaterThanOrEqual(1) - expect(lines[12]).toBeGreaterThanOrEqual(1) + expect(lines[22]).toBeGreaterThanOrEqual(1) + expect(lines[30]).toBeGreaterThanOrEqual(1) + // Ignored start+end lines + expect(lines[11]).toBeUndefined() + expect(lines[12]).toBeUndefined() + expect(lines[13]).toBeUndefined() + expect(lines[14]).toBeUndefined() + expect(lines[15]).toBeUndefined() + expect(lines[16]).toBeUndefined() + expect(lines[17]).toBeUndefined() + expect(lines[18]).toBeUndefined() + expect(lines[19]).toBeUndefined() + + // Ignore istanbul + expect(lines[28]).toBeUndefined() + + // Line 25 = Ignore v8 if (isV8Provider()) { - expect(lines[15]).toBeUndefined() - expect(lines[18]).toBeUndefined() + expect(lines[25]).toBeUndefined() } else { - expect(lines[15]).toBeGreaterThanOrEqual(1) - expect(lines[18]).toBeUndefined() + expect(lines[25]).toBeGreaterThanOrEqual(1) } }) diff --git a/test/coverage-test/test/results-snapshot.test.ts b/test/coverage-test/test/results-snapshot.test.ts index 63ea4aeb1b53..e34b548de673 100644 --- a/test/coverage-test/test/results-snapshot.test.ts +++ b/test/coverage-test/test/results-snapshot.test.ts @@ -32,10 +32,10 @@ test('coverage results matches snapshot', async () => { "statements": "1/4 (25%)", }, "/fixtures/src/untested-file.ts": { - "branches": "0/4 (0%)", + "branches": "0/2 (0%)", "functions": "0/4 (0%)", - "lines": "0/8 (0%)", - "statements": "0/8 (0%)", + "lines": "0/6 (0%)", + "statements": "0/6 (0%)", }, } `) @@ -62,8 +62,6 @@ test('coverage results matches snapshot', async () => { "21": 0, "33": 0, "35": 0, - "39": 0, - "41": 0, "46": 0, "9": 0, },