Use `useDefineForClassFields` with `coverage-v8` and vitest workspace cause error
Describe the bug
I'm using vitest and a coverage error showed up after I added a static class field:
TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
❯ RangeTree.fromSortedRanges node_modules/.pnpm/@[email protected]/node_modules/@bcoe/v8-coverage/dist/lib/range-tree.js:27:39
❯ normalizeFunctionCov node_modules/.pnpm/@[email protected]/node_modules/@bcoe/v8-coverage/dist/lib/normalize.js:74:41
❯ Object.deepNormalizeScriptCov node_modules/.pnpm/@[email protected]/node_modules/@bcoe/v8-coverage/dist/lib/normalize.js:59:9
❯ mergeScriptCovs node_modules/.pnpm/@[email protected]/node_modules/@bcoe/v8-coverage/dist/lib/merge.js:59:21
❯ mergeProcessCovs node_modules/.pnpm/@[email protected]/node_modules/@bcoe/v8-coverage/dist/lib/merge.js:34:21
❯ node_modules/.pnpm/@[email protected][email protected]/node_modules/@vitest/coverage-v8/dist/provider.js:265:22
❯ V8CoverageProvider.reportCoverage node_modules/.pnpm/@[email protected][email protected]/node_modules/@vitest/coverage-v8/dist/provider.js:262:11
❯ Vitest.reportCoverage node_modules/.pnpm/[email protected]_@[email protected]/node_modules/vitest/dist/vendor/cac.wWT9ELdg.js:11918:7
❯ async node_modules/.pnpm/[email protected]_@[email protected]/node_modules/vitest/dist/vendor/cac.wWT9ELdg.js:11709:7
I tried to minimize the reproduction demo and it seems like it is related to useDefineForClassFields. See the Reproduction section for details.
Reproduction
A minimal reproduction repo is created at: https://github.com/colinaaa/vitest-v8-repro
Just run
-
pnpm install -
pnpm vitest --coverage
to reproduce the issue.
Note that any of these will eliminate the error:
- removing
useDefineForClassFieldsintsconfig.json - replacing
coverage-v8withcoverage-istanbul - removing
static Bar - replacing
static Bazwithrequire.resole('./loader.js') - not using vitest workspace
System Info
System:
OS: macOS 14.0
CPU: (12) arm64 Apple M2 Max
Memory: 14.89 GB / 96.00 GB
Shell: 3.7.0 - /opt/homebrew/bin/fish
Binaries:
Node: 20.11.1 - ~/Library/Caches/fnm_multishells/77527_1709530742451/bin/node
Yarn: 1.22.19 - ~/Library/Caches/fnm_multishells/77527_1709530742451/bin/yarn
npm: 10.2.4 - ~/Library/Caches/fnm_multishells/77527_1709530742451/bin/npm
pnpm: 7.33.6 - ~/Library/Caches/fnm_multishells/77527_1709530742451/bin/pnpm
Browsers:
Chrome: 122.0.6261.94
Firefox Nightly: 115.0
Safari: 17.0
npmPackages:
@vitest/coverage-v8: ^1.3.1 => 1.3.1
vitest: ^1.3.1 => 1.3.1
Used Package Manager
pnpm
Validations
- [X] Follow our Code of Conduct
- [X] Read the Contributing Guidelines.
- [X] Read the docs.
- [X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [X] Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- [X] The provided reproduction is a minimal reproducible example of the bug.
This looks like a bug in @bcoe/v8-coverage (👋 @bcoe). Here's minimal reproduction without Vitest in pure Javascript https://github.com/AriPerkkio/reproductions/tree/v8-merge.
import { mergeProcessCovs } from "@bcoe/v8-coverage";
import { writeFileSync } from "node:fs";
import inspector from "node:inspector";
writeFileSync(
"./source-file.js",
`
export class Foo {
static Baz = process.env["NODE_ENV"] === "test" ? "some" : "thing";
// Remove this will not cause error
static Bar = {};
}
`.trim(),
"utf8"
);
const session = new inspector.Session();
session.connect();
session.post("Profiler.enable");
session.post("Profiler.startPreciseCoverage", {
callCount: true,
detailed: true,
});
await import("./source-file.js");
const coverage = await collectCoverage("source-file.js");
console.log(JSON.stringify(coverage, null, 2));
mergeProcessCovs([coverage]);
async function collectCoverage(filename) {
return new Promise((resolve, reject) => {
session.post("Profiler.takePreciseCoverage", async (error, coverage) => {
if (error) return reject(error);
const result = coverage.result.filter((entry) =>
entry.url.includes(filename)
);
resolve({ result });
});
});
}
$ node index.mjs
{
"result": [
{
"scriptId": "499",
"url": "file:///<root>/reproductions/source-file.js",
"functions": [
{
"functionName": "",
"ranges": [
{
"startOffset": 0,
"endOffset": 148,
"count": 1
}
],
"isBlockCoverage": true
},
{
"functionName": "<static_initializer>",
"ranges": [
{
"startOffset": 130,
"endOffset": 145,
"count": 1
},
{
"startOffset": 69,
"endOffset": 77,
"count": 0
}
],
"isBlockCoverage": true
}
]
}
]
}
/<root>/reproductions/node_modules/.pnpm/@[email protected]/node_modules/@bcoe/v8-coverage/dist/lib/range-tree.js:27
[parent, parentCount] = stack[stack.length - 1];
^
TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
at RangeTree.fromSortedRanges (/<root>/reproductions/node_modules/.pnpm/@[email protected]/node_modules/@bcoe/v8-coverage/dist/lib/range-tree.js:27:39)
at normalizeFunctionCov (/<root>/reproductions/node_modules/.pnpm/@[email protected]/node_modules/@bcoe/v8-coverage/dist/lib/normalize.js:74:41)
at Object.deepNormalizeScriptCov (/<root>/reproductions/node_modules/.pnpm/@[email protected]/node_modules/@bcoe/v8-coverage/dist/lib/normalize.js:59:9)
at mergeScriptCovs (/<root>/reproductions/node_modules/.pnpm/@[email protected]/node_modules/@bcoe/v8-coverage/dist/lib/merge.js:59:21)
at mergeProcessCovs (/<root>/reproductions/node_modules/.pnpm/@[email protected]/node_modules/@bcoe/v8-coverage/dist/lib/merge.js:34:21)
at file:///<root>/reproductions/index.mjs:32:1
Node.js v18.17.1
I'm going to need to strip out the ancient TypeScript from v8-coverage before I can build and release, the toolchain from 6 years ago is very broken.
@colinaaa @AriPerkkio, I believe this should now be addressed in @bcoe/[email protected]. I did a major bump because I tore the library apart a bit to make it build again.