@vitest/coverage-v8 4.0.0-beta.8 → 4.0.0

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/browser.js CHANGED
@@ -1,4 +1,4 @@
1
- import { cdp } from '@vitest/browser/context';
1
+ import { cdp } from 'vitest/browser';
2
2
  import { l as loadProvider } from './load-provider-CdgAx3rL.js';
3
3
 
4
4
  const session = cdp();
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@ import inspector from 'node:inspector/promises';
2
2
  import { fileURLToPath } from 'node:url';
3
3
  import { provider } from 'std-env';
4
4
  import { l as loadProvider } from './load-provider-CdgAx3rL.js';
5
+ import { n as normalize } from './pathe.M-eThtNZ-BTaAGrLg.js';
5
6
 
6
7
  const session = new inspector.Session();
7
8
  let enabled = false;
@@ -29,7 +30,7 @@ const mod = {
29
30
  if (filterResult(entry)) {
30
31
  result.push({
31
32
  ...entry,
32
- startOffset: options?.moduleExecutionInfo?.get(fileURLToPath(entry.url))?.startOffset || 0
33
+ startOffset: options?.moduleExecutionInfo?.get(normalize(fileURLToPath(entry.url)))?.startOffset || 0
33
34
  });
34
35
  }
35
36
  }
@@ -0,0 +1,104 @@
1
+ const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
2
+ function normalizeWindowsPath(input = "") {
3
+ if (!input) {
4
+ return input;
5
+ }
6
+ return input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
7
+ }
8
+
9
+ const _UNC_REGEX = /^[/\\]{2}/;
10
+ const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
11
+ const _DRIVE_LETTER_RE = /^[A-Za-z]:$/;
12
+ const normalize = function(path) {
13
+ if (path.length === 0) {
14
+ return ".";
15
+ }
16
+ path = normalizeWindowsPath(path);
17
+ const isUNCPath = path.match(_UNC_REGEX);
18
+ const isPathAbsolute = isAbsolute(path);
19
+ const trailingSeparator = path[path.length - 1] === "/";
20
+ path = normalizeString(path, !isPathAbsolute);
21
+ if (path.length === 0) {
22
+ if (isPathAbsolute) {
23
+ return "/";
24
+ }
25
+ return trailingSeparator ? "./" : ".";
26
+ }
27
+ if (trailingSeparator) {
28
+ path += "/";
29
+ }
30
+ if (_DRIVE_LETTER_RE.test(path)) {
31
+ path += "/";
32
+ }
33
+ if (isUNCPath) {
34
+ if (!isPathAbsolute) {
35
+ return `//./${path}`;
36
+ }
37
+ return `//${path}`;
38
+ }
39
+ return isPathAbsolute && !isAbsolute(path) ? `/${path}` : path;
40
+ };
41
+ function normalizeString(path, allowAboveRoot) {
42
+ let res = "";
43
+ let lastSegmentLength = 0;
44
+ let lastSlash = -1;
45
+ let dots = 0;
46
+ let char = null;
47
+ for (let index = 0; index <= path.length; ++index) {
48
+ if (index < path.length) {
49
+ char = path[index];
50
+ } else if (char === "/") {
51
+ break;
52
+ } else {
53
+ char = "/";
54
+ }
55
+ if (char === "/") {
56
+ if (lastSlash === index - 1 || dots === 1) ; else if (dots === 2) {
57
+ if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
58
+ if (res.length > 2) {
59
+ const lastSlashIndex = res.lastIndexOf("/");
60
+ if (lastSlashIndex === -1) {
61
+ res = "";
62
+ lastSegmentLength = 0;
63
+ } else {
64
+ res = res.slice(0, lastSlashIndex);
65
+ lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
66
+ }
67
+ lastSlash = index;
68
+ dots = 0;
69
+ continue;
70
+ } else if (res.length > 0) {
71
+ res = "";
72
+ lastSegmentLength = 0;
73
+ lastSlash = index;
74
+ dots = 0;
75
+ continue;
76
+ }
77
+ }
78
+ if (allowAboveRoot) {
79
+ res += res.length > 0 ? "/.." : "..";
80
+ lastSegmentLength = 2;
81
+ }
82
+ } else {
83
+ if (res.length > 0) {
84
+ res += `/${path.slice(lastSlash + 1, index)}`;
85
+ } else {
86
+ res = path.slice(lastSlash + 1, index);
87
+ }
88
+ lastSegmentLength = index - lastSlash - 1;
89
+ }
90
+ lastSlash = index;
91
+ dots = 0;
92
+ } else if (char === "." && dots !== -1) {
93
+ ++dots;
94
+ } else {
95
+ dots = -1;
96
+ }
97
+ }
98
+ return res;
99
+ }
100
+ const isAbsolute = function(p) {
101
+ return _IS_ABSOLUTE_RE.test(p);
102
+ };
103
+
104
+ export { normalize as n };
package/dist/provider.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { promises } from 'node:fs';
2
2
  import { fileURLToPath } from 'node:url';
3
3
  import { mergeProcessCovs } from '@bcoe/v8-coverage';
4
- import { cleanUrl } from '@vitest/utils';
5
4
  import astV8ToIstanbul from 'ast-v8-to-istanbul';
6
5
  import createDebug from 'debug';
7
6
  import libCoverage from 'istanbul-lib-coverage';
@@ -12,112 +11,10 @@ import { parseModule } from 'magicast';
12
11
  import { provider } from 'std-env';
13
12
  import c from 'tinyrainbow';
14
13
  import { BaseCoverageProvider } from 'vitest/coverage';
15
- import { parseAstAsync, isCSSRequest } from 'vitest/node';
14
+ import { parseAstAsync } from 'vitest/node';
15
+ import { n as normalize } from './pathe.M-eThtNZ-BTaAGrLg.js';
16
16
 
17
- const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
18
- function normalizeWindowsPath(input = "") {
19
- if (!input) {
20
- return input;
21
- }
22
- return input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
23
- }
24
-
25
- const _UNC_REGEX = /^[/\\]{2}/;
26
- const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
27
- const _DRIVE_LETTER_RE = /^[A-Za-z]:$/;
28
- const normalize = function(path) {
29
- if (path.length === 0) {
30
- return ".";
31
- }
32
- path = normalizeWindowsPath(path);
33
- const isUNCPath = path.match(_UNC_REGEX);
34
- const isPathAbsolute = isAbsolute(path);
35
- const trailingSeparator = path[path.length - 1] === "/";
36
- path = normalizeString(path, !isPathAbsolute);
37
- if (path.length === 0) {
38
- if (isPathAbsolute) {
39
- return "/";
40
- }
41
- return trailingSeparator ? "./" : ".";
42
- }
43
- if (trailingSeparator) {
44
- path += "/";
45
- }
46
- if (_DRIVE_LETTER_RE.test(path)) {
47
- path += "/";
48
- }
49
- if (isUNCPath) {
50
- if (!isPathAbsolute) {
51
- return `//./${path}`;
52
- }
53
- return `//${path}`;
54
- }
55
- return isPathAbsolute && !isAbsolute(path) ? `/${path}` : path;
56
- };
57
- function normalizeString(path, allowAboveRoot) {
58
- let res = "";
59
- let lastSegmentLength = 0;
60
- let lastSlash = -1;
61
- let dots = 0;
62
- let char = null;
63
- for (let index = 0; index <= path.length; ++index) {
64
- if (index < path.length) {
65
- char = path[index];
66
- } else if (char === "/") {
67
- break;
68
- } else {
69
- char = "/";
70
- }
71
- if (char === "/") {
72
- if (lastSlash === index - 1 || dots === 1) ; else if (dots === 2) {
73
- if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
74
- if (res.length > 2) {
75
- const lastSlashIndex = res.lastIndexOf("/");
76
- if (lastSlashIndex === -1) {
77
- res = "";
78
- lastSegmentLength = 0;
79
- } else {
80
- res = res.slice(0, lastSlashIndex);
81
- lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
82
- }
83
- lastSlash = index;
84
- dots = 0;
85
- continue;
86
- } else if (res.length > 0) {
87
- res = "";
88
- lastSegmentLength = 0;
89
- lastSlash = index;
90
- dots = 0;
91
- continue;
92
- }
93
- }
94
- if (allowAboveRoot) {
95
- res += res.length > 0 ? "/.." : "..";
96
- lastSegmentLength = 2;
97
- }
98
- } else {
99
- if (res.length > 0) {
100
- res += `/${path.slice(lastSlash + 1, index)}`;
101
- } else {
102
- res = path.slice(lastSlash + 1, index);
103
- }
104
- lastSegmentLength = index - lastSlash - 1;
105
- }
106
- lastSlash = index;
107
- dots = 0;
108
- } else if (char === "." && dots !== -1) {
109
- ++dots;
110
- } else {
111
- dots = -1;
112
- }
113
- }
114
- return res;
115
- }
116
- const isAbsolute = function(p) {
117
- return _IS_ABSOLUTE_RE.test(p);
118
- };
119
-
120
- var version = "4.0.0-beta.8";
17
+ var version = "4.0.0";
121
18
 
122
19
  const FILE_PROTOCOL = "file://";
123
20
  const debug = createDebug("vitest:coverage");
@@ -198,7 +95,6 @@ class V8CoverageProvider extends BaseCoverageProvider {
198
95
  return parseModule(await promises.readFile(configFilePath, "utf8"));
199
96
  }
200
97
  async getCoverageMapForUncoveredFiles(testedFiles) {
201
- const transformResults = normalizeTransformResults(this.ctx.vite.environments);
202
98
  const transform = this.createUncoveredFileTransformer(this.ctx);
203
99
  const uncoveredFiles = await this.getUntestedFiles(testedFiles);
204
100
  let index = 0;
@@ -216,8 +112,8 @@ class V8CoverageProvider extends BaseCoverageProvider {
216
112
  timeout = setTimeout(() => debug(c.bgRed(`File "${filename}" is taking longer than 3s`)), 3e3);
217
113
  }
218
114
  // Do not use pathToFileURL to avoid encoding filename parts
219
- const url = `file://${filename.startsWith("/") ? "" : "/"}${filename}`;
220
- const sources = await this.getSources(url, transformResults, transform);
115
+ const url = `file://${filename[0] === "/" ? "" : "/"}${filename}`;
116
+ const sources = await this.getSources(url, transform);
221
117
  coverageMap.merge(await this.remapCoverage(url, 0, sources, []));
222
118
  if (debug.enabled) {
223
119
  clearTimeout(timeout);
@@ -260,6 +156,11 @@ class V8CoverageProvider extends BaseCoverageProvider {
260
156
  if (type === "statement" && node.type === "VariableDeclarator" && node.id.type === "Identifier" && node.id.name === "__vite_ssr_export_default__") {
261
157
  return true;
262
158
  }
159
+ // CJS imports as ternaries - e.g.
160
+ // const React = __vite__cjsImport0_react.__esModule ? __vite__cjsImport0_react.default : __vite__cjsImport0_react;
161
+ if (type === "branch" && node.type === "ConditionalExpression" && node.test.type === "MemberExpression" && node.test.object.type === "Identifier" && node.test.object.name.startsWith("__vite__cjsImport") && node.test.property.type === "Identifier" && node.test.property.name === "__esModule") {
162
+ return true;
163
+ }
263
164
  // in-source test with "if (import.meta.vitest)"
264
165
  if ((type === "branch" || type === "statement") && node.type === "IfStatement" && node.test.type === "MemberExpression" && node.test.property.type === "Identifier" && node.test.property.name === "vitest") {
265
166
  // SSR
@@ -286,15 +187,12 @@ class V8CoverageProvider extends BaseCoverageProvider {
286
187
  }
287
188
  });
288
189
  }
289
- async getSources(url, transformResults, onTransform, functions = []) {
290
- const filePath = normalize(fileURLToPath(url));
291
- let transformResult = transformResults.get(filePath);
292
- if (!transformResult) {
293
- transformResult = await onTransform(removeStartsWith(url, FILE_PROTOCOL)).catch(() => undefined);
294
- }
190
+ async getSources(url, onTransform, functions = []) {
191
+ const transformResult = await onTransform(removeStartsWith(url, FILE_PROTOCOL)).catch(() => undefined);
295
192
  const map = transformResult?.map;
296
193
  const code = transformResult?.code;
297
194
  if (code == null) {
195
+ const filePath = normalize(fileURLToPath(url));
298
196
  const original = await promises.readFile(filePath, "utf-8").catch(() => {
299
197
  // If file does not exist construct a dummy source for it.
300
198
  // These can be files that were generated dynamically during the test run and were removed after it.
@@ -320,11 +218,6 @@ class V8CoverageProvider extends BaseCoverageProvider {
320
218
  if (environment === "__browser__" && !project.browser) {
321
219
  throw new Error(`Cannot access browser module graph because it was torn down.`);
322
220
  }
323
- const moduleGraph = environment === "__browser__" ? project.browser.vite.environments.client.moduleGraph : project.vite.environments[environment]?.moduleGraph;
324
- if (!moduleGraph) {
325
- throw new Error(`Module graph for environment ${environment} was not defined.`);
326
- }
327
- const transformResults = normalizeTransformResults({ [environment]: { moduleGraph } });
328
221
  async function onTransform(filepath) {
329
222
  if (environment === "__browser__" && project.browser) {
330
223
  const result = await project.browser.vite.transformRequest(removeStartsWith(filepath, project.config.root));
@@ -348,11 +241,11 @@ class V8CoverageProvider extends BaseCoverageProvider {
348
241
  result.url = `${FILE_PROTOCOL}${project.config.root}${result.url}`;
349
242
  }
350
243
  }
351
- // Ignore all CSS requests, so we don't override the actual code coverage
352
- // In cases where CSS and JS are in the same file (.vue, .svelte)
353
- // The file has a `.vue` extension, but the URL has `lang.css` query
354
- if (!isCSSRequest(result.url) && this.isIncluded(fileURLToPath(result.url))) {
355
- scriptCoverages.push(result);
244
+ if (this.isIncluded(fileURLToPath(result.url))) {
245
+ scriptCoverages.push({
246
+ ...result,
247
+ url: decodeURIComponent(result.url)
248
+ });
356
249
  }
357
250
  }
358
251
  const coverageMap = this.createCoverageMap();
@@ -369,7 +262,7 @@ class V8CoverageProvider extends BaseCoverageProvider {
369
262
  start = performance.now();
370
263
  timeout = setTimeout(() => debug(c.bgRed(`File "${fileURLToPath(url)}" is taking longer than 3s`)), 3e3);
371
264
  }
372
- const sources = await this.getSources(url, transformResults, onTransform, functions);
265
+ const sources = await this.getSources(url, onTransform, functions);
373
266
  coverageMap.merge(await this.remapCoverage(url, startOffset, sources, functions));
374
267
  if (debug.enabled) {
375
268
  clearTimeout(timeout);
@@ -395,19 +288,6 @@ function findLongestFunctionLength(functions) {
395
288
  return Math.max(previous, maxEndOffset);
396
289
  }, 0);
397
290
  }
398
- function normalizeTransformResults(environments) {
399
- const normalized = new Map();
400
- for (const environmentName in environments) {
401
- const moduleGraph = environments[environmentName].moduleGraph;
402
- for (const [key, value] of moduleGraph.idToModuleMap) {
403
- const cleanEntry = cleanUrl(key);
404
- if (value.transformResult && !normalized.has(cleanEntry)) {
405
- normalized.set(cleanEntry, value.transformResult);
406
- }
407
- }
408
- }
409
- return normalized;
410
- }
411
291
  function removeStartsWith(filepath, start) {
412
292
  if (filepath.startsWith(start)) {
413
293
  return filepath.slice(start.length);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vitest/coverage-v8",
3
3
  "type": "module",
4
- "version": "4.0.0-beta.8",
4
+ "version": "4.0.0",
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": "4.0.0-beta.8",
45
- "vitest": "4.0.0-beta.8"
44
+ "@vitest/browser": "4.0.0",
45
+ "vitest": "4.0.0"
46
46
  },
47
47
  "peerDependenciesMeta": {
48
48
  "@vitest/browser": {
@@ -51,16 +51,16 @@
51
51
  },
52
52
  "dependencies": {
53
53
  "@bcoe/v8-coverage": "^1.0.2",
54
- "ast-v8-to-istanbul": "^0.3.3",
55
- "debug": "^4.4.1",
54
+ "ast-v8-to-istanbul": "^0.3.5",
55
+ "debug": "^4.4.3",
56
56
  "istanbul-lib-coverage": "^3.2.2",
57
57
  "istanbul-lib-report": "^3.0.1",
58
58
  "istanbul-lib-source-maps": "^5.0.6",
59
- "istanbul-reports": "^3.1.7",
59
+ "istanbul-reports": "^3.2.0",
60
60
  "magicast": "^0.3.5",
61
61
  "std-env": "^3.9.0",
62
- "tinyrainbow": "^2.0.0",
63
- "@vitest/utils": "4.0.0-beta.8"
62
+ "tinyrainbow": "^3.0.3",
63
+ "@vitest/utils": "4.0.0"
64
64
  },
65
65
  "devDependencies": {
66
66
  "@types/debug": "^4.1.12",
@@ -69,11 +69,11 @@
69
69
  "@types/istanbul-lib-source-maps": "^4.0.4",
70
70
  "@types/istanbul-reports": "^3.0.4",
71
71
  "pathe": "^2.0.3",
72
- "@vitest/browser": "4.0.0-beta.8",
73
- "vitest": "4.0.0-beta.8"
72
+ "@vitest/browser": "4.0.0",
73
+ "vitest": "4.0.0"
74
74
  },
75
75
  "scripts": {
76
- "build": "rimraf dist && rollup -c",
76
+ "build": "premove dist && rollup -c",
77
77
  "dev": "rollup -c --watch --watch.include 'src/**'"
78
78
  }
79
79
  }