monocart-coverage-reports 2.11.0 โ†’ 2.11.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
@@ -1,10 +1,12 @@
1
1
  # Monocart Coverage Reports
2
2
 
3
- [![](https://img.shields.io/npm/v/monocart-coverage-reports)](https://www.npmjs.com/package/monocart-coverage-reports)
4
- [![](https://devimg.vercel.app/npm/downloads/monocart-coverage-reports?label={total}%20downloads/month)](https://www.npmjs.com/package/monocart-coverage-reports)
5
- ![](https://img.shields.io/librariesio/github/cenfun/monocart-coverage-reports)
6
- ![](https://img.shields.io/github/license/cenfun/monocart-coverage-reports)
7
- ![](https://img.shields.io/github/actions/workflow/status/cenfun/monocart-coverage-reports/ci.yml)
3
+ [![npm](https://img.shields.io/npm/v/monocart-coverage-reports)](https://www.npmjs.com/package/monocart-coverage-reports)
4
+ ![license](https://img.shields.io/github/license/cenfun/monocart-coverage-reports)
5
+ ![build](https://img.shields.io/github/actions/workflow/status/cenfun/monocart-coverage-reports/ci.yml)
6
+ [![install size](https://packagephobia.com/badge?p=monocart-coverage-reports)](https://packagephobia.com/result?p=monocart-coverage-reports)
7
+ [![npm graph](https://img.shields.io/badge/npm-graph-blue)](https://npmgraph.js.org/?q=monocart-coverage-reports)
8
+ ![dependencies](https://img.shields.io/librariesio/github/cenfun/monocart-coverage-reports)
9
+ [![downloads](https://devimg.vercel.app/npm/downloads/monocart-coverage-reports?label={total}%20downloads/month)](https://www.npmjs.com/package/monocart-coverage-reports)
8
10
 
9
11
  ๐ŸŒ English | [็ฎ€ไฝ“ไธญๆ–‡](README.zh-Hans.md)
10
12
 
@@ -485,6 +487,16 @@ export interface ScriptCoverage {
485
487
  export type V8CoverageData = ScriptCoverage[];
486
488
  ```
487
489
 
490
+ | JavaScript Runtime | V8 Coverage | |
491
+ | :--------------| :----: | :---------------------- |
492
+ | Chrome (65%) | โœ… | Chromium-based |
493
+ | Safari (18%) | โŒ | |
494
+ | Edge (5%) | โœ… | Chromium-based |
495
+ | Firefox (2%) | โŒ | |
496
+ | Node.js | โœ… | |
497
+ | Deno | โŒ | [issue](https://github.com/denoland/deno/issues/23359) |
498
+ | Bun | โŒ | |
499
+
488
500
  ## Filtering Results
489
501
  ### Using `entryFilter` and `sourceFilter` to filter the results for V8 report
490
502
  When V8 coverage data collected, it actually contains the data of all entry files, for example:
package/README.zh-Hans.md CHANGED
@@ -1,10 +1,12 @@
1
1
  # Monocart Coverage Reports
2
2
 
3
- [![](https://img.shields.io/npm/v/monocart-coverage-reports)](https://www.npmjs.com/package/monocart-coverage-reports)
4
- [![](https://devimg.vercel.app/npm/downloads/monocart-coverage-reports?label={total}%20downloads/month)](https://www.npmjs.com/package/monocart-coverage-reports)
5
- ![](https://img.shields.io/librariesio/github/cenfun/monocart-coverage-reports)
6
- ![](https://img.shields.io/github/license/cenfun/monocart-coverage-reports)
7
- ![](https://img.shields.io/github/actions/workflow/status/cenfun/monocart-coverage-reports/ci.yml)
3
+ [![npm](https://img.shields.io/npm/v/monocart-coverage-reports)](https://www.npmjs.com/package/monocart-coverage-reports)
4
+ ![license](https://img.shields.io/github/license/cenfun/monocart-coverage-reports)
5
+ ![build](https://img.shields.io/github/actions/workflow/status/cenfun/monocart-coverage-reports/ci.yml)
6
+ [![install size](https://packagephobia.com/badge?p=monocart-coverage-reports)](https://packagephobia.com/result?p=monocart-coverage-reports)
7
+ [![npm graph](https://img.shields.io/badge/npm-graph-blue)](https://npmgraph.js.org/?q=monocart-coverage-reports)
8
+ ![dependencies](https://img.shields.io/librariesio/github/cenfun/monocart-coverage-reports)
9
+ [![downloads](https://devimg.vercel.app/npm/downloads/monocart-coverage-reports?label={total}%20downloads/month)](https://www.npmjs.com/package/monocart-coverage-reports)
8
10
 
9
11
  ๐ŸŒ [English](README.md) | ็ฎ€ไฝ“ไธญๆ–‡
10
12
 
@@ -489,6 +491,16 @@ export interface ScriptCoverage {
489
491
  export type V8CoverageData = ScriptCoverage[];
490
492
  ```
491
493
 
494
+ | JavaScript Runtime | V8 Coverage | |
495
+ | :--------------| :----: | :---------------------- |
496
+ | Chrome (65%) | โœ… | Chromium-based |
497
+ | Safari (18%) | โŒ | |
498
+ | Edge (5%) | โœ… | Chromium-based |
499
+ | Firefox (2%) | โŒ | |
500
+ | Node.js | โœ… | |
501
+ | Deno | โŒ | [issue](https://github.com/denoland/deno/issues/23359) |
502
+ | Bun | โŒ | |
503
+
492
504
  ## Filtering Results
493
505
  ## Using `entryFilter` and `sourceFilter` to filter the results for V8 report
494
506
  ๅฝ“ๆ”ถ้›†ๅˆฐV8็š„่ฆ†็›–ๆ•ฐๆฎๆ—ถ๏ผŒๅฎƒๅฎž้™…ไธŠๅŒ…ๅซไบ†ๆ‰€ๆœ‰็š„ๅ…ฅๅฃๆ–‡ไปถ็š„่ฆ†็›–็އๆ•ฐๆฎ, ๆฏ”ๅฆ‚ๆœ‰ไปฅไธ‹3ไธชๆ–‡ไปถ:
@@ -88,6 +88,9 @@ module.exports = {
88
88
  // {boolean} Indicates whether to clean previous cache in output dir before generating report. Defaults to false.
89
89
  cleanCache: false,
90
90
 
91
+ // {number} gc threshold
92
+ gc: null,
93
+
91
94
  // {function} onEntry hook
92
95
  // onEntry: async (entry) => {}
93
96
  onEntry: null,
package/lib/generate.js CHANGED
@@ -340,7 +340,7 @@ const resolveEntrySource = (entry, sourceMapCache, sourceCache) => {
340
340
  const url = entry.url;
341
341
 
342
342
  // source from `source-id.json`
343
- const sourceData = sourceCache[url];
343
+ const sourceData = sourceCache.get(url);
344
344
  if (sourceData) {
345
345
  entry.source = sourceData.source;
346
346
  return;
@@ -424,7 +424,7 @@ const readCoverageData = async (dir, filename, entryFilter, sourceCache) => {
424
424
  };
425
425
 
426
426
  const readSourceList = async (dir, sourceList) => {
427
- const sourceCache = {};
427
+ const sourceCache = new Map();
428
428
 
429
429
  for (const filename of sourceList) {
430
430
  const content = await Util.readFile(path.resolve(dir, filename));
@@ -436,7 +436,7 @@ const readSourceList = async (dir, sourceList) => {
436
436
  continue;
437
437
  }
438
438
  if (json.url) {
439
- sourceCache[json.url] = json;
439
+ sourceCache.set(json.url, json);
440
440
  }
441
441
  }
442
442
 
@@ -476,16 +476,16 @@ const readFromDir = async (mcr, dir) => {
476
476
 
477
477
  const entryFilter = mcr.getEntryFilter();
478
478
 
479
- const results = [];
480
479
  for (const filename of coverageList) {
481
480
  const coverageData = await readCoverageData(dir, filename, entryFilter, sourceCache);
482
481
  if (coverageData) {
483
- const res = await mcr.add(coverageData);
484
- results.push(res);
482
+ await mcr.add(coverageData);
485
483
  }
486
484
  }
487
485
 
488
- return results;
486
+ // GC
487
+ sourceCache.clear();
488
+
489
489
  };
490
490
 
491
491
  module.exports = {
package/lib/index.d.ts CHANGED
@@ -404,6 +404,13 @@ declare namespace MCR {
404
404
  */
405
405
  cleanCache?: boolean;
406
406
 
407
+ /**
408
+ * {number} gc threshold
409
+ * for example: sets gc to 1024 means that force gc when the memory > 1024M at certain critical stages
410
+ * https://nodejs.org/docs/latest/api/v8.html#v8setflagsfromstringflags
411
+ */
412
+ gc?: number;
413
+
407
414
  /** (V8 only) {function} onEntry hook */
408
415
  onEntry?: (entry: V8CoverageEntry) => Promise<void>;
409
416
 
package/lib/index.js CHANGED
@@ -68,6 +68,10 @@ class CoverageReport {
68
68
  // init logging for clean after generated
69
69
  this.logging = Util.initLoggingLevel(this.options.logging);
70
70
 
71
+ if (Util.isNum(this.options.gc)) {
72
+ Util.setGC(this.options.gc);
73
+ }
74
+
71
75
  // init outputDir
72
76
  const outputDir = `${this.options.outputDir || defaultOptions.outputDir}`;
73
77
  this.options.outputDir = outputDir;
@@ -124,9 +128,8 @@ class CoverageReport {
124
128
  // add coverage from dir
125
129
  async addFromDir(dir) {
126
130
  const time_start = Date.now();
127
- const results = await readFromDir(this, dir);
131
+ await readFromDir(this, dir);
128
132
  Util.logTime(`added from dir: ${dir}`, time_start);
129
- return results;
130
133
  }
131
134
 
132
135
  // generate report
@@ -144,7 +144,7 @@ const addUntestedFiles = async (istanbulData, options) => {
144
144
 
145
145
  };
146
146
 
147
- const mergeIstanbulDataList = (dataList) => {
147
+ const mergeIstanbulDataList = (dataList, options) => {
148
148
  const istanbulCoverageList = dataList.map((it) => it.data);
149
149
  const coverageMap = istanbulLibCoverage.createCoverageMap();
150
150
  istanbulCoverageList.forEach((coverage) => {
@@ -155,7 +155,7 @@ const mergeIstanbulDataList = (dataList) => {
155
155
  };
156
156
 
157
157
  const mergeIstanbulCoverage = async (dataList, options) => {
158
- const istanbulData = mergeIstanbulDataList(dataList);
158
+ const istanbulData = mergeIstanbulDataList(dataList, options);
159
159
  await addUntestedFiles(istanbulData, options);
160
160
  return istanbulData;
161
161
  };
@@ -5,14 +5,14 @@ const { ZipFile } = require('../packages/monocart-coverage-vendor.js');
5
5
  const { mergeIstanbulDataList } = require('../istanbul/istanbul.js');
6
6
  const { mergeV8DataList } = require('../v8/v8.js');
7
7
 
8
- const getMergedData = (type, dataList) => {
8
+ const getMergedData = (type, dataList, options) => {
9
9
  if (type === 'istanbul') {
10
- return mergeIstanbulDataList(dataList);
10
+ return mergeIstanbulDataList(dataList, options);
11
11
  }
12
- return mergeV8DataList(dataList);
12
+ return mergeV8DataList(dataList, options);
13
13
  };
14
14
 
15
- const mergeReport = async (rawDir, rawParent) => {
15
+ const mergeReport = async (rawDir, options) => {
16
16
  const coverageFiles = fs.readdirSync(rawDir).filter((n) => n.endsWith('.json') && n.startsWith('coverage-'));
17
17
  // console.log(coverageFiles);
18
18
 
@@ -29,7 +29,7 @@ const mergeReport = async (rawDir, rawParent) => {
29
29
  Util.rmSync(jsonPath);
30
30
  }
31
31
 
32
- const mergedData = await getMergedData(type, dataList);
32
+ const mergedData = await getMergedData(type, dataList, options);
33
33
 
34
34
  const dataId = Util.uid();
35
35
  const results = {
@@ -99,7 +99,7 @@ const rawReport = async (reportData, reportOptions, options) => {
99
99
 
100
100
  // merge
101
101
  if (rawOptions.merge) {
102
- await mergeReport(rawDir, rawParent);
102
+ await mergeReport(rawDir, options);
103
103
  }
104
104
 
105
105
  // zip
@@ -0,0 +1,9 @@
1
+ const v8 = require('node:v8');
2
+ const vm = require('node:vm');
3
+
4
+ if (typeof global.gc !== 'function') {
5
+ v8.setFlagsFromString('--expose_gc');
6
+ global.gc = vm.runInNewContext('gc');
7
+ }
8
+
9
+ module.exports = global.gc;
package/lib/utils/util.js CHANGED
@@ -3,6 +3,7 @@ const { writeFile, readFile } = require('fs/promises');
3
3
  const path = require('path');
4
4
  const os = require('os');
5
5
  const crypto = require('crypto');
6
+
6
7
  const EC = require('eight-colors');
7
8
  const CG = require('console-grid');
8
9
  const acornWalk = require('acorn-walk');
@@ -12,6 +13,7 @@ const request = require('./request.js');
12
13
  const version = require('../../package.json').version;
13
14
  const markdownGrid = require('./markdown.js');
14
15
  const { mergeV8Coverage } = require('./merge/merge.js');
16
+ const gc = require('./gc.js');
15
17
 
16
18
  const {
17
19
  findUpSync, supportsColor, minimatch
@@ -37,6 +39,10 @@ const Util = {
37
39
  markdownGrid,
38
40
  mergeV8Coverage,
39
41
 
42
+ forceGC: () => {
43
+ gc();
44
+ },
45
+
40
46
  relativePath: function(p, root) {
41
47
  p = `${p}`;
42
48
  root = `${root || Util.root}`;
@@ -863,8 +869,28 @@ const Util = {
863
869
  console.log(`[MCR] ${message} before ${lengthBefore} => after ${lengthAfter}`);
864
870
  },
865
871
 
872
+ setGC: (threshold) => {
873
+ if (!Util.isNum(threshold)) {
874
+ threshold = 1024;
875
+ }
876
+ Util.gcThreshold = threshold;
877
+ },
878
+
879
+ getMemory: () => {
880
+ const { heapUsed } = process.memoryUsage();
881
+ const memory = parseFloat((heapUsed / 1024 ** 2).toFixed(1));
882
+ return memory;
883
+ },
884
+
866
885
  // time is debug level, fix the log info, for checking snapshot
867
886
  logTime: (message, time_start) => {
887
+
888
+ // memory gc
889
+ let memory = Util.getMemory();
890
+ if (Util.gcThreshold && Util.gcThreshold < memory) {
891
+ Util.forceGC();
892
+ }
893
+
868
894
  if (Util.loggingLevel < Util.loggingLevels.debug && !process.env.MCR_LOG_TIME) {
869
895
  return;
870
896
  }
@@ -872,9 +898,7 @@ const Util = {
872
898
  const durationH = Util.TF(duration);
873
899
  const ls = [`[MCR] ${message}`];
874
900
 
875
- // memory
876
- const { heapUsed } = process.memoryUsage();
877
- const memory = parseFloat((heapUsed / 1024 ** 2).toFixed(1));
901
+ memory = Util.getMemory();
878
902
  ls.push(` (memory: ${memory}MB)`);
879
903
 
880
904
  // time
package/lib/v8/v8.js CHANGED
@@ -164,7 +164,7 @@ const mergeCssRanges = (itemList) => {
164
164
  // ranges: [ {start, end} ]
165
165
  const ranges = dedupeFlatRanges(concatRanges);
166
166
 
167
- resolve(ranges || []);
167
+ resolve(ranges);
168
168
  });
169
169
  };
170
170
 
@@ -173,14 +173,19 @@ const mergeJsFunctions = async (itemList) => {
173
173
  return res.functions;
174
174
  };
175
175
 
176
- const mergeV8DataList = async (dataList) => {
177
- let allList = [];
178
- dataList.forEach((d) => {
179
- allList = allList.concat(d.data);
180
- });
176
+ const mergeV8DataList = async (dataList, options) => {
177
+ const allList = dataList.map((d) => d.data).flat();
181
178
 
182
- // remove empty items
183
- const coverageList = allList.filter((it) => !it.empty);
179
+ // separate coverage and empty items
180
+ const coverageList = [];
181
+ const allEmptyList = [];
182
+ allList.forEach((it) => {
183
+ if (it.empty) {
184
+ allEmptyList.push(it);
185
+ } else {
186
+ coverageList.push(it);
187
+ }
188
+ });
184
189
 
185
190
  // connect all functions and ranges
186
191
  const itemMap = {};
@@ -215,7 +220,7 @@ const mergeV8DataList = async (dataList) => {
215
220
 
216
221
  // first time filter for empty, (not for sources)
217
222
  // empty and not in item map
218
- const emptyList = allList.filter((it) => it.empty).filter((it) => {
223
+ const emptyList = allEmptyList.filter((it) => {
219
224
  if (itemMap[it.id]) {
220
225
  return false;
221
226
  }
@@ -225,16 +230,15 @@ const mergeV8DataList = async (dataList) => {
225
230
  return true;
226
231
  });
227
232
 
228
- // empty list + merged list
229
- const mergedList = emptyList.concat(Object.values(itemMap));
230
-
233
+ // merged list + empty list
234
+ const mergedList = Object.values(itemMap).concat(emptyList);
231
235
 
232
236
  return mergedList;
233
237
  };
234
238
 
235
239
  const mergeV8Coverage = async (dataList, sourceCache, options) => {
236
240
 
237
- const mergedList = await mergeV8DataList(dataList);
241
+ const mergedList = await mergeV8DataList(dataList, options);
238
242
 
239
243
  // try to load coverage and source by id
240
244
  for (const entry of mergedList) {
@@ -254,6 +258,9 @@ const mergeV8Coverage = async (dataList, sourceCache, options) => {
254
258
 
255
259
  }
256
260
 
261
+ // GC
262
+ sourceCache.clear();
263
+
257
264
  return mergedList;
258
265
  };
259
266
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monocart-coverage-reports",
3
- "version": "2.11.0",
3
+ "version": "2.11.1",
4
4
  "description": "A code coverage tool to generate native V8 reports or Istanbul reports.",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {
@@ -59,7 +59,7 @@
59
59
  "dev": "npx sf d app",
60
60
  "open": "node ./scripts/open.js",
61
61
  "eol": "git rm -rf --cached . && git reset --hard HEAD",
62
- "patch": "npm version patch && npm run build && npm run test && npm publish",
62
+ "patch": "npm run build && npm run test && npx sf publish patch -r",
63
63
  "beta": "npm version prerelease --preid=beta && npm run build && npm run test && npm publish --tag beta"
64
64
  },
65
65
  "workspaces": [
@@ -95,7 +95,7 @@
95
95
  "convert-source-map": "^2.0.0",
96
96
  "diff-sequences": "^29.6.3",
97
97
  "esbuild": "^0.24.0",
98
- "eslint": "~9.11.1",
98
+ "eslint": "~9.12.0",
99
99
  "eslint-config-plus": "^2.0.2",
100
100
  "eslint-plugin-html": "^8.1.2",
101
101
  "eslint-plugin-vue": "^9.28.0",