monocart-coverage-reports 2.7.1 → 2.7.3
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 +14 -8
- package/lib/cli.js +74 -88
- package/lib/converter/collect-source-maps.js +12 -1
- package/lib/converter/find-original-range.js +97 -94
- package/lib/generate.js +130 -1
- package/lib/index.d.ts +6 -0
- package/lib/index.js +20 -6
- package/lib/packages/monocart-coverage-v8.js +1 -1
- package/lib/register/hooks.js +58 -0
- package/lib/register/hooks.mjs +3 -0
- package/lib/register/register.js +4 -0
- package/lib/register/register.mjs +3 -0
- package/lib/utils/source-path.js +30 -14
- package/package.json +97 -83
|
@@ -129,13 +129,18 @@ const getComparedPosition = (info, direction) => {
|
|
|
129
129
|
gt = gt.trimEnd();
|
|
130
130
|
ot = ot.trimEnd();
|
|
131
131
|
|
|
132
|
-
// no content after trim
|
|
133
|
-
if (!ot
|
|
132
|
+
// no original content after trim
|
|
133
|
+
if (!ot) {
|
|
134
134
|
return {
|
|
135
135
|
pos: direction === 'start' ? oLen : 0
|
|
136
136
|
};
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
// no generated content after trim
|
|
140
|
+
if (!gt) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
139
144
|
// same content
|
|
140
145
|
if (gt === ot) {
|
|
141
146
|
return {
|
|
@@ -273,16 +278,16 @@ const getFixedPosition = (info, direction) => {
|
|
|
273
278
|
|
|
274
279
|
// ========================================================================================================
|
|
275
280
|
|
|
276
|
-
const getOriginalEndOffset = (m,
|
|
281
|
+
const getOriginalEndOffset = (m, cache) => {
|
|
277
282
|
if (!m.originalEndOffset) {
|
|
278
|
-
const line =
|
|
283
|
+
const line = cache.originalState.locator.getLine(m.originalLine + 1);
|
|
279
284
|
m.originalEndOffset = line ? line.end : m.originalOffset;
|
|
280
285
|
}
|
|
281
286
|
return m.originalEndOffset;
|
|
282
287
|
};
|
|
283
288
|
|
|
284
|
-
const getOriginalText = (m1, m2,
|
|
285
|
-
const originalLocator =
|
|
289
|
+
const getOriginalText = (m1, m2, cache) => {
|
|
290
|
+
const originalLocator = cache.originalState.locator;
|
|
286
291
|
|
|
287
292
|
const o1 = m1.originalOffset;
|
|
288
293
|
const o2 = m2.originalOffset;
|
|
@@ -299,7 +304,7 @@ const getOriginalText = (m1, m2, rangeInfo) => {
|
|
|
299
304
|
// esbuild fixing two mapping have same original
|
|
300
305
|
// m1 to end line
|
|
301
306
|
if (o1 === o2) {
|
|
302
|
-
const originalEndOffset = getOriginalEndOffset(m1,
|
|
307
|
+
const originalEndOffset = getOriginalEndOffset(m1, cache);
|
|
303
308
|
return {
|
|
304
309
|
originalOffset: o1,
|
|
305
310
|
originalText: originalLocator.getSlice(o1, originalEndOffset)
|
|
@@ -319,12 +324,12 @@ const getOriginalText = (m1, m2, rangeInfo) => {
|
|
|
319
324
|
|
|
320
325
|
// if (direction === 'start') {
|
|
321
326
|
// should be m2 ?
|
|
322
|
-
// console.log(direction,
|
|
327
|
+
// console.log(direction, cache.originalState.sourcePath);
|
|
323
328
|
// console.log(m1, m2);
|
|
324
329
|
// }
|
|
325
330
|
|
|
326
331
|
// should be wrong, ignore m2
|
|
327
|
-
const originalEndOffset = getOriginalEndOffset(m1,
|
|
332
|
+
const originalEndOffset = getOriginalEndOffset(m1, cache);
|
|
328
333
|
return {
|
|
329
334
|
originalOffset: o1,
|
|
330
335
|
originalText: originalLocator.getSlice(o1, originalEndOffset)
|
|
@@ -385,10 +390,10 @@ const getGeneratedText = (m1, m2, state, offset) => {
|
|
|
385
390
|
|
|
386
391
|
// ========================================================================================================
|
|
387
392
|
|
|
388
|
-
const getFixedOriginalStart = (start, mappings, state,
|
|
393
|
+
const getFixedOriginalStart = (start, mappings, state, cache) => {
|
|
389
394
|
|
|
390
395
|
const [m1, m2] = mappings;
|
|
391
|
-
const { originalState, crossStart } =
|
|
396
|
+
const { originalState, crossStart } = cache;
|
|
392
397
|
|
|
393
398
|
// cross file from start of line
|
|
394
399
|
if (crossStart) {
|
|
@@ -398,7 +403,7 @@ const getFixedOriginalStart = (start, mappings, state, rangeInfo) => {
|
|
|
398
403
|
}
|
|
399
404
|
|
|
400
405
|
const direction = 'start';
|
|
401
|
-
const { originalText, originalOffset } = getOriginalText(m1, m2,
|
|
406
|
+
const { originalText, originalOffset } = getOriginalText(m1, m2, cache);
|
|
402
407
|
const { generatedText, generatedPos } = getGeneratedText(m1, m2, state, start);
|
|
403
408
|
|
|
404
409
|
const info = {
|
|
@@ -426,14 +431,14 @@ const getFixedOriginalStart = (start, mappings, state, rangeInfo) => {
|
|
|
426
431
|
};
|
|
427
432
|
};
|
|
428
433
|
|
|
429
|
-
const getFixedOriginalEnd = (end, mappings, state,
|
|
434
|
+
const getFixedOriginalEnd = (end, mappings, state, cache) => {
|
|
430
435
|
|
|
431
436
|
const [m1, m2] = mappings;
|
|
432
|
-
const { originalState, crossEnd } =
|
|
437
|
+
const { originalState, crossEnd } = cache;
|
|
433
438
|
|
|
434
439
|
// cross file until e1 line end (not file end)
|
|
435
440
|
if (crossEnd) {
|
|
436
|
-
const originalEndOffset = getOriginalEndOffset(m1,
|
|
441
|
+
const originalEndOffset = getOriginalEndOffset(m1, cache);
|
|
437
442
|
return {
|
|
438
443
|
originalEnd: originalEndOffset
|
|
439
444
|
};
|
|
@@ -448,33 +453,8 @@ const getFixedOriginalEnd = (end, mappings, state, rangeInfo) => {
|
|
|
448
453
|
};
|
|
449
454
|
}
|
|
450
455
|
|
|
451
|
-
// quick check next one if exact match
|
|
452
|
-
// most of case is same string
|
|
453
|
-
if (m2.generatedOffset === end + 1) {
|
|
454
|
-
const gt = state.locator.source[end];
|
|
455
|
-
const oi = m2.originalOffset - 1;
|
|
456
|
-
const ot = originalState.locator.source[oi];
|
|
457
|
-
// it could be ; but it quite far away
|
|
458
|
-
if (gt === ot && [';', ','].includes(gt)) {
|
|
459
|
-
return {
|
|
460
|
-
originalEnd: oi
|
|
461
|
-
};
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
// Not applicable
|
|
465
|
-
// console.log('==================================');
|
|
466
|
-
// console.log({
|
|
467
|
-
// gp: state.sourcePath,
|
|
468
|
-
// g: end,
|
|
469
|
-
// gt,
|
|
470
|
-
// op: originalState.sourcePath,
|
|
471
|
-
// o: oi,
|
|
472
|
-
// ot
|
|
473
|
-
// });
|
|
474
|
-
}
|
|
475
|
-
|
|
476
456
|
const direction = 'end';
|
|
477
|
-
const { originalText, originalOffset } = getOriginalText(m1, m2,
|
|
457
|
+
const { originalText, originalOffset } = getOriginalText(m1, m2, cache);
|
|
478
458
|
const { generatedText, generatedPos } = getGeneratedText(m1, m2, state, end);
|
|
479
459
|
|
|
480
460
|
const info = {
|
|
@@ -506,23 +486,57 @@ const getFixedOriginalEnd = (end, mappings, state, rangeInfo) => {
|
|
|
506
486
|
|
|
507
487
|
// ========================================================================================================
|
|
508
488
|
|
|
509
|
-
const
|
|
510
|
-
|
|
511
|
-
|
|
489
|
+
const getOriginalStartPosition = (cache, state) => {
|
|
490
|
+
|
|
491
|
+
const { start, startMappings } = cache;
|
|
492
|
+
|
|
493
|
+
if (Array.isArray(startMappings)) {
|
|
494
|
+
return getFixedOriginalStart(start, startMappings, state, cache);
|
|
512
495
|
}
|
|
496
|
+
|
|
513
497
|
// Exact match
|
|
514
498
|
return {
|
|
515
|
-
originalStart:
|
|
499
|
+
originalStart: startMappings.originalOffset
|
|
516
500
|
};
|
|
517
501
|
};
|
|
518
502
|
|
|
519
|
-
const
|
|
520
|
-
|
|
521
|
-
|
|
503
|
+
const getOriginalExclusiveEnd = (cache, state) => {
|
|
504
|
+
// end, exclusive mappings
|
|
505
|
+
const { end } = cache;
|
|
506
|
+
const { decodedMappings } = state;
|
|
507
|
+
const endMappings = findMapping(decodedMappings, end);
|
|
508
|
+
if (Array.isArray(endMappings)) {
|
|
509
|
+
return getFixedOriginalEnd(end, endMappings, state, cache);
|
|
522
510
|
}
|
|
523
|
-
|
|
511
|
+
|
|
512
|
+
// Exact match end
|
|
524
513
|
return {
|
|
525
|
-
originalEnd:
|
|
514
|
+
originalEnd: endMappings.originalOffset
|
|
515
|
+
};
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
const getOriginalEndPosition = (cache, state) => {
|
|
519
|
+
|
|
520
|
+
const { endMappings, originalState } = cache;
|
|
521
|
+
|
|
522
|
+
// (end - 1), inclusive
|
|
523
|
+
if (Array.isArray(endMappings)) {
|
|
524
|
+
return getOriginalExclusiveEnd(cache, state);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// Exact match (end - 1)
|
|
528
|
+
|
|
529
|
+
// check end char
|
|
530
|
+
const oi = endMappings.originalOffset;
|
|
531
|
+
const originalEndChar = originalState.locator.getSlice(oi, oi + 1);
|
|
532
|
+
// the char should never end with "{" or "("
|
|
533
|
+
if (['{', '('].includes(originalEndChar)) {
|
|
534
|
+
return getOriginalExclusiveEnd(cache, state);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// inclusive to exclusive
|
|
538
|
+
return {
|
|
539
|
+
originalEnd: oi + 1
|
|
526
540
|
};
|
|
527
541
|
};
|
|
528
542
|
|
|
@@ -536,9 +550,6 @@ const checkSourceFileIndexes = (startIndexes, endIndexes) => {
|
|
|
536
550
|
sourceIndex: s1
|
|
537
551
|
};
|
|
538
552
|
}
|
|
539
|
-
return {
|
|
540
|
-
error: true
|
|
541
|
-
};
|
|
542
553
|
};
|
|
543
554
|
|
|
544
555
|
const checkIndex21 = (s1, s2, e1) => {
|
|
@@ -553,9 +564,6 @@ const checkSourceFileIndexes = (startIndexes, endIndexes) => {
|
|
|
553
564
|
sourceIndex: e1
|
|
554
565
|
};
|
|
555
566
|
}
|
|
556
|
-
return {
|
|
557
|
-
error: true
|
|
558
|
-
};
|
|
559
567
|
};
|
|
560
568
|
|
|
561
569
|
const checkIndex12 = (s1, e1, e2) => {
|
|
@@ -570,9 +578,6 @@ const checkSourceFileIndexes = (startIndexes, endIndexes) => {
|
|
|
570
578
|
sourceIndex: s1
|
|
571
579
|
};
|
|
572
580
|
}
|
|
573
|
-
return {
|
|
574
|
-
error: true
|
|
575
|
-
};
|
|
576
581
|
};
|
|
577
582
|
|
|
578
583
|
const checkIndex22 = (s1, s2, e1, e2) => {
|
|
@@ -602,10 +607,6 @@ const checkSourceFileIndexes = (startIndexes, endIndexes) => {
|
|
|
602
607
|
// both between two mappings: 38,39 ~ 38,39
|
|
603
608
|
// if (s1 === e1 && s2 === e2) {
|
|
604
609
|
// }
|
|
605
|
-
|
|
606
|
-
return {
|
|
607
|
-
error: true
|
|
608
|
-
};
|
|
609
610
|
};
|
|
610
611
|
|
|
611
612
|
// both exact matched
|
|
@@ -626,13 +627,20 @@ const checkSourceFileIndexes = (startIndexes, endIndexes) => {
|
|
|
626
627
|
|
|
627
628
|
};
|
|
628
629
|
|
|
629
|
-
const getOriginalState = (
|
|
630
|
+
const getOriginalState = (start, end, state, originalMap) => {
|
|
631
|
+
|
|
632
|
+
const mappingInfo = getMappingInfo(start, end, state);
|
|
633
|
+
if (mappingInfo.error) {
|
|
634
|
+
return mappingInfo;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
const { startMappings, endMappings } = mappingInfo;
|
|
630
638
|
|
|
631
639
|
// check source file indexes
|
|
632
640
|
const startIndexes = [].concat(startMappings).map((it) => it.sourceIndex);
|
|
633
641
|
const endIndexes = [].concat(endMappings).map((it) => it.sourceIndex);
|
|
634
|
-
const
|
|
635
|
-
if (
|
|
642
|
+
const results = checkSourceFileIndexes(startIndexes, endIndexes);
|
|
643
|
+
if (!results) {
|
|
636
644
|
return {
|
|
637
645
|
error: true,
|
|
638
646
|
errors: [`invalid source indexes: ${EC.yellow(`${startIndexes} ~ ${endIndexes}`)}`]
|
|
@@ -641,7 +649,7 @@ const getOriginalState = (startMappings, endMappings, originalMap) => {
|
|
|
641
649
|
|
|
642
650
|
const {
|
|
643
651
|
sourceIndex, crossStart, crossEnd
|
|
644
|
-
} =
|
|
652
|
+
} = results;
|
|
645
653
|
|
|
646
654
|
// if (crossStart || crossEnd) {
|
|
647
655
|
// console.log(EC.magenta('cross file'), EC.yellow(`${startIndexes} ~ ${endIndexes}`));
|
|
@@ -655,11 +663,17 @@ const getOriginalState = (startMappings, endMappings, originalMap) => {
|
|
|
655
663
|
};
|
|
656
664
|
}
|
|
657
665
|
|
|
666
|
+
// cache for original info
|
|
658
667
|
return {
|
|
659
668
|
// for debug
|
|
660
669
|
// startIndexes,
|
|
661
670
|
// endIndexes,
|
|
662
671
|
|
|
672
|
+
start,
|
|
673
|
+
end,
|
|
674
|
+
startMappings,
|
|
675
|
+
endMappings,
|
|
676
|
+
|
|
663
677
|
sourceIndex,
|
|
664
678
|
crossStart,
|
|
665
679
|
crossEnd,
|
|
@@ -667,7 +681,9 @@ const getOriginalState = (startMappings, endMappings, originalMap) => {
|
|
|
667
681
|
};
|
|
668
682
|
};
|
|
669
683
|
|
|
670
|
-
const getMappingInfo = (
|
|
684
|
+
const getMappingInfo = (start, end, state) => {
|
|
685
|
+
|
|
686
|
+
const { decodedMappings } = state;
|
|
671
687
|
// possible no length
|
|
672
688
|
if (decodedMappings.length < 2) {
|
|
673
689
|
return {
|
|
@@ -677,9 +693,6 @@ const getMappingInfo = (decodedMappings, start, end) => {
|
|
|
677
693
|
}
|
|
678
694
|
|
|
679
695
|
// start: inclusive
|
|
680
|
-
// end: exclusive
|
|
681
|
-
// could be 4 mappings found
|
|
682
|
-
|
|
683
696
|
const startMappings = findMapping(decodedMappings, start);
|
|
684
697
|
if (!startMappings) {
|
|
685
698
|
return {
|
|
@@ -688,7 +701,8 @@ const getMappingInfo = (decodedMappings, start, end) => {
|
|
|
688
701
|
};
|
|
689
702
|
}
|
|
690
703
|
|
|
691
|
-
|
|
704
|
+
// end: exclusive
|
|
705
|
+
const endMappings = findMapping(decodedMappings, end - 1);
|
|
692
706
|
if (!endMappings) {
|
|
693
707
|
return {
|
|
694
708
|
error: true,
|
|
@@ -696,6 +710,7 @@ const getMappingInfo = (decodedMappings, start, end) => {
|
|
|
696
710
|
};
|
|
697
711
|
}
|
|
698
712
|
|
|
713
|
+
// could be 4 mappings found
|
|
699
714
|
return {
|
|
700
715
|
startMappings,
|
|
701
716
|
endMappings
|
|
@@ -704,7 +719,7 @@ const getMappingInfo = (decodedMappings, start, end) => {
|
|
|
704
719
|
|
|
705
720
|
const findOriginalRange = (start, end, state, originalMap) => {
|
|
706
721
|
|
|
707
|
-
const { sourcePath
|
|
722
|
+
const { sourcePath } = state;
|
|
708
723
|
|
|
709
724
|
const createMappingError = (errors) => {
|
|
710
725
|
return {
|
|
@@ -716,29 +731,17 @@ const findOriginalRange = (start, end, state, originalMap) => {
|
|
|
716
731
|
};
|
|
717
732
|
};
|
|
718
733
|
|
|
719
|
-
const
|
|
720
|
-
if (
|
|
721
|
-
return createMappingError(
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
const { startMappings, endMappings } = mappingInfo;
|
|
725
|
-
|
|
726
|
-
const rangeInfo = getOriginalState(startMappings, endMappings, originalMap);
|
|
727
|
-
if (rangeInfo.error) {
|
|
728
|
-
return createMappingError(rangeInfo.errors);
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
const originalStartResult = getOriginalStart(start, startMappings, state, rangeInfo);
|
|
732
|
-
if (originalStartResult.error) {
|
|
733
|
-
return createMappingError(originalStartResult.errors);
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
const originalEndResult = getOriginalEnd(end, endMappings, state, rangeInfo);
|
|
737
|
-
if (originalEndResult.error) {
|
|
738
|
-
return createMappingError(originalEndResult.errors);
|
|
734
|
+
const cache = getOriginalState(start, end, state, originalMap);
|
|
735
|
+
if (cache.error) {
|
|
736
|
+
return createMappingError(cache.errors);
|
|
739
737
|
}
|
|
740
738
|
|
|
739
|
+
const originalStartResult = getOriginalStartPosition(cache, state);
|
|
741
740
|
const { originalStart } = originalStartResult;
|
|
741
|
+
// could be used for end
|
|
742
|
+
cache.originalStart = originalStart;
|
|
743
|
+
|
|
744
|
+
const originalEndResult = getOriginalEndPosition(cache, state);
|
|
742
745
|
const { originalEnd } = originalEndResult;
|
|
743
746
|
|
|
744
747
|
// range start > end
|
|
@@ -746,7 +749,7 @@ const findOriginalRange = (start, end, state, originalMap) => {
|
|
|
746
749
|
return createMappingError([`invalid original start > end: ${EC.yellow(originalStart)} > ${EC.yellow(originalEnd)}`]);
|
|
747
750
|
}
|
|
748
751
|
|
|
749
|
-
const { originalState } =
|
|
752
|
+
const { originalState } = cache;
|
|
750
753
|
|
|
751
754
|
return {
|
|
752
755
|
start: originalStart,
|
package/lib/generate.js
CHANGED
|
@@ -2,7 +2,7 @@ const fs = require('fs');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const CG = require('console-grid');
|
|
4
4
|
const EC = require('eight-colors');
|
|
5
|
-
const { pathToFileURL } = require('url');
|
|
5
|
+
const { pathToFileURL, fileURLToPath } = require('url');
|
|
6
6
|
|
|
7
7
|
const Util = require('./utils/util.js');
|
|
8
8
|
const {
|
|
@@ -12,6 +12,7 @@ const {
|
|
|
12
12
|
const { mergeV8Coverage, saveV8Report } = require('./v8/v8.js');
|
|
13
13
|
|
|
14
14
|
const { convertV8List } = require('./converter/converter.js');
|
|
15
|
+
const { resolveSourceMap } = require('./converter/collect-source-maps.js');
|
|
15
16
|
|
|
16
17
|
const { minimatch } = require('./packages/monocart-coverage-vendor.js');
|
|
17
18
|
const { getGroupedRows } = require('./utils/snapshot.js');
|
|
@@ -720,7 +721,135 @@ const getInputData = async (inputList, all, cacheDir, addHandler) => {
|
|
|
720
721
|
};
|
|
721
722
|
};
|
|
722
723
|
|
|
724
|
+
// ========================================================================================================
|
|
725
|
+
|
|
726
|
+
const resolveEntrySource = (entry, sourceMapCache, sourceCache) => {
|
|
727
|
+
|
|
728
|
+
const url = entry.url;
|
|
729
|
+
|
|
730
|
+
// source from `source-id.json`
|
|
731
|
+
const sourceData = sourceCache[url];
|
|
732
|
+
if (sourceData) {
|
|
733
|
+
entry.source = sourceData.source;
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// source for typescript file from source map cache
|
|
738
|
+
// Note: no runtime code but lineLengths
|
|
739
|
+
const tsExtensionsPattern = /\.([cm]?ts|[tj]sx)($|\?)/;
|
|
740
|
+
if (tsExtensionsPattern.test(url)) {
|
|
741
|
+
const sourcemapData = sourceMapCache[url];
|
|
742
|
+
const lineLengths = sourcemapData && sourcemapData.lineLengths;
|
|
743
|
+
|
|
744
|
+
// for fake source file (can not parse to AST)
|
|
745
|
+
if (lineLengths) {
|
|
746
|
+
let fakeSource = '';
|
|
747
|
+
sourcemapData.lineLengths.forEach((length) => {
|
|
748
|
+
fakeSource += `${''.padEnd(length, '*')}\n`;
|
|
749
|
+
});
|
|
750
|
+
entry.fake = true;
|
|
751
|
+
entry.source = fakeSource;
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// Note: it could be jsx format even extname is `.js`
|
|
758
|
+
const filePath = fileURLToPath(url);
|
|
759
|
+
if (fs.existsSync(filePath)) {
|
|
760
|
+
entry.source = fs.readFileSync(filePath).toString('utf8');
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
};
|
|
764
|
+
|
|
765
|
+
const resolveEntrySourceMap = (entry, sourceMapCache) => {
|
|
766
|
+
// sourcemap data
|
|
767
|
+
const sourcemapData = sourceMapCache[entry.url];
|
|
768
|
+
if (sourcemapData) {
|
|
769
|
+
if (sourcemapData.data) {
|
|
770
|
+
entry.sourceMap = resolveSourceMap(sourcemapData.data, entry.url);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
|
|
775
|
+
const readCoverageData = (filePath, entryFilter, sourceCache) => {
|
|
776
|
+
|
|
777
|
+
const content = fs.readFileSync(filePath).toString('utf-8');
|
|
778
|
+
if (!content) {
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
const json = JSON.parse(content);
|
|
783
|
+
let coverageData = json.result;
|
|
784
|
+
if (!Util.isList(coverageData)) {
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// filter node internal files, should no anonymous for nodejs
|
|
789
|
+
coverageData = coverageData.filter((entry) => entry.url && entry.url.startsWith('file:'));
|
|
790
|
+
coverageData = coverageData.filter(entryFilter);
|
|
791
|
+
|
|
792
|
+
if (!Util.isList(coverageData)) {
|
|
793
|
+
// Util.logDebug('No coverage data after filter');
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
const sourceMapCache = json['source-map-cache'] || {};
|
|
798
|
+
for (const entry of coverageData) {
|
|
799
|
+
resolveEntrySource(entry, sourceMapCache, sourceCache);
|
|
800
|
+
resolveEntrySourceMap(entry, sourceMapCache);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
return coverageData;
|
|
804
|
+
};
|
|
805
|
+
|
|
806
|
+
const readFromDir = async (dir, entryFilter, addHandler) => {
|
|
807
|
+
|
|
808
|
+
if (!dir || !fs.existsSync(dir)) {
|
|
809
|
+
Util.logError(`Invalid V8 coverage dir: ${dir}`);
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
const files = fs.readdirSync(dir);
|
|
814
|
+
if (!files.length) {
|
|
815
|
+
Util.logInfo(`No coverage files in the dir: ${dir}`);
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
const coverageFiles = [];
|
|
820
|
+
const sourceCache = {};
|
|
821
|
+
files.forEach((filename) => {
|
|
822
|
+
const isCoverage = filename.startsWith('coverage-');
|
|
823
|
+
if (isCoverage) {
|
|
824
|
+
coverageFiles.push(filename);
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
const isSource = filename.startsWith('source-');
|
|
828
|
+
if (isSource) {
|
|
829
|
+
const filePath = path.resolve(dir, filename);
|
|
830
|
+
const content = fs.readFileSync(filePath).toString('utf-8');
|
|
831
|
+
if (content) {
|
|
832
|
+
const json = JSON.parse(content);
|
|
833
|
+
if (json.url) {
|
|
834
|
+
sourceCache[json.url] = json;
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
});
|
|
839
|
+
|
|
840
|
+
// filter before adding
|
|
841
|
+
for (const filename of coverageFiles) {
|
|
842
|
+
const filePath = path.resolve(dir, filename);
|
|
843
|
+
const coverageData = readCoverageData(filePath, entryFilter, sourceCache);
|
|
844
|
+
if (coverageData) {
|
|
845
|
+
await addHandler(coverageData);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
};
|
|
850
|
+
|
|
723
851
|
module.exports = {
|
|
724
852
|
getInputData,
|
|
853
|
+
readFromDir,
|
|
725
854
|
generateCoverageReports
|
|
726
855
|
};
|
package/lib/index.d.ts
CHANGED
|
@@ -347,6 +347,12 @@ declare namespace MCR {
|
|
|
347
347
|
* @param coverageData {array} V8 format, {object} Istanbul format */
|
|
348
348
|
add: (coverageData: any[] | any) => Promise<AddedResults>;
|
|
349
349
|
|
|
350
|
+
/**
|
|
351
|
+
* add V8 coverage from a dir
|
|
352
|
+
* @param dir node v8 coverage dir
|
|
353
|
+
*/
|
|
354
|
+
addFromDir: (dir: string) => Promise<void>;
|
|
355
|
+
|
|
350
356
|
/** generate report */
|
|
351
357
|
generate: () => Promise<CoverageResults>;
|
|
352
358
|
|
package/lib/index.js
CHANGED
|
@@ -7,7 +7,9 @@ const defaultOptions = require('./default/options.js');
|
|
|
7
7
|
const Util = require('./utils/util.js');
|
|
8
8
|
|
|
9
9
|
const { initV8ListAndSourcemap, getEntryFilter } = require('./v8/v8.js');
|
|
10
|
-
const {
|
|
10
|
+
const {
|
|
11
|
+
getInputData, readFromDir, generateCoverageReports
|
|
12
|
+
} = require('./generate.js');
|
|
11
13
|
const { getSnapshot, diffSnapshot } = require('./utils/snapshot.js');
|
|
12
14
|
const CDPClient = require('./client/cdp-client.js');
|
|
13
15
|
|
|
@@ -26,12 +28,15 @@ const resolveConfigOptions = async (configPath) => {
|
|
|
26
28
|
err = ee;
|
|
27
29
|
}
|
|
28
30
|
|
|
29
|
-
if (err
|
|
31
|
+
if (err) {
|
|
30
32
|
Util.logError(`ERROR: failed to load config "${configPath}": ${err && err.message} `);
|
|
31
33
|
return;
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
// could be multiple level default
|
|
37
|
+
while (configOptions && configOptions.default) {
|
|
38
|
+
configOptions = configOptions.default;
|
|
39
|
+
}
|
|
35
40
|
|
|
36
41
|
return configOptions;
|
|
37
42
|
};
|
|
@@ -113,6 +118,14 @@ class CoverageReport {
|
|
|
113
118
|
return results;
|
|
114
119
|
}
|
|
115
120
|
|
|
121
|
+
// add coverage from dir
|
|
122
|
+
addFromDir(dir) {
|
|
123
|
+
const entryFilter = this.getEntryFilter();
|
|
124
|
+
return readFromDir(dir, entryFilter, (coverageData) => {
|
|
125
|
+
return this.add(coverageData);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
116
129
|
// generate report
|
|
117
130
|
async generate() {
|
|
118
131
|
|
|
@@ -227,9 +240,9 @@ class CoverageReport {
|
|
|
227
240
|
'mcr.config.cjs',
|
|
228
241
|
'mcr.config.mjs',
|
|
229
242
|
'mcr.config.json',
|
|
243
|
+
'mcr.config.ts',
|
|
230
244
|
'.mcrrc.js',
|
|
231
|
-
'.mcrrc'
|
|
232
|
-
'mcr.config.ts'
|
|
245
|
+
'.mcrrc'
|
|
233
246
|
];
|
|
234
247
|
|
|
235
248
|
const existsList = configList.filter((p) => p && fs.existsSync(p));
|
|
@@ -252,7 +265,8 @@ class CoverageReport {
|
|
|
252
265
|
return;
|
|
253
266
|
}
|
|
254
267
|
|
|
255
|
-
Util.logInfo(`Loaded
|
|
268
|
+
Util.logInfo(`Loaded: ${EC.cyan(configPath)}`);
|
|
269
|
+
|
|
256
270
|
// init options again
|
|
257
271
|
this.options = {
|
|
258
272
|
... defaultOptions,
|