monocart-coverage-reports 2.13.0 → 2.13.1

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/README.md CHANGED
@@ -671,7 +671,7 @@ const coverageOptions = {
671
671
  ```
672
672
 
673
673
  ## Adding Empty Coverage for Untested Files
674
- By default the untested files will not be included in the coverage report, we can add empty coverage for untested files with option `all`, the untested files will show 0% coverage.
674
+ By default the untested files will not be included in the coverage report. Use `all` to include them with 0% coverage. This also works when no coverage data has been collected: a V8 report is generated from the matching untested files.
675
675
  ```js
676
676
  const coverageOptions = {
677
677
  all: './src',
package/README.zh-Hans.md CHANGED
@@ -674,7 +674,7 @@ const coverageOptions = {
674
674
  ```
675
675
 
676
676
  ## Adding Empty Coverage for Untested Files
677
- 默认,未测试的文件是不会包含到覆盖率报告的,需要使用`all`选项来为这些文件添加一个空的覆盖率,也就是0%
677
+ 默认,未测试的文件不会包含在覆盖率报告中。使用 `all` 选项可将它们以 0% 覆盖率加入报告。即使没有收集到任何覆盖率数据,也会为匹配的未测试文件生成 V8 报告。
678
678
  ```js
679
679
  const coverageOptions = {
680
680
  all: './src',
@@ -1,6 +1,7 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
  const EC = require('eight-colors');
4
+ const { CommentParser } = require('monocart-locator');
4
5
  const { fileURLToPath, pathToFileURL } = require('url');
5
6
  const Concurrency = require('../platform/concurrency.js');
6
7
  const { convertSourceMap } = require('../packages/monocart-coverage-vendor.js');
@@ -8,6 +9,15 @@ const { flattenSourceMaps } = require('./flatten-source-maps.js');
8
9
 
9
10
  const Util = require('../utils/util.js');
10
11
 
12
+ const getSourceMapComments = (source) => {
13
+ if (!source.includes('sourceMappingURL=')) {
14
+ return [];
15
+ }
16
+ return new CommentParser(source).comments
17
+ .map((item) => item.text)
18
+ .filter((comment) => (/^\/[/*][@#][ \t]+sourceMappingURL=/).test(comment));
19
+ };
20
+
11
21
  const defaultSourceMapResolver = async (url = '') => {
12
22
 
13
23
  if (url.startsWith('file:')) {
@@ -48,26 +58,26 @@ const loadSourceMap = async (url, options) => {
48
58
  return defaultSourceMapResolver(url);
49
59
  };
50
60
 
51
- const getSourceMapUrl = (content, url) => {
52
-
53
- const m = content.match(convertSourceMap.mapFileCommentRegex);
54
- if (!m) {
55
- return;
56
- }
57
-
58
- const comment = m.pop();
59
- const r = convertSourceMap.mapFileCommentRegex.exec(comment);
60
- // for some odd reason //# .. captures in 1 and /* .. */ in 2
61
- const filename = r[1] || r[2];
62
-
63
- const urlObj = Util.resolveUrl(filename, url);
64
- if (urlObj) {
65
- return urlObj.toString();
66
- }
61
+ const resolveMapUrl = (filename, url) => {
62
+ const urlObj = Util.resolveUrl(filename, url) || Util.resolveUrl(filename, pathToFileURL(url).toString());
63
+ return urlObj?.toString();
64
+ };
67
65
 
68
- const mapUrl = Util.resolveUrl(filename, pathToFileURL(url).toString());
69
- if (mapUrl) {
70
- return mapUrl.toString();
66
+ const getSourceMapUrl = (comments, url) => {
67
+ for (let i = comments.length - 1; i >= 0; i--) {
68
+ const r = convertSourceMap.mapFileCommentRegex.exec(comments[i]);
69
+ if (!r || r.index !== 0) {
70
+ continue;
71
+ }
72
+ // //# captures in 1 and /* */ in 2
73
+ const filename = r[1] || r[2];
74
+ if (!filename || filename.startsWith('data:')) {
75
+ continue;
76
+ }
77
+ const mapUrl = resolveMapUrl(filename, url);
78
+ if (mapUrl) {
79
+ return mapUrl;
80
+ }
71
81
  }
72
82
  };
73
83
 
@@ -181,15 +191,19 @@ const resolveSourceMap = (data, url) => {
181
191
 
182
192
  };
183
193
 
184
- const getInlineSourceMap = (content) => {
185
- let smc;
186
- try {
187
- smc = convertSourceMap.fromSource(content);
188
- } catch (e) {
189
- // ignore "//# sourceMappingURL=" in a string
190
- // console.log(e);
194
+ const getInlineSourceMap = (comments) => {
195
+ for (let i = comments.length - 1; i >= 0; i--) {
196
+ const comment = comments[i];
197
+ const match = convertSourceMap.commentRegex.exec(comment);
198
+ if (!match || match.index !== 0) {
199
+ continue;
200
+ }
201
+ try {
202
+ return convertSourceMap.fromComment(comment);
203
+ } catch (e) {
204
+ // Ignore invalid inline maps.
205
+ }
191
206
  }
192
- return smc;
193
207
  };
194
208
 
195
209
  const collectSourceMaps = async (v8list, options) => {
@@ -223,15 +237,12 @@ const collectSourceMaps = async (v8list, options) => {
223
237
  sourceMap
224
238
  };
225
239
 
226
- // remove comments if not debug
227
- if (!Util.isDebug()) {
228
- sourceData.source = convertSourceMap.removeComments(source);
229
- }
230
-
240
+ // Keep the original source so V8 offsets remain valid.
231
241
  // check sourceMap only for js
232
242
  if (type === 'js' && !sourceData.sourceMap) {
243
+ const comments = getSourceMapComments(source);
233
244
  // from inline sync
234
- const smc = getInlineSourceMap(source);
245
+ const smc = getInlineSourceMap(comments);
235
246
  if (smc) {
236
247
  sourceData.sourceMap = resolveSourceMap(smc.sourcemap, url);
237
248
  sourcemapList.push({
@@ -242,7 +253,7 @@ const collectSourceMaps = async (v8list, options) => {
242
253
  continue;
243
254
  }
244
255
  // from url async
245
- const sourceMapUrl = getSourceMapUrl(source, item.url);
256
+ const sourceMapUrl = getSourceMapUrl(comments, url);
246
257
  if (sourceMapUrl) {
247
258
  concurrency.addItem({
248
259
  sourceMapUrl,
@@ -6,9 +6,6 @@ const { pathToFileURL, fileURLToPath } = require('url');
6
6
 
7
7
  const { normalizeSourcePath, getSourcePathReplacer } = require('../utils/source-path.js');
8
8
 
9
- // const EC = require('eight-colors');
10
- const { convertSourceMap } = require('../packages/monocart-coverage-vendor.js');
11
-
12
9
  // ========================================================================================================
13
10
 
14
11
  const resolveAllDirList = (input) => {
@@ -133,11 +130,6 @@ const saveUntestedFileSource = async (entryFile, options) => {
133
130
  sourceMap
134
131
  };
135
132
 
136
- // remove comments if not debug
137
- if (!Util.isDebug()) {
138
- sourceData.source = convertSourceMap.removeComments(source);
139
- }
140
-
141
133
  // console.log('save untested file', id, url);
142
134
 
143
135
  await Util.saveSourceCacheFile(sourceData, options);
package/lib/generate.js CHANGED
@@ -321,9 +321,13 @@ const getInputData = async (mcr) => {
321
321
  }
322
322
 
323
323
  if (!dataList.length) {
324
- const dirs = inputList.map((dir) => Util.relativePath(dir));
325
- Util.logError(`Not found coverage data in dir(s): ${dirs.join(', ')}`);
326
- return;
324
+ if (!mcr.options.all) {
325
+ const dirs = inputList.map((dir) => Util.relativePath(dir));
326
+ Util.logError(`Not found coverage data in dir(s): ${dirs.join(', ')}`);
327
+ return;
328
+ }
329
+ // No coverage input: use V8 so `all` can add untested files.
330
+ dataList.push({ type: 'v8', data: [] });
327
331
  }
328
332
 
329
333
  return {