monocart-coverage-reports 2.12.11 → 2.13.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/README.md +47 -9
- package/README.zh-Hans.md +48 -10
- package/lib/assets.js +1 -1
- package/lib/converter/converter.js +28 -13
- package/lib/packages/monocart-coverage-assets.js +1 -1
- package/lib/packages/monocart-coverage-vendor.js +24 -16
- package/lib/platform/share.js +18 -10
- package/lib/reports/console-details.js +1 -34
- package/lib/utils/gc.js +13 -4
- package/lib/utils/merge/merge.js +5 -9
- package/lib/utils/util.js +37 -86
- package/lib/v8/v8.js +11 -12
- package/package.json +149 -136
package/lib/platform/share.js
CHANGED
|
@@ -220,18 +220,26 @@ const Util = {
|
|
|
220
220
|
return;
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
// rangeList
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
223
|
+
// rangeList is sorted by startKey ascending.
|
|
224
|
+
// Binary search for the rightmost range where startKey <= startPos.
|
|
225
|
+
let low = 0;
|
|
226
|
+
let high = rangeList.length;
|
|
227
|
+
while (low < high) {
|
|
228
|
+
const mid = (low + high) >>> 1;
|
|
229
|
+
if (rangeList[mid][startKey] > startPos) {
|
|
230
|
+
high = mid;
|
|
231
|
+
} else {
|
|
232
|
+
low = mid + 1;
|
|
233
|
+
}
|
|
227
234
|
}
|
|
228
235
|
|
|
229
|
-
//
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
236
|
+
// Scan backwards from the insertion point; the first match is the answer.
|
|
237
|
+
for (let i = low - 1; i >= 0; i--) {
|
|
238
|
+
const it = rangeList[i];
|
|
239
|
+
if (endPos <= it[endKey]) {
|
|
240
|
+
return it;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
235
243
|
},
|
|
236
244
|
|
|
237
245
|
getRangeLines: (sLoc, eLoc) => {
|
|
@@ -62,40 +62,7 @@ const getDetailsRows = (files, metrics, cdOptions, color) => {
|
|
|
62
62
|
};
|
|
63
63
|
|
|
64
64
|
const getFileFilter = (input) => {
|
|
65
|
-
|
|
66
|
-
if (typeof input === 'function') {
|
|
67
|
-
return input;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// for single minimatch pattern
|
|
71
|
-
if (input && typeof input === 'string') {
|
|
72
|
-
// string to multiple patterns "{...}"
|
|
73
|
-
// mcr npx mocha --entryFilter {'**/node_modules/**':false,'**/src/*.js':true}
|
|
74
|
-
// mcr npx mocha --entryFilter "{'**/node_modules/**': false, '**/src/*.js': true}"
|
|
75
|
-
const obj = Util.strToObj(input);
|
|
76
|
-
if (obj) {
|
|
77
|
-
input = obj;
|
|
78
|
-
} else {
|
|
79
|
-
return (file) => {
|
|
80
|
-
return Util.betterMinimatch(file.sourcePath, input);
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// for patterns
|
|
86
|
-
if (input && typeof input === 'object') {
|
|
87
|
-
const patterns = Object.keys(input);
|
|
88
|
-
return (file) => {
|
|
89
|
-
const sourcePath = file.sourcePath;
|
|
90
|
-
for (const pattern of patterns) {
|
|
91
|
-
if (Util.betterMinimatch(sourcePath, pattern)) {
|
|
92
|
-
return input[pattern];
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
// false if not matched
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
65
|
+
return Util.createFilterHandler(input, (file) => file.sourcePath);
|
|
99
66
|
};
|
|
100
67
|
|
|
101
68
|
const getFilteredFiles = (filter, files) => {
|
package/lib/utils/gc.js
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
1
|
+
|
|
2
|
+
const isBun = typeof Bun !== 'undefined' && Boolean(process.versions.bun);
|
|
3
3
|
|
|
4
4
|
if (typeof global.gc !== 'function') {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
|
|
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');
|
|
15
|
+
}
|
|
7
16
|
}
|
|
8
17
|
|
|
9
18
|
module.exports = global.gc;
|
package/lib/utils/merge/merge.js
CHANGED
|
@@ -46,19 +46,15 @@ function fromSortedRanges(ranges) {
|
|
|
46
46
|
}
|
|
47
47
|
let parent;
|
|
48
48
|
let parentCount;
|
|
49
|
-
while (
|
|
49
|
+
while (stack.length > 0) {
|
|
50
50
|
[parent, parentCount] = stack[stack.length - 1];
|
|
51
|
-
// assert: `top !== undefined` (the ranges are sorted)
|
|
52
51
|
if (range.startOffset < parent.end) {
|
|
53
52
|
break;
|
|
54
|
-
} else {
|
|
55
|
-
stack.pop();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// prevent crash when v8 incorrectly merges static_initializer's
|
|
59
|
-
if (stack.length === 0) {
|
|
60
|
-
break;
|
|
61
53
|
}
|
|
54
|
+
stack.pop();
|
|
55
|
+
// parent / parentCount still hold the last popped values
|
|
56
|
+
// when v8 incorrectly merges static_initializer's, the stack
|
|
57
|
+
// may become empty; the while condition handles that.
|
|
62
58
|
}
|
|
63
59
|
node.delta -= parentCount;
|
|
64
60
|
parent.children.push(node);
|
package/lib/utils/util.js
CHANGED
|
@@ -39,6 +39,15 @@ const Util = {
|
|
|
39
39
|
markdownGrid,
|
|
40
40
|
mergeV8Coverage,
|
|
41
41
|
|
|
42
|
+
ensureDirSync: function(filePath) {
|
|
43
|
+
const p = path.dirname(filePath);
|
|
44
|
+
if (!fs.existsSync(p)) {
|
|
45
|
+
fs.mkdirSync(p, {
|
|
46
|
+
recursive: true
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
|
|
42
51
|
forceGC: () => {
|
|
43
52
|
gc();
|
|
44
53
|
},
|
|
@@ -97,9 +106,9 @@ const Util = {
|
|
|
97
106
|
}
|
|
98
107
|
},
|
|
99
108
|
|
|
100
|
-
calculateSha1: (
|
|
109
|
+
calculateSha1: (input) => {
|
|
101
110
|
const hash = crypto.createHash('sha1');
|
|
102
|
-
hash.update(
|
|
111
|
+
hash.update(input);
|
|
103
112
|
return hash.digest('hex');
|
|
104
113
|
},
|
|
105
114
|
|
|
@@ -132,6 +141,10 @@ const Util = {
|
|
|
132
141
|
},
|
|
133
142
|
|
|
134
143
|
resolveWatermarks: (defaultWatermarks, watermarks) => {
|
|
144
|
+
// clone to avoid mutating the input
|
|
145
|
+
defaultWatermarks = {
|
|
146
|
+
... defaultWatermarks
|
|
147
|
+
};
|
|
135
148
|
if (watermarks) {
|
|
136
149
|
if (Array.isArray(watermarks)) {
|
|
137
150
|
Object.keys(defaultWatermarks).forEach((k) => {
|
|
@@ -204,62 +217,54 @@ const Util = {
|
|
|
204
217
|
return false;
|
|
205
218
|
},
|
|
206
219
|
|
|
207
|
-
|
|
208
|
-
getEntryFilter: (options) => {
|
|
209
|
-
// for entry.url
|
|
210
|
-
|
|
211
|
-
if (options.entryFilterHandler) {
|
|
212
|
-
return options.entryFilterHandler;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
let input = options.entryFilter || options.filter;
|
|
216
|
-
|
|
220
|
+
createFilterHandler: function(input, fieldAccessor) {
|
|
217
221
|
// for function handler
|
|
218
222
|
if (typeof input === 'function') {
|
|
219
|
-
options.entryFilterHandler = input;
|
|
220
223
|
return input;
|
|
221
224
|
}
|
|
222
225
|
|
|
223
226
|
// for single minimatch pattern
|
|
224
227
|
if (input && typeof input === 'string') {
|
|
225
|
-
// string to multiple patterns "{...}"
|
|
226
|
-
// mcr npx mocha --entryFilter {'**/node_modules/**':false,'**/src/*.js':true}
|
|
227
|
-
// mcr npx mocha --entryFilter "{'**/node_modules/**': false, '**/src/*.js': true}"
|
|
228
228
|
const obj = Util.strToObj(input);
|
|
229
229
|
if (obj) {
|
|
230
230
|
input = obj;
|
|
231
231
|
} else {
|
|
232
|
-
|
|
233
|
-
return Util.betterMinimatch(
|
|
232
|
+
return (item) => {
|
|
233
|
+
return Util.betterMinimatch(fieldAccessor(item), input);
|
|
234
234
|
};
|
|
235
|
-
options.entryFilterHandler = handler;
|
|
236
|
-
return handler;
|
|
237
235
|
}
|
|
238
236
|
}
|
|
239
237
|
|
|
240
238
|
// for patterns
|
|
241
239
|
if (input && typeof input === 'object') {
|
|
242
240
|
const patterns = Object.keys(input);
|
|
243
|
-
|
|
244
|
-
const
|
|
241
|
+
return (item) => {
|
|
242
|
+
const value = fieldAccessor(item);
|
|
245
243
|
for (const pattern of patterns) {
|
|
246
|
-
if (Util.betterMinimatch(
|
|
244
|
+
if (Util.betterMinimatch(value, pattern)) {
|
|
247
245
|
return input[pattern];
|
|
248
246
|
}
|
|
249
247
|
}
|
|
250
|
-
// false if not matched
|
|
251
248
|
};
|
|
252
|
-
options.entryFilterHandler = handler;
|
|
253
|
-
return handler;
|
|
254
249
|
}
|
|
255
250
|
|
|
256
251
|
// default
|
|
257
|
-
|
|
252
|
+
return () => true;
|
|
253
|
+
},
|
|
254
|
+
|
|
255
|
+
getEntryFilter: (options) => {
|
|
256
|
+
// for entry.url
|
|
257
|
+
|
|
258
|
+
if (options.entryFilterHandler) {
|
|
259
|
+
return options.entryFilterHandler;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const input = options.entryFilter || options.filter;
|
|
263
|
+
const handler = Util.createFilterHandler(input, (entry) => entry.url);
|
|
258
264
|
options.entryFilterHandler = handler;
|
|
259
265
|
return handler;
|
|
260
266
|
},
|
|
261
267
|
|
|
262
|
-
// eslint-disable-next-line complexity
|
|
263
268
|
getSourceFilter: (options) => {
|
|
264
269
|
// for sourcePath
|
|
265
270
|
|
|
@@ -267,48 +272,8 @@ const Util = {
|
|
|
267
272
|
return options.sourceFilterHandler;
|
|
268
273
|
}
|
|
269
274
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
// for function handler
|
|
273
|
-
if (typeof input === 'function') {
|
|
274
|
-
options.sourceFilterHandler = input;
|
|
275
|
-
return input;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
// for single minimatch pattern
|
|
279
|
-
if (input && typeof input === 'string') {
|
|
280
|
-
// string to multiple patterns "{...}"
|
|
281
|
-
// mcr npx mocha --sourceFilter {'**/node_modules/**':false,'**/src/*.js':true}
|
|
282
|
-
// mcr npx mocha --sourceFilter "{'**/node_modules/**': false, '**/src/*.js': true}"
|
|
283
|
-
const obj = Util.strToObj(input);
|
|
284
|
-
if (obj) {
|
|
285
|
-
input = obj;
|
|
286
|
-
} else {
|
|
287
|
-
const handler = (sourcePath) => {
|
|
288
|
-
return Util.betterMinimatch(sourcePath, input);
|
|
289
|
-
};
|
|
290
|
-
options.sourceFilterHandler = handler;
|
|
291
|
-
return handler;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// for patterns
|
|
296
|
-
if (input && typeof input === 'object') {
|
|
297
|
-
const patterns = Object.keys(input);
|
|
298
|
-
const handler = (sourcePath) => {
|
|
299
|
-
for (const pattern of patterns) {
|
|
300
|
-
if (Util.betterMinimatch(sourcePath, pattern)) {
|
|
301
|
-
return input[pattern];
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
// false if not matched
|
|
305
|
-
};
|
|
306
|
-
options.sourceFilterHandler = handler;
|
|
307
|
-
return handler;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// default
|
|
311
|
-
const handler = () => true;
|
|
275
|
+
const input = options.sourceFilter || options.filter;
|
|
276
|
+
const handler = Util.createFilterHandler(input, (sourcePath) => sourcePath);
|
|
312
277
|
options.sourceFilterHandler = handler;
|
|
313
278
|
return handler;
|
|
314
279
|
},
|
|
@@ -524,26 +489,12 @@ const Util = {
|
|
|
524
489
|
},
|
|
525
490
|
|
|
526
491
|
writeFileSync: function(filePath, content) {
|
|
527
|
-
|
|
528
|
-
const p = path.dirname(filePath);
|
|
529
|
-
if (!fs.existsSync(p)) {
|
|
530
|
-
fs.mkdirSync(p, {
|
|
531
|
-
recursive: true
|
|
532
|
-
});
|
|
533
|
-
}
|
|
534
|
-
}
|
|
492
|
+
Util.ensureDirSync(filePath);
|
|
535
493
|
fs.writeFileSync(filePath, content);
|
|
536
494
|
},
|
|
537
495
|
|
|
538
496
|
writeFile: async (filePath, content) => {
|
|
539
|
-
|
|
540
|
-
const p = path.dirname(filePath);
|
|
541
|
-
if (!fs.existsSync(p)) {
|
|
542
|
-
fs.mkdirSync(p, {
|
|
543
|
-
recursive: true
|
|
544
|
-
});
|
|
545
|
-
}
|
|
546
|
-
}
|
|
497
|
+
Util.ensureDirSync(filePath);
|
|
547
498
|
await writeFile(filePath, content).catch((e) => {
|
|
548
499
|
Util.logError(`write file: ${filePath} ${e.message || e}`);
|
|
549
500
|
});
|
package/lib/v8/v8.js
CHANGED
|
@@ -152,20 +152,19 @@ const initV8ListAndSourcemap = async (mcr, v8list) => {
|
|
|
152
152
|
|
|
153
153
|
// ========================================================================================================
|
|
154
154
|
|
|
155
|
-
// force to async
|
|
156
155
|
const mergeCssRanges = (itemList) => {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
concatRanges
|
|
162
|
-
}
|
|
156
|
+
// Concatenate all ranges using push to avoid O(n²) array copying
|
|
157
|
+
const concatRanges = [];
|
|
158
|
+
for (const item of itemList) {
|
|
159
|
+
for (const range of item.ranges) {
|
|
160
|
+
concatRanges.push(range);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
163
|
|
|
164
|
-
|
|
165
|
-
|
|
164
|
+
// ranges: [ {start, end} ]
|
|
165
|
+
const ranges = dedupeFlatRanges(concatRanges);
|
|
166
166
|
|
|
167
|
-
|
|
168
|
-
});
|
|
167
|
+
return ranges;
|
|
169
168
|
};
|
|
170
169
|
|
|
171
170
|
const mergeJsFunctions = async (itemList) => {
|
|
@@ -212,7 +211,7 @@ const mergeV8DataList = async (dataList, options) => {
|
|
|
212
211
|
const itemList = mergeMap[id];
|
|
213
212
|
const item = itemMap[id];
|
|
214
213
|
if (item.type === 'css') {
|
|
215
|
-
item.ranges =
|
|
214
|
+
item.ranges = mergeCssRanges(itemList);
|
|
216
215
|
} else {
|
|
217
216
|
item.functions = await mergeJsFunctions(itemList);
|
|
218
217
|
}
|