monocart-coverage-reports 2.13.2 → 3.1.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.
Files changed (69) hide show
  1. package/README.md +314 -116
  2. package/README.zh-Hans.md +315 -117
  3. package/lib/assets.js +6 -6
  4. package/lib/cli.js +191 -95
  5. package/lib/client/cdp-client.js +74 -43
  6. package/lib/client/coverage-client.js +24 -8
  7. package/lib/client/ws-session.js +115 -37
  8. package/lib/converter/ast-visitor.js +5 -7
  9. package/lib/converter/ast.js +29 -8
  10. package/lib/converter/collect-source-maps.js +42 -21
  11. package/lib/converter/converter.js +124 -129
  12. package/lib/converter/css-coverage.js +76 -0
  13. package/lib/converter/fake-source-coverage.js +64 -0
  14. package/lib/converter/find-original-range.js +214 -6
  15. package/lib/converter/flatten-source-maps.js +2 -4
  16. package/lib/converter/ignore.js +2 -4
  17. package/lib/converter/info-branch.js +5 -3
  18. package/lib/converter/info-function.js +5 -3
  19. package/lib/converter/info-statement.js +5 -3
  20. package/lib/converter/range-index.js +78 -0
  21. package/lib/converter/source-range-merge.js +103 -0
  22. package/lib/converter/untested.js +30 -60
  23. package/lib/default/options.js +13 -1
  24. package/lib/generate.js +44 -26
  25. package/lib/index.d.ts +52 -4
  26. package/lib/index.js +35 -41
  27. package/lib/istanbul/istanbul-summary.js +2 -2
  28. package/lib/istanbul/istanbul.js +35 -13
  29. package/lib/packages/monocart-coverage-assets.js +4 -3
  30. package/lib/packages/monocart-coverage-converter.js +27 -0
  31. package/lib/packages/monocart-coverage-vendor.js +2 -41
  32. package/lib/packages/monocart-coverage-vendor.js.LICENSE +3 -221
  33. package/lib/platform/concurrency.js +47 -43
  34. package/lib/platform/share.js +8 -1
  35. package/lib/register/hooks.js +19 -13
  36. package/lib/register/register.js +5 -3
  37. package/lib/reports/codacy.js +3 -5
  38. package/lib/reports/codecov.js +3 -5
  39. package/lib/reports/console-details.js +5 -5
  40. package/lib/reports/console-summary.js +4 -4
  41. package/lib/reports/custom.js +8 -24
  42. package/lib/reports/markdown-details.js +4 -6
  43. package/lib/reports/markdown-summary.js +4 -6
  44. package/lib/reports/raw.js +10 -12
  45. package/lib/reports/v8-json.js +3 -5
  46. package/lib/reports/v8.js +3 -5
  47. package/lib/utils/dedupe.js +1 -1
  48. package/lib/utils/gc.js +30 -14
  49. package/lib/utils/markdown.js +2 -2
  50. package/lib/utils/merge/merge.js +2 -4
  51. package/lib/utils/merge/range-tree.js +1 -1
  52. package/lib/utils/request.js +85 -73
  53. package/lib/utils/snapshot.js +4 -4
  54. package/lib/utils/source-path.js +26 -11
  55. package/lib/utils/util.js +67 -42
  56. package/lib/v8/v8-summary.js +2 -4
  57. package/lib/v8/v8.js +11 -11
  58. package/migrate-to-3.md +175 -0
  59. package/package.json +54 -42
  60. package/skills/monocart-coverage-reports/SKILL.md +106 -0
  61. package/skills/monocart-coverage-reports/references/best-practices.md +218 -0
  62. package/skills/monocart-coverage-reports/references/cli.md +108 -0
  63. package/skills/monocart-coverage-reports/references/collection.md +154 -0
  64. package/skills/monocart-coverage-reports/references/filtering-and-sourcemaps.md +170 -0
  65. package/skills/monocart-coverage-reports/references/reports-and-ci.md +219 -0
  66. package/skills/monocart-coverage-reports/references/repository-map.md +59 -0
  67. package/lib/index.mjs +0 -9
  68. package/lib/register/hooks.mjs +0 -3
  69. package/lib/register/register.mjs +0 -3
@@ -1,12 +1,11 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const Util = require('../utils/util.js');
4
- const { ZipFile } = require('../packages/monocart-coverage-vendor.js');
5
- const { mergeIstanbulDataList } = require('../istanbul/istanbul.js');
6
- const { mergeV8DataList } = require('../v8/v8.js');
7
-
8
- const getMergedData = (type, dataList, options) => {
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { Util } from '../utils/util.js';
4
+ import { mergeV8DataList } from '../v8/v8.js';
5
+
6
+ const getMergedData = async (type, dataList, options) => {
9
7
  if (type === 'istanbul') {
8
+ const { mergeIstanbulDataList } = await import('../istanbul/istanbul.js');
10
9
  return mergeIstanbulDataList(dataList, options);
11
10
  }
12
11
  return mergeV8DataList(dataList, options);
@@ -43,7 +42,8 @@ const mergeReport = async (rawDir, options) => {
43
42
 
44
43
  };
45
44
 
46
- const zipReport = (rawDir, rawParent) => {
45
+ const zipReport = async (rawDir, rawParent) => {
46
+ const { ZipFile } = await import('yazl');
47
47
  const zipName = path.basename(rawDir);
48
48
  const zipPath = path.resolve(rawParent, `${zipName}.zip`);
49
49
 
@@ -110,6 +110,4 @@ const rawReport = async (reportData, reportOptions, options) => {
110
110
 
111
111
  };
112
112
 
113
- module.exports = {
114
- rawReport
115
- };
113
+ export { rawReport };
@@ -1,5 +1,5 @@
1
- const path = require('path');
2
- const Util = require('../utils/util.js');
1
+ import path from 'node:path';
2
+ import { Util } from '../utils/util.js';
3
3
 
4
4
  const v8JsonReport = async (reportData, reportOptions, options) => {
5
5
  const v8JsonOptions = {
@@ -17,6 +17,4 @@ const v8JsonReport = async (reportData, reportOptions, options) => {
17
17
  return reportPath;
18
18
  };
19
19
 
20
- module.exports = {
21
- v8JsonReport
22
- };
20
+ export { v8JsonReport };
package/lib/reports/v8.js CHANGED
@@ -1,5 +1,4 @@
1
- const path = require('path');
2
- const Assets = require('../assets.js');
1
+ import path from 'node:path';
3
2
 
4
3
  const v8Report = async (reportData, reportOptions, options) => {
5
4
 
@@ -41,11 +40,10 @@ const v8Report = async (reportData, reportOptions, options) => {
41
40
  };
42
41
 
43
42
  // compress json data for html
43
+ const { Assets } = await import('../assets.js');
44
44
  const htmlPath = await Assets.saveHtmlReport(htmlOptions);
45
45
 
46
46
  return htmlPath;
47
47
  };
48
48
 
49
- module.exports = {
50
- v8Report
51
- };
49
+ export { v8Report };
@@ -115,7 +115,7 @@ const dedupeCountRanges = (ranges) => {
115
115
  };
116
116
 
117
117
 
118
- module.exports = {
118
+ export {
119
119
  sortRanges,
120
120
  dedupeFlatRanges,
121
121
  mergeRangesWith,
package/lib/utils/gc.js CHANGED
@@ -1,18 +1,34 @@
1
+ let collect;
1
2
 
2
- const isBun = typeof Bun !== 'undefined' && Boolean(process.versions.bun);
3
-
4
- if (typeof global.gc !== 'function') {
3
+ const createGC = () => {
4
+ const v8 = process.getBuiltinModule('v8');
5
+ const vm = process.getBuiltinModule('vm');
6
+ // The host may have replaced global.gc while leaving the flag enabled.
7
+ const existing = vm.runInNewContext('typeof gc === "function" ? gc : null');
8
+ if (existing) {
9
+ return existing;
10
+ }
11
+ v8.setFlagsFromString('--expose_gc');
12
+ try {
13
+ return vm.runInNewContext('gc');
14
+ } finally {
15
+ v8.setFlagsFromString('--no-expose_gc');
16
+ }
17
+ };
5
18
 
6
- if (isBun) {
7
- global.gc = () => {
8
- Bun.gc(true);
9
- };
10
- } else {
11
- const v8 = require('node:v8');
12
- const vm = require('node:vm');
13
- v8.setFlagsFromString('--expose_gc');
14
- global.gc = vm.runInNewContext('gc');
19
+ // Importing MCR must not change V8 flags or install globals in the host process.
20
+ const gc = () => {
21
+ if (typeof globalThis.gc === 'function') {
22
+ return globalThis.gc();
23
+ }
24
+ if (!collect) {
25
+ if (typeof Bun !== 'undefined' && process.versions.bun) {
26
+ collect = () => Bun.gc(true);
27
+ } else {
28
+ collect = createGC();
29
+ }
15
30
  }
16
- }
31
+ return collect();
32
+ };
17
33
 
18
- module.exports = global.gc;
34
+ export { gc };
@@ -1,4 +1,4 @@
1
- const os = require('os');
1
+ import os from 'node:os';
2
2
 
3
3
  const renderLine = (ls, padding) => {
4
4
  const spacing = ''.padEnd(padding, ' ');
@@ -129,4 +129,4 @@ const markdownGrid = (data) => {
129
129
  };
130
130
 
131
131
 
132
- module.exports = markdownGrid;
132
+ export { markdownGrid };
@@ -4,7 +4,7 @@
4
4
  * https://github.com/demurgos/v8-coverage
5
5
  */
6
6
 
7
- const RangeTree = require('./range-tree.js');
7
+ import { RangeTree } from './range-tree.js';
8
8
 
9
9
 
10
10
  /**
@@ -430,6 +430,4 @@ function mergeV8Coverage(scriptCovs) {
430
430
  return merged;
431
431
  }
432
432
 
433
- module.exports = {
434
- mergeV8Coverage
435
- };
433
+ export { mergeV8Coverage };
@@ -120,4 +120,4 @@ class RangeTree {
120
120
  }
121
121
  }
122
122
 
123
- module.exports = RangeTree;
123
+ export { RangeTree };
@@ -1,86 +1,98 @@
1
- const http = require('http');
2
- const https = require('https');
1
+ import http from 'node:http';
2
+ import https from 'node:https';
3
3
 
4
- // minimal http request for get sourcemap json
5
- // https://nodejs.org/docs/latest/api/http.html#httprequesturl-options-callback
6
- const request = (url, options) => {
7
-
8
- const HTTP = url.startsWith('https') ? https : http;
9
- // console.log('request', url);
10
-
11
- return new Promise((resolve) => {
12
-
13
- // get method only
14
- HTTP.get(url, options, (res) => {
15
- const { statusCode } = res;
16
-
17
- // Any 2xx status code signals a successful response but here we're only checking for 200.
18
- if (statusCode !== 200) {
19
- // Consume response data to free up memory
20
- res.resume();
21
- const resErr = new Error(`Request Failed. Status Code: ${statusCode}`);
22
- resolve([resErr]);
23
- return;
24
- }
25
-
26
- res.setEncoding('utf8');
27
-
28
- let rawData = '';
29
- res.on('data', (chunk) => {
30
- rawData += chunk;
31
- });
32
-
33
- res.on('end', () => {
34
-
35
- let dataErr;
36
- let data = rawData;
37
-
38
- // parse json
39
- const contentType = res.headers['content-type'];
40
- if ((/^application\/json/).test(contentType)) {
41
- try {
42
- data = JSON.parse(rawData);
43
- } catch (e) {
44
- dataErr = e;
45
- }
46
- }
47
-
48
- res.data = data;
49
- resolve([dataErr, res]);
50
-
51
- });
52
-
53
- }).on('error', (httpErr) => {
54
-
55
- resolve([httpErr]);
4
+ const readResponse = async (res) => {
5
+ if (res.statusCode !== 200) {
6
+ res.destroy();
7
+ return [new Error(`Request Failed. Status Code: ${res.statusCode}`)];
8
+ }
9
+ res.setEncoding('utf8');
10
+ let rawData = '';
11
+ // Async iteration rejects on response errors and premature connection close.
12
+ for await (const chunk of res) {
13
+ rawData += chunk;
14
+ }
15
+ let dataErr;
16
+ let data = rawData;
17
+ if ((/^application\/json/).test(res.headers['content-type'])) {
18
+ try {
19
+ data = JSON.parse(rawData);
20
+ } catch (error) {
21
+ dataErr = error;
22
+ }
23
+ }
24
+ res.data = data;
25
+ return [dataErr, res];
26
+ };
56
27
 
28
+ // Keep the existing [error, IncomingMessage] API and Node HTTP options.
29
+ // timeout is a total deadline (headers and body); 0 explicitly disables it.
30
+ const requestHTTP = (url, options) => new Promise((resolve) => {
31
+ const { timeout = 30000, ... requestOptions } = options;
32
+ const HTTP = url.startsWith('https:') ? https : http;
33
+ let req;
34
+ let timer;
35
+ let settled = false;
36
+ const finish = (result) => {
37
+ if (settled) {
38
+ return;
39
+ }
40
+ settled = true;
41
+ clearTimeout(timer);
42
+ resolve(result);
43
+ };
44
+ const fail = (error) => {
45
+ finish([error]);
46
+ req?.destroy();
47
+ };
48
+ try {
49
+ req = HTTP.get(url, requestOptions, (res) => {
50
+ readResponse(res).then(finish, fail);
57
51
  });
52
+ req.once('error', fail);
53
+ if (timeout > 0) {
54
+ timer = setTimeout(() => {
55
+ const error = new Error(`Request timed out after ${timeout}ms: ${url}`);
56
+ error.code = 'ETIMEDOUT';
57
+ fail(error);
58
+ }, timeout);
59
+ }
60
+ } catch (error) {
61
+ fail(error);
62
+ }
63
+ });
58
64
 
59
- });
65
+ const resolveRequestURL = (url, options) => {
66
+ const urlObj = new URL(url);
67
+ if (!['http:', 'https:'].includes(urlObj.protocol)) {
68
+ throw new TypeError(`Unsupported request protocol: ${urlObj.protocol}`);
69
+ }
70
+ const { timeout = 30000 } = options;
71
+ if (!Number.isFinite(timeout) || timeout < 0) {
72
+ throw new RangeError('Request timeout must be a non-negative finite number');
73
+ }
74
+ return urlObj;
60
75
  };
61
76
 
62
- module.exports = async (url, options = {}) => {
63
- let urlErr;
77
+ const shouldRetryIPv4 = (err, urlObj, options) => err?.code === 'ECONNREFUSED'
78
+ && urlObj.hostname === 'localhost' && !options.signal?.aborted;
79
+
80
+ const request = async (url, options = {}) => {
64
81
  let urlObj;
65
82
  try {
66
- urlObj = new URL(url);
67
- } catch (err) {
68
- // console.error('error url', input);
69
- urlErr = err;
83
+ urlObj = resolveRequestURL(url, options);
84
+ } catch (error) {
85
+ return [error];
70
86
  }
71
87
 
72
- if (urlErr) {
73
- return [urlErr];
74
- }
75
-
76
- const [err, res] = await request(urlObj.toString(), options);
77
- if (err) {
78
- // replace localhost to 127.0.0.1
79
- // ECONNREFUSED on NodeJS 18 https://github.com/node-fetch/node-fetch/issues/1624
80
- if (urlObj.hostname === 'localhost') {
81
- urlObj.hostname = '127.0.0.1';
82
- return request(urlObj.toString(), options);
83
- }
88
+ const [err, res] = await requestHTTP(urlObj.toString(), options);
89
+ // IPv4-only servers can reject localhost's IPv6 address on modern Node too.
90
+ // Do not repeat timeouts, aborts, HTTP failures or JSON parsing errors.
91
+ if (shouldRetryIPv4(err, urlObj, options)) {
92
+ urlObj.hostname = '127.0.0.1';
93
+ return requestHTTP(urlObj.toString(), options);
84
94
  }
85
95
  return [err, res];
86
96
  };
97
+
98
+ export { request };
@@ -1,7 +1,7 @@
1
- const CG = require('console-grid');
2
- const EC = require('eight-colors');
1
+ import CG from 'console-grid';
2
+ import EC from 'eight-colors';
3
3
 
4
- const Util = require('./util.js');
4
+ import { Util } from './util.js';
5
5
 
6
6
  const mergeSingleSubGroups = (item) => {
7
7
 
@@ -341,7 +341,7 @@ const diffSnapshot = (oldData, newData, diffOptions) => {
341
341
  };
342
342
  };
343
343
 
344
- module.exports = {
344
+ export {
345
345
  getGroupedRows,
346
346
  getSnapshot,
347
347
  diffSnapshot
@@ -1,7 +1,7 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const { fileURLToPath, pathToFileURL } = require('url');
4
- const Util = require('./util.js');
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath, pathToFileURL } from 'node:url';
4
+ import { Util } from './util.js';
5
5
 
6
6
  const resolveSourceRootUrl = (sourceName, sourceRoot) => {
7
7
  // prepend sourceRoot
@@ -31,8 +31,13 @@ const resolveAnonymousUrl = (url, index, type) => {
31
31
 
32
32
  const normalizePathDir = (sourcePath) => {
33
33
 
34
- // decodeURI("%20") to space
35
- let str = decodeURI(`${sourcePath}`);
34
+ let str = `${sourcePath}`;
35
+ try {
36
+ // decodeURI("%20") to space
37
+ str = decodeURI(str);
38
+ } catch {
39
+ // Preserve unresolvable URI text instead of aborting the report.
40
+ }
36
41
  str = str.replace(/\\/g, '/');
37
42
 
38
43
  // remove / of start, end or double, ./ ../
@@ -55,15 +60,21 @@ const betterFileURLToPath = (url) => {
55
60
  try {
56
61
  url = fileURLToPath(url);
57
62
  } catch (e) {
58
- url = decodeURIComponent(url);
59
- url = fileURLToPath(url);
63
+ try {
64
+ url = decodeURIComponent(url);
65
+ url = fileURLToPath(url);
66
+ } catch {
67
+ // in case that it cannot be safely resolved, we pass it verbatim.
68
+ return url;
69
+ }
60
70
  }
61
71
  return url;
62
72
  };
63
73
 
64
74
  const normalizeSourcePath = (sourceUrl, baseDir) => {
65
75
 
66
- // includes anonymous and everything
76
+ // Best-effort report paths, not filesystem lookup paths. Leave special cases
77
+ // to sourcePath, which can use the original URL instead of guessing here.
67
78
 
68
79
  // file url
69
80
  if (sourceUrl.startsWith('file:')) {
@@ -120,11 +131,14 @@ const normalizeSourcePath = (sourceUrl, baseDir) => {
120
131
  return normalizePathDir(relPath);
121
132
  };
122
133
 
134
+ const cssTypes = new Set(['css', 'less', 'sass', 'scss', 'styl', 'stylus', 'postcss', 'pcss', 'sss']);
135
+
123
136
  const getSourceType = (sourcePath) => {
124
137
  let ext = path.extname(sourcePath);
125
138
  let type = 'js';
126
139
  if (ext) {
127
- ext = ext.slice(1);
140
+ // extensions are case-insensitive, e.g. `.CSS` or `.SCSS`
141
+ ext = ext.slice(1).toLowerCase();
128
142
  const reg = /^[a-z0-9]+$/;
129
143
  if (reg.test(ext)) {
130
144
  type = ext;
@@ -241,10 +255,11 @@ const initSourceMapSourcesPath = (fileUrls, sourceMap, distFile, options) => {
241
255
 
242
256
  };
243
257
 
244
- module.exports = {
258
+ export {
245
259
  resolveAnonymousUrl,
246
260
  normalizeSourcePath,
247
261
  getSourceType,
262
+ cssTypes,
248
263
  getSourcePathReplacer,
249
264
  initIstanbulSourcePath,
250
265
  initSourceMapSourcesPath
package/lib/utils/util.js CHANGED
@@ -1,23 +1,45 @@
1
- const fs = require('fs');
2
- const { writeFile, readFile } = require('fs/promises');
3
- const path = require('path');
4
- const os = require('os');
5
- const crypto = require('crypto');
6
-
7
- const EC = require('eight-colors');
8
- const CG = require('console-grid');
9
- const acornWalk = require('acorn-walk');
10
-
11
- const Share = require('../platform/share.js');
12
- const request = require('./request.js');
13
- const version = require('../../package.json').version;
14
- const markdownGrid = require('./markdown.js');
15
- const { mergeV8Coverage } = require('./merge/merge.js');
16
- const gc = require('./gc.js');
17
-
18
- const {
19
- findUpSync, supportsColor, minimatch
20
- } = require('../packages/monocart-coverage-vendor.js');
1
+ import packageMetadata from '../../package.json' with { type: 'json' };
2
+ import fs from 'node:fs';
3
+ import { writeFile, readFile } from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import os from 'node:os';
6
+ import crypto from 'node:crypto';
7
+
8
+ import EC from 'eight-colors';
9
+ import CG from 'console-grid';
10
+ import * as acornWalk from 'acorn-walk';
11
+
12
+ import { Util as Share } from '../platform/share.js';
13
+ import { request } from './request.js';
14
+ import { markdownGrid } from './markdown.js';
15
+ import { mergeV8Coverage } from './merge/merge.js';
16
+ import { gc } from './gc.js';
17
+
18
+ import {
19
+ findUpSync, supportsColor, minimatch, Minimatch
20
+ } from '../packages/monocart-coverage-vendor.js';
21
+
22
+ const version = packageMetadata.version;
23
+
24
+ // Compile lazily: substring matches need no glob, and invalid patterns should
25
+ // only fail when the old matcher would actually have evaluated them.
26
+ const createPatternMatcher = (pattern) => {
27
+ let matcher;
28
+ const match = (value) => {
29
+ matcher ||= new Minimatch(pattern);
30
+ return matcher.match(value);
31
+ };
32
+ return (value) => Util.betterMinimatch(value, pattern, match);
33
+ };
34
+
35
+ const getMemoryAfterGC = () => {
36
+ const memory = Util.getMemory();
37
+ if (Util.gcThreshold && Util.gcThreshold < memory) {
38
+ Util.forceGC();
39
+ return Util.getMemory();
40
+ }
41
+ return memory;
42
+ };
21
43
 
22
44
  // https://github.com/chalk/supports-color
23
45
  // disabled color if Terminal stdout does not support color
@@ -185,7 +207,7 @@ const Util = {
185
207
  };
186
208
  },
187
209
 
188
- betterMinimatch: (str, pattern) => {
210
+ betterMinimatch: (str, pattern, match = (value) => minimatch(value, pattern)) => {
189
211
  str = `${str}`;
190
212
  pattern = `${pattern}`;
191
213
 
@@ -199,18 +221,23 @@ const Util = {
199
221
  }
200
222
 
201
223
  // with minimatch
202
- if (minimatch(str, pattern)) {
224
+ if (match(str)) {
203
225
  return true;
204
226
  }
205
227
 
206
228
  // after decode url
207
- str = decodeURIComponent(str);
229
+ try {
230
+ str = decodeURIComponent(str);
231
+ } catch {
232
+ // The raw path did not match and cannot be decoded. Let later rules run.
233
+ return false;
234
+ }
208
235
 
209
236
  if (str.includes(pattern)) {
210
237
  return true;
211
238
  }
212
239
 
213
- if (minimatch(str, pattern)) {
240
+ if (match(str)) {
214
241
  return true;
215
242
  }
216
243
 
@@ -229,19 +256,18 @@ const Util = {
229
256
  if (obj) {
230
257
  input = obj;
231
258
  } else {
232
- return (item) => {
233
- return Util.betterMinimatch(fieldAccessor(item), input);
234
- };
259
+ const match = createPatternMatcher(input);
260
+ return (item) => match(fieldAccessor(item));
235
261
  }
236
262
  }
237
263
 
238
264
  // for patterns
239
265
  if (input && typeof input === 'object') {
240
- const patterns = Object.keys(input);
266
+ const patterns = Object.keys(input).map((pattern) => [pattern, createPatternMatcher(pattern)]);
241
267
  return (item) => {
242
268
  const value = fieldAccessor(item);
243
- for (const pattern of patterns) {
244
- if (Util.betterMinimatch(value, pattern)) {
269
+ for (const [pattern, match] of patterns) {
270
+ if (match(value)) {
245
271
  return input[pattern];
246
272
  }
247
273
  }
@@ -426,11 +452,12 @@ const Util = {
426
452
  }
427
453
  };
428
454
 
429
- const list = fs.readdirSync(dir);
430
- for (const name of list) {
455
+ const list = fs.readdirSync(dir, {
456
+ withFileTypes: true
457
+ });
458
+ for (const info of list) {
459
+ const { name } = info;
431
460
  const abs = path.resolve(dir, name);
432
-
433
- const info = fs.lstatSync(abs);
434
461
  if (info.isSymbolicLink()) {
435
462
  continue;
436
463
  }
@@ -879,20 +906,18 @@ const Util = {
879
906
  // time is debug level, fix the log info, for checking snapshot
880
907
  logTime: (message, time_start) => {
881
908
 
882
- // memory gc
883
- let memory = Util.getMemory();
884
- if (Util.gcThreshold && Util.gcThreshold < memory) {
885
- Util.forceGC();
909
+ const logEnabled = Util.loggingLevel >= Util.loggingLevels.debug || Boolean(process.env.MCR_LOG_TIME);
910
+ if (!logEnabled && !Util.gcThreshold) {
911
+ return;
886
912
  }
887
-
888
- if (Util.loggingLevel < Util.loggingLevels.debug && !process.env.MCR_LOG_TIME) {
913
+ const memory = getMemoryAfterGC();
914
+ if (!logEnabled) {
889
915
  return;
890
916
  }
891
917
  const duration = Date.now() - time_start;
892
918
  const durationH = Util.TF(duration);
893
919
  const ls = [`[MCR] ${message}`];
894
920
 
895
- memory = Util.getMemory();
896
921
  ls.push(` (memory: ${memory}MB)`);
897
922
 
898
923
  // time
@@ -911,4 +936,4 @@ const Util = {
911
936
 
912
937
  };
913
938
 
914
- module.exports = Util;
939
+ export { Util };
@@ -1,4 +1,4 @@
1
- const Util = require('../utils/util.js');
1
+ import { Util } from '../utils/util.js';
2
2
 
3
3
  // both css and js
4
4
  const getV8SummaryBytes = (item) => {
@@ -133,6 +133,4 @@ const getV8Summary = (v8list, watermarks) => {
133
133
  return summary;
134
134
  };
135
135
 
136
- module.exports = {
137
- getV8Summary
138
- };
136
+ export { getV8Summary };