@vitest/coverage-v8 5.0.0-beta.1 → 5.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +4 -1
- package/dist/index.js +43 -6
- package/dist/provider.d.ts +2 -0
- package/dist/provider.js +24 -7
- package/package.json +7 -7
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,17 +1,28 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { readdir, readFile, rm } from 'node:fs/promises';
|
|
1
4
|
import inspector from 'node:inspector/promises';
|
|
5
|
+
import { resolve } from 'node:path';
|
|
2
6
|
import { fileURLToPath } from 'node:url';
|
|
3
7
|
import { provider } from 'std-env';
|
|
4
8
|
import { l as loadProvider } from './load-provider-CdgAx3rL.js';
|
|
5
9
|
import { n as normalize } from './pathe.M-eThtNZ-BTaAGrLg.js';
|
|
6
10
|
|
|
7
|
-
const session = new inspector.Session();
|
|
8
11
|
let enabled = false;
|
|
9
12
|
const mod = {
|
|
10
|
-
|
|
13
|
+
extendedContextCoverageDir: undefined,
|
|
14
|
+
session: null,
|
|
15
|
+
async startCoverage({ isolate, autoAttachSubprocess, reportsDirectory }) {
|
|
11
16
|
if (isolate === false && enabled) {
|
|
12
17
|
return;
|
|
13
18
|
}
|
|
14
19
|
enabled = true;
|
|
20
|
+
if (autoAttachSubprocess) {
|
|
21
|
+
this.extendedContextCoverageDir = resolve(reportsDirectory, "tmp", randomUUID());
|
|
22
|
+
process.env.NODE_V8_COVERAGE = this.extendedContextCoverageDir;
|
|
23
|
+
}
|
|
24
|
+
this.session ||= new inspector.Session();
|
|
25
|
+
const session = this.session;
|
|
15
26
|
session.connect();
|
|
16
27
|
await session.post("Profiler.enable");
|
|
17
28
|
await session.post("Profiler.startPreciseCoverage", {
|
|
@@ -23,15 +34,36 @@ const mod = {
|
|
|
23
34
|
if (provider === "stackblitz") {
|
|
24
35
|
return { result: [] };
|
|
25
36
|
}
|
|
37
|
+
const session = this.session;
|
|
38
|
+
if (!session) {
|
|
39
|
+
throw new Error("V8 provider missing inspector session.");
|
|
40
|
+
}
|
|
26
41
|
const coverage = await session.post("Profiler.takePreciseCoverage");
|
|
27
42
|
const result = [];
|
|
28
43
|
// Reduce amount of data sent over rpc by doing some early result filtering
|
|
29
44
|
for (const entry of coverage.result) {
|
|
30
45
|
if (filterResult(entry)) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
46
|
+
entry.startOffset = options?.moduleExecutionInfo?.get(normalize(fileURLToPath(entry.url)))?.startOffset || 0;
|
|
47
|
+
result.push(entry);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (this.extendedContextCoverageDir && existsSync(this.extendedContextCoverageDir)) {
|
|
51
|
+
const filenames = await readdir(this.extendedContextCoverageDir);
|
|
52
|
+
const contents = await Promise.all(filenames.filter((filename) => filename.endsWith(".json")).map(async (filename) => {
|
|
53
|
+
const path = `${this.extendedContextCoverageDir}/${filename}`;
|
|
54
|
+
const content = await readFile(path, "utf8");
|
|
55
|
+
await rm(path);
|
|
56
|
+
return content;
|
|
57
|
+
}));
|
|
58
|
+
for (const content of contents) {
|
|
59
|
+
const json = JSON.parse(content);
|
|
60
|
+
for (const entry of json.result) {
|
|
61
|
+
if (filterResult(entry)) {
|
|
62
|
+
entry.startOffset = 0;
|
|
63
|
+
entry.isExtendedContext = true;
|
|
64
|
+
result.push(entry);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
35
67
|
}
|
|
36
68
|
}
|
|
37
69
|
return { result };
|
|
@@ -40,9 +72,14 @@ const mod = {
|
|
|
40
72
|
if (isolate === false) {
|
|
41
73
|
return;
|
|
42
74
|
}
|
|
75
|
+
const session = this.session;
|
|
76
|
+
if (!session) {
|
|
77
|
+
throw new Error("V8 provider missing inspector session.");
|
|
78
|
+
}
|
|
43
79
|
await session.post("Profiler.stopPreciseCoverage");
|
|
44
80
|
await session.post("Profiler.disable");
|
|
45
81
|
session.disconnect();
|
|
82
|
+
this.session = null;
|
|
46
83
|
},
|
|
47
84
|
async getProvider() {
|
|
48
85
|
return loadProvider();
|
package/dist/provider.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ import { BaseCoverageProvider, CoverageProvider, Vitest, ReportContext } from 'v
|
|
|
5
5
|
|
|
6
6
|
interface ScriptCoverageWithOffset extends Profiler.ScriptCoverage {
|
|
7
7
|
startOffset: number;
|
|
8
|
+
/** Whether script ran outside Vite, e.g. in sub-processes or worker threads */
|
|
9
|
+
isExtendedContext?: boolean;
|
|
8
10
|
}
|
|
9
11
|
declare class V8CoverageProvider extends BaseCoverageProvider implements CoverageProvider {
|
|
10
12
|
name: "v8";
|
package/dist/provider.js
CHANGED
|
@@ -12,7 +12,7 @@ import c from 'tinyrainbow';
|
|
|
12
12
|
import { BaseCoverageProvider, parseAstAsync } from 'vitest/node';
|
|
13
13
|
import { n as normalize } from './pathe.M-eThtNZ-BTaAGrLg.js';
|
|
14
14
|
|
|
15
|
-
var version = "5.0.0-beta.
|
|
15
|
+
var version = "5.0.0-beta.2";
|
|
16
16
|
|
|
17
17
|
const FILE_PROTOCOL = "file://";
|
|
18
18
|
const debug = createDebug("vitest:coverage");
|
|
@@ -21,6 +21,16 @@ class V8CoverageProvider extends BaseCoverageProvider {
|
|
|
21
21
|
version = version;
|
|
22
22
|
initialize(ctx) {
|
|
23
23
|
this._initialize(ctx);
|
|
24
|
+
if (this.options.autoAttachSubprocess) {
|
|
25
|
+
const isAnyThreadsPools = ctx.projects.some((p) => p.config.pool === "threads" || p.config.pool === "vmThreads");
|
|
26
|
+
if (isAnyThreadsPools) {
|
|
27
|
+
// Work-around for https://github.com/nodejs/node/issues/46378
|
|
28
|
+
// Node never does anything with this directory, it's just required so that
|
|
29
|
+
// the next Workers read **their** env.NODE_V8_COVERAGE.
|
|
30
|
+
// Node never creates this .unused directory at all.
|
|
31
|
+
process.env.NODE_V8_COVERAGE = `${this.coverageFilesDirectory}/.unused`;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
24
34
|
}
|
|
25
35
|
createCoverageMap() {
|
|
26
36
|
return libCoverage.createCoverageMap({});
|
|
@@ -29,15 +39,22 @@ class V8CoverageProvider extends BaseCoverageProvider {
|
|
|
29
39
|
const start = debug.enabled ? performance.now() : 0;
|
|
30
40
|
const coverageMap = this.createCoverageMap();
|
|
31
41
|
let merged = { result: [] };
|
|
42
|
+
const autoAttachSubprocess = this.options.autoAttachSubprocess;
|
|
32
43
|
await this.readCoverageFiles({
|
|
33
44
|
onFileRead(coverage) {
|
|
34
45
|
merged = mergeProcessCovs([merged, coverage]);
|
|
46
|
+
// mergeProcessCovs sometimes loses autoAttachSubprocess
|
|
47
|
+
const fromExtendedContext = autoAttachSubprocess ? coverage.result.filter((r) => r.isExtendedContext) : [];
|
|
35
48
|
// mergeProcessCovs sometimes loses startOffset, e.g. in vue
|
|
36
49
|
merged.result.forEach((result) => {
|
|
37
50
|
if (!result.startOffset) {
|
|
38
51
|
const original = coverage.result.find((r) => r.url === result.url);
|
|
39
52
|
result.startOffset = original?.startOffset || 0;
|
|
40
53
|
}
|
|
54
|
+
if (autoAttachSubprocess && !result.isExtendedContext) {
|
|
55
|
+
const actual = fromExtendedContext.find((r) => r.url === result.url);
|
|
56
|
+
result.isExtendedContext = actual?.isExtendedContext;
|
|
57
|
+
}
|
|
41
58
|
});
|
|
42
59
|
},
|
|
43
60
|
onFinished: async (project, environment) => {
|
|
@@ -189,11 +206,11 @@ class V8CoverageProvider extends BaseCoverageProvider {
|
|
|
189
206
|
}
|
|
190
207
|
});
|
|
191
208
|
}
|
|
192
|
-
async getSources(url, onTransform, functions = []) {
|
|
209
|
+
async getSources(url, onTransform, functions = [], isExtendedContext = false) {
|
|
193
210
|
// TODO: need to standardize file urls before this call somehow, this is messy
|
|
194
211
|
const filepath = url.match(/^file:\/\/\/\w:\//) ? url.slice(8) : removeStartsWith(url, FILE_PROTOCOL);
|
|
195
212
|
// TODO: do we still need to "catch" here? why would it fail?
|
|
196
|
-
const transformResult = await onTransform(filepath).catch(() => null);
|
|
213
|
+
const transformResult = await onTransform(filepath, isExtendedContext).catch(() => null);
|
|
197
214
|
const map = transformResult?.map;
|
|
198
215
|
const code = transformResult?.code;
|
|
199
216
|
if (code == null) {
|
|
@@ -223,8 +240,8 @@ class V8CoverageProvider extends BaseCoverageProvider {
|
|
|
223
240
|
if (environment === "__browser__" && !project.browser) {
|
|
224
241
|
throw new Error(`Cannot access browser module graph because it was torn down.`);
|
|
225
242
|
}
|
|
226
|
-
const onTransform = async (filepath) => {
|
|
227
|
-
const result = await this.transformFile(filepath, project, environment);
|
|
243
|
+
const onTransform = async (filepath, isExtendedContext = false) => {
|
|
244
|
+
const result = await this.transformFile(filepath, project, environment, !isExtendedContext);
|
|
228
245
|
if (result && environment === "__browser__" && project.browser) {
|
|
229
246
|
return {
|
|
230
247
|
...result,
|
|
@@ -258,14 +275,14 @@ class V8CoverageProvider extends BaseCoverageProvider {
|
|
|
258
275
|
index += chunk.length;
|
|
259
276
|
debug("Converting %d/%d", index, scriptCoverages.length);
|
|
260
277
|
}
|
|
261
|
-
await Promise.all(chunk.map(async ({ url, functions, startOffset }) => {
|
|
278
|
+
await Promise.all(chunk.map(async ({ url, functions, startOffset, isExtendedContext }) => {
|
|
262
279
|
let timeout;
|
|
263
280
|
let start;
|
|
264
281
|
if (debug.enabled) {
|
|
265
282
|
start = performance.now();
|
|
266
283
|
timeout = setTimeout(() => debug(c.bgRed(`File "${fileURLToPath(url)}" is taking longer than 3s`)), 3e3);
|
|
267
284
|
}
|
|
268
|
-
const sources = await this.getSources(url, onTransform, functions);
|
|
285
|
+
const sources = await this.getSources(url, onTransform, functions, isExtendedContext);
|
|
269
286
|
coverageMap.merge(await this.remapCoverage(url, startOffset, sources, functions));
|
|
270
287
|
if (debug.enabled) {
|
|
271
288
|
clearTimeout(timeout);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vitest/coverage-v8",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "5.0.0-beta.
|
|
4
|
+
"version": "5.0.0-beta.2",
|
|
5
5
|
"description": "V8 coverage provider for Vitest",
|
|
6
6
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"dist"
|
|
42
42
|
],
|
|
43
43
|
"peerDependencies": {
|
|
44
|
-
"@vitest/browser": "5.0.0-beta.
|
|
45
|
-
"vitest": "5.0.0-beta.
|
|
44
|
+
"@vitest/browser": "5.0.0-beta.2",
|
|
45
|
+
"vitest": "5.0.0-beta.2"
|
|
46
46
|
},
|
|
47
47
|
"peerDependenciesMeta": {
|
|
48
48
|
"@vitest/browser": {
|
|
@@ -59,16 +59,16 @@
|
|
|
59
59
|
"obug": "^2.1.1",
|
|
60
60
|
"std-env": "^4.0.0-rc.1",
|
|
61
61
|
"tinyrainbow": "^3.1.0",
|
|
62
|
-
"@vitest/utils": "5.0.0-beta.
|
|
62
|
+
"@vitest/utils": "5.0.0-beta.2"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@types/istanbul-lib-coverage": "^2.0.6",
|
|
66
66
|
"@types/istanbul-lib-report": "^3.0.3",
|
|
67
67
|
"@types/istanbul-reports": "^3.0.4",
|
|
68
68
|
"pathe": "^2.0.3",
|
|
69
|
-
"@vitest/browser": "5.0.0-beta.
|
|
70
|
-
"
|
|
71
|
-
"vitest": "5.0.0-beta.
|
|
69
|
+
"@vitest/browser-playwright": "5.0.0-beta.2",
|
|
70
|
+
"vitest": "5.0.0-beta.2",
|
|
71
|
+
"@vitest/browser": "5.0.0-beta.2"
|
|
72
72
|
},
|
|
73
73
|
"scripts": {
|
|
74
74
|
"build": "premove dist && rollup -c",
|