monocart-coverage-reports 2.2.2 → 2.3.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 +140 -26
- package/lib/cli.js +0 -6
- package/lib/converter/ast.js +26 -5
- package/lib/converter/collect-source-maps.js +15 -3
- package/lib/converter/converter.js +306 -120
- package/lib/converter/find-original-range.js +5 -0
- package/lib/converter/info-branch.js +13 -5
- package/lib/default/options.js +3 -0
- package/lib/generate.js +132 -65
- package/lib/index.d.ts +13 -3
- package/lib/index.js +45 -15
- package/lib/istanbul/istanbul.js +7 -7
- package/lib/packages/monocart-coverage-v8.js +1 -1
- package/lib/platform/share.js +13 -0
- package/lib/utils/dedupe.js +21 -8
- package/lib/utils/source-path.js +5 -0
- package/lib/utils/util.js +30 -1
- package/lib/v8/v8.js +85 -86
- package/package.json +5 -3
- package/lib/utils/decode-mappings-worker.js +0 -9
- package/lib/utils/decode-mappings.js +0 -35
|
@@ -1,27 +1,12 @@
|
|
|
1
|
-
// https://github.com/demurgos/v8-coverage
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
4
|
-
* @
|
|
5
|
-
*
|
|
6
|
-
* @true means that the ranges form a tree of blocks representing how many times each statement or expression inside was executed.
|
|
7
|
-
* It detects skipped or repeated statements. The root range counts the number of function calls.
|
|
8
|
-
* @functionName can be an empty string. This is common for the FunctionCov representing the whole module.
|
|
2
|
+
* V8 Coverage Data Converter
|
|
3
|
+
* @copyright https://github.com/cenfun/monocart-coverage-reports
|
|
4
|
+
* @author cenfun@gmail.com
|
|
9
5
|
*/
|
|
10
|
-
// https://github.com/bcoe/v8-coverage
|
|
11
|
-
/**
|
|
12
|
-
* @ranges is always non-empty. The first range is called the "root range".
|
|
13
|
-
* @isBlockCoverage indicates if the function has block coverage information.
|
|
14
|
-
If this is false, it usually means that the functions was never called.
|
|
15
|
-
It seems to be equivalent to ranges.length === 1 && ranges[0].count === 0.
|
|
16
|
-
* @functionName can be an empty string. This is common for the FunctionCov representing the whole module.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
// if you have a line of code that says `var x= 10; console.log(x);` that's one line and 2 statements.
|
|
20
6
|
|
|
21
7
|
const path = require('path');
|
|
22
8
|
|
|
23
9
|
const Util = require('../utils/util.js');
|
|
24
|
-
const decodeMappings = require('../utils/decode-mappings.js');
|
|
25
10
|
|
|
26
11
|
// position mapping for conversion between offset and line/column
|
|
27
12
|
const { Locator } = require('monocart-formatter');
|
|
@@ -29,8 +14,11 @@ const findOriginalRange = require('./find-original-range.js');
|
|
|
29
14
|
const { getJsAstInfo, getCssAstInfo } = require('./ast.js');
|
|
30
15
|
const { getIgnoredRanges } = require('./ignore.js');
|
|
31
16
|
|
|
32
|
-
const {
|
|
17
|
+
const {
|
|
18
|
+
sortRanges, dedupeCountRanges, mergeRangesWith
|
|
19
|
+
} = require('../utils/dedupe.js');
|
|
33
20
|
const { getSourceType, initSourceMapSourcePath } = require('../utils/source-path.js');
|
|
21
|
+
const { decode } = require('../packages/monocart-coverage-vendor.js');
|
|
34
22
|
|
|
35
23
|
const InfoLine = require('./info-line.js');
|
|
36
24
|
const InfoBranch = require('./info-branch.js');
|
|
@@ -226,13 +214,14 @@ const calculateV8Lines = (lines, blankCount, commentCount) => {
|
|
|
226
214
|
* * `f` - hit count for functions
|
|
227
215
|
* * `b` - hit count for branches
|
|
228
216
|
*/
|
|
229
|
-
const collectFileCoverage = (
|
|
217
|
+
const collectFileCoverage = (v8Data, state, options) => {
|
|
230
218
|
|
|
231
|
-
const { sourcePath } = item;
|
|
232
219
|
const {
|
|
233
220
|
bytes,
|
|
234
221
|
functions,
|
|
235
222
|
branches,
|
|
223
|
+
|
|
224
|
+
sourcePath,
|
|
236
225
|
locator
|
|
237
226
|
} = state;
|
|
238
227
|
|
|
@@ -277,11 +266,13 @@ const collectFileCoverage = (item, state, coverageData, options) => {
|
|
|
277
266
|
data.functions = functions.map((info) => {
|
|
278
267
|
return info.getRange();
|
|
279
268
|
});
|
|
269
|
+
sortRanges(data.functions);
|
|
280
270
|
|
|
281
271
|
// branch group with locations to flat branches
|
|
282
272
|
data.branches = branches.map((info) => {
|
|
283
273
|
return info.getRanges();
|
|
284
274
|
}).flat();
|
|
275
|
+
sortRanges(data.branches);
|
|
285
276
|
|
|
286
277
|
// ==========================================
|
|
287
278
|
// lines
|
|
@@ -292,8 +283,8 @@ const collectFileCoverage = (item, state, coverageData, options) => {
|
|
|
292
283
|
|
|
293
284
|
// ==========================================
|
|
294
285
|
// v8 data and summary
|
|
295
|
-
|
|
296
|
-
|
|
286
|
+
v8Data.data = data;
|
|
287
|
+
v8Data.summary = {
|
|
297
288
|
functions: calculateV8Functions(data.functions),
|
|
298
289
|
branches: calculateV8Branches(data.branches),
|
|
299
290
|
lines: calculateV8Lines(lines, blankCount, commentCount)
|
|
@@ -301,7 +292,7 @@ const collectFileCoverage = (item, state, coverageData, options) => {
|
|
|
301
292
|
|
|
302
293
|
// ==========================================
|
|
303
294
|
// istanbul
|
|
304
|
-
const
|
|
295
|
+
const istanbulData = {
|
|
305
296
|
path: sourcePath,
|
|
306
297
|
|
|
307
298
|
statementMap: {},
|
|
@@ -317,8 +308,8 @@ const collectFileCoverage = (item, state, coverageData, options) => {
|
|
|
317
308
|
data.lines = {};
|
|
318
309
|
|
|
319
310
|
lines.filter((it) => !it.ignored).forEach((line, index) => {
|
|
320
|
-
|
|
321
|
-
|
|
311
|
+
istanbulData.statementMap[`${index}`] = line.generate();
|
|
312
|
+
istanbulData.s[`${index}`] = line.count;
|
|
322
313
|
|
|
323
314
|
let count = 0;
|
|
324
315
|
if (line.covered) {
|
|
@@ -331,18 +322,18 @@ const collectFileCoverage = (item, state, coverageData, options) => {
|
|
|
331
322
|
});
|
|
332
323
|
|
|
333
324
|
functions.filter((it) => !it.ignored).forEach((fn, index) => {
|
|
334
|
-
|
|
335
|
-
|
|
325
|
+
istanbulData.fnMap[`${index}`] = fn.generate(locator);
|
|
326
|
+
istanbulData.f[`${index}`] = fn.count;
|
|
336
327
|
});
|
|
337
328
|
|
|
338
329
|
branches.filter((it) => !it.ignored).forEach((branch, index) => {
|
|
339
330
|
const { map, counts } = branch.generate(locator);
|
|
340
|
-
|
|
341
|
-
|
|
331
|
+
istanbulData.branchMap[`${index}`] = map;
|
|
332
|
+
istanbulData.b[`${index}`] = counts;
|
|
342
333
|
});
|
|
343
334
|
|
|
344
|
-
//
|
|
345
|
-
|
|
335
|
+
// istanbul data
|
|
336
|
+
return istanbulData;
|
|
346
337
|
|
|
347
338
|
};
|
|
348
339
|
|
|
@@ -612,13 +603,13 @@ const handleOriginalBytesCoverage = (state, originalMap) => {
|
|
|
612
603
|
|
|
613
604
|
// ========================================================================================================
|
|
614
605
|
|
|
615
|
-
const decodeSourceMappings =
|
|
606
|
+
const decodeSourceMappings = (state, originalDecodedMap) => {
|
|
616
607
|
|
|
617
608
|
const generatedLocator = state.locator;
|
|
618
609
|
|
|
619
610
|
const { sources, mappings } = state.sourceMap;
|
|
620
611
|
|
|
621
|
-
const decodedList =
|
|
612
|
+
const decodedList = decode(mappings);
|
|
622
613
|
|
|
623
614
|
sources.forEach((source, i) => {
|
|
624
615
|
originalDecodedMap.set(i, []);
|
|
@@ -679,7 +670,7 @@ const getOriginalDecodedMappings = (originalDecodedMap, sourceIndex, locator) =>
|
|
|
679
670
|
// all mappings for the original file sorted
|
|
680
671
|
const decodedMappings = originalDecodedMap.get(sourceIndex);
|
|
681
672
|
|
|
682
|
-
if (!
|
|
673
|
+
if (!decodedMappings) {
|
|
683
674
|
return [];
|
|
684
675
|
}
|
|
685
676
|
|
|
@@ -713,8 +704,6 @@ const initOriginalList = (state, originalDecodedMap, options) => {
|
|
|
713
704
|
sourceFilter = () => true;
|
|
714
705
|
}
|
|
715
706
|
|
|
716
|
-
const fileSources = state.fileSources;
|
|
717
|
-
|
|
718
707
|
// create original content mappings
|
|
719
708
|
const originalMap = new Map();
|
|
720
709
|
|
|
@@ -734,9 +723,6 @@ const initOriginalList = (state, originalDecodedMap, options) => {
|
|
|
734
723
|
return;
|
|
735
724
|
}
|
|
736
725
|
|
|
737
|
-
// keep original formatted content
|
|
738
|
-
fileSources[sourcePath] = sourceContent;
|
|
739
|
-
|
|
740
726
|
const locator = new Locator(sourceContent);
|
|
741
727
|
|
|
742
728
|
const decodedMappings = getOriginalDecodedMappings(originalDecodedMap, sourceIndex, locator);
|
|
@@ -747,11 +733,11 @@ const initOriginalList = (state, originalDecodedMap, options) => {
|
|
|
747
733
|
|
|
748
734
|
const originalState = {
|
|
749
735
|
original: true,
|
|
750
|
-
//
|
|
736
|
+
// original file is js
|
|
751
737
|
js: true,
|
|
752
738
|
type,
|
|
753
|
-
sourcePath,
|
|
754
739
|
source: sourceContent,
|
|
740
|
+
sourcePath,
|
|
755
741
|
locator,
|
|
756
742
|
decodedMappings,
|
|
757
743
|
// coverage info
|
|
@@ -761,7 +747,9 @@ const initOriginalList = (state, originalDecodedMap, options) => {
|
|
|
761
747
|
astInfo: {
|
|
762
748
|
functions: [],
|
|
763
749
|
branches: []
|
|
764
|
-
}
|
|
750
|
+
},
|
|
751
|
+
// coverage data
|
|
752
|
+
v8Data: {}
|
|
765
753
|
};
|
|
766
754
|
|
|
767
755
|
originalMap.set(sourceIndex, originalState);
|
|
@@ -770,14 +758,12 @@ const initOriginalList = (state, originalDecodedMap, options) => {
|
|
|
770
758
|
return originalMap;
|
|
771
759
|
};
|
|
772
760
|
|
|
773
|
-
const collectOriginalList = (
|
|
761
|
+
const collectOriginalList = (state, originalMap) => {
|
|
774
762
|
|
|
775
763
|
const { fileUrls, sourceMap } = state;
|
|
776
|
-
const distFile = sourceMap.file || path.basename(
|
|
764
|
+
const distFile = sourceMap.file || path.basename(state.sourcePath);
|
|
777
765
|
|
|
778
766
|
// collect original files
|
|
779
|
-
const sourceList = [];
|
|
780
|
-
|
|
781
767
|
originalMap.forEach((originalState) => {
|
|
782
768
|
|
|
783
769
|
const {
|
|
@@ -788,7 +774,7 @@ const collectOriginalList = (item, state, originalMap, options) => {
|
|
|
788
774
|
const url = fileUrls[sourcePath] || sourcePath;
|
|
789
775
|
|
|
790
776
|
// add dist for id
|
|
791
|
-
const id = Util.calculateSha1(
|
|
777
|
+
const id = Util.calculateSha1(sourcePath + source);
|
|
792
778
|
|
|
793
779
|
const sourceItem = {
|
|
794
780
|
url,
|
|
@@ -800,31 +786,26 @@ const collectOriginalList = (item, state, originalMap, options) => {
|
|
|
800
786
|
source
|
|
801
787
|
};
|
|
802
788
|
|
|
803
|
-
//
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
sourceList.push(sourceItem);
|
|
789
|
+
// save v8 data and add to originalList
|
|
790
|
+
originalState.v8Data = sourceItem;
|
|
791
|
+
state.originalList.push(originalState);
|
|
807
792
|
});
|
|
808
793
|
|
|
809
|
-
return sourceList;
|
|
810
794
|
};
|
|
811
795
|
|
|
812
796
|
// ========================================================================================================
|
|
813
797
|
|
|
814
|
-
const generateCoverageForDist = (
|
|
798
|
+
const generateCoverageForDist = (state) => {
|
|
815
799
|
|
|
816
800
|
handleFunctionsCoverage(state);
|
|
817
801
|
handleBranchesCoverage(state);
|
|
818
802
|
handleBytesCoverage(state);
|
|
819
803
|
|
|
820
|
-
collectFileCoverage(item, state, state.coverageData, options);
|
|
821
|
-
|
|
822
804
|
};
|
|
823
805
|
|
|
824
|
-
const unpackSourceMap =
|
|
806
|
+
const unpackSourceMap = (state, options) => {
|
|
825
807
|
|
|
826
|
-
const {
|
|
827
|
-
const sourceMap = state.sourceMap;
|
|
808
|
+
const { sourceMap } = state;
|
|
828
809
|
|
|
829
810
|
// keep original urls
|
|
830
811
|
const fileUrls = {};
|
|
@@ -834,12 +815,10 @@ const unpackSourceMap = async (item, state, options) => {
|
|
|
834
815
|
|
|
835
816
|
// ===============================================
|
|
836
817
|
// decode mappings for each original file
|
|
837
|
-
|
|
818
|
+
|
|
838
819
|
const originalDecodedMap = new Map();
|
|
839
820
|
// for find-original-range
|
|
840
|
-
state.decodedMappings =
|
|
841
|
-
// only debug level
|
|
842
|
-
Util.logTime(`decode source mappings: ${sourcePath}`, time_start_decode);
|
|
821
|
+
state.decodedMappings = decodeSourceMappings(state, originalDecodedMap);
|
|
843
822
|
|
|
844
823
|
// filter original list and init list
|
|
845
824
|
const originalMap = initOriginalList(state, originalDecodedMap, options);
|
|
@@ -868,28 +847,28 @@ const unpackSourceMap = async (item, state, options) => {
|
|
|
868
847
|
handleOriginalBytesCoverage(state, originalMap);
|
|
869
848
|
|
|
870
849
|
// collect coverage for original list
|
|
871
|
-
|
|
850
|
+
collectOriginalList(state, originalMap);
|
|
872
851
|
|
|
873
852
|
};
|
|
874
853
|
|
|
875
|
-
const unpackDistFile =
|
|
854
|
+
const unpackDistFile = (item, state, options) => {
|
|
876
855
|
|
|
877
856
|
if (state.sourceMap) {
|
|
878
857
|
if (Util.loggingType === 'debug') {
|
|
879
858
|
// js self
|
|
880
859
|
item.debug = true;
|
|
881
|
-
generateCoverageForDist(
|
|
860
|
+
generateCoverageForDist(state);
|
|
882
861
|
} else {
|
|
883
862
|
item.dedupe = true;
|
|
884
863
|
}
|
|
885
864
|
|
|
886
865
|
// unpack source map
|
|
887
|
-
|
|
866
|
+
unpackSourceMap(state, options);
|
|
888
867
|
|
|
889
868
|
} else {
|
|
890
869
|
|
|
891
870
|
// css/js self
|
|
892
|
-
generateCoverageForDist(
|
|
871
|
+
generateCoverageForDist(state);
|
|
893
872
|
|
|
894
873
|
}
|
|
895
874
|
|
|
@@ -897,27 +876,260 @@ const unpackDistFile = async (item, state, options) => {
|
|
|
897
876
|
|
|
898
877
|
// ========================================================================================================
|
|
899
878
|
|
|
900
|
-
const
|
|
901
|
-
const
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
879
|
+
const filterCoverageList = (item) => {
|
|
880
|
+
const {
|
|
881
|
+
functions, scriptOffset, source
|
|
882
|
+
} = item;
|
|
883
|
+
|
|
884
|
+
// no script offset
|
|
885
|
+
if (!scriptOffset) {
|
|
886
|
+
return functions;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
// vm script offset
|
|
890
|
+
const minOffset = scriptOffset;
|
|
891
|
+
// the inline sourcemap could be removed
|
|
892
|
+
const maxOffset = source.length;
|
|
893
|
+
|
|
894
|
+
const rootFunctionInfo = {
|
|
895
|
+
root: true,
|
|
896
|
+
ranges: [{
|
|
897
|
+
startOffset: minOffset,
|
|
898
|
+
endOffset: maxOffset,
|
|
899
|
+
count: 1
|
|
900
|
+
}]
|
|
901
|
+
};
|
|
902
|
+
|
|
903
|
+
const coverageList = functions.filter((block) => {
|
|
904
|
+
const { ranges } = block;
|
|
905
|
+
|
|
906
|
+
// first one is function coverage info
|
|
907
|
+
const functionRange = ranges[0];
|
|
908
|
+
const { startOffset, endOffset } = functionRange;
|
|
909
|
+
if (startOffset >= minOffset && endOffset <= maxOffset) {
|
|
910
|
+
return true;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
// blocks
|
|
914
|
+
const len = ranges.length;
|
|
915
|
+
if (len > 1) {
|
|
916
|
+
for (let i = 1; i < len; i++) {
|
|
917
|
+
const range = ranges[i];
|
|
918
|
+
if (range.startOffset >= minOffset && range.endOffset <= maxOffset) {
|
|
919
|
+
rootFunctionInfo.ranges.push(range);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
905
922
|
}
|
|
923
|
+
|
|
924
|
+
return false;
|
|
906
925
|
});
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
926
|
+
|
|
927
|
+
// first one for root function
|
|
928
|
+
if (rootFunctionInfo.ranges.length > 1) {
|
|
929
|
+
coverageList.unshift(rootFunctionInfo);
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
return coverageList;
|
|
933
|
+
};
|
|
934
|
+
|
|
935
|
+
// ========================================================================================================
|
|
936
|
+
|
|
937
|
+
const isCoveredInRanges = (range, uncoveredBytes) => {
|
|
938
|
+
if (!uncoveredBytes.length) {
|
|
939
|
+
return true;
|
|
912
940
|
}
|
|
941
|
+
for (const item of uncoveredBytes) {
|
|
942
|
+
if (range.start >= item.start && range.end <= item.end) {
|
|
943
|
+
return false;
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
return true;
|
|
947
|
+
};
|
|
948
|
+
|
|
949
|
+
const mergeV8Data = (state, stateList) => {
|
|
950
|
+
// console.log(stateList);
|
|
951
|
+
|
|
952
|
+
// const sourcePath = state.sourcePath;
|
|
953
|
+
// console.log(sourcePath);
|
|
954
|
+
// if (sourcePath.endsWith('scroll_zoom.ts')) {
|
|
955
|
+
// console.log('merge v8 data ===================================', sourcePath);
|
|
956
|
+
// console.log(stateList.map((it) => it.bytes));
|
|
957
|
+
// console.log(stateList.map((it) => it.functions));
|
|
958
|
+
// console.log(stateList.map((it) => it.branches.map((b) => [`${b.start}-${b.end}`, JSON.stringify(b.locations.map((l) => l.count))])));
|
|
959
|
+
// }
|
|
960
|
+
|
|
961
|
+
// ===========================================================
|
|
962
|
+
// bytes
|
|
963
|
+
const mergedBytes = [];
|
|
964
|
+
const uncoveredList = [];
|
|
965
|
+
stateList.forEach((st) => {
|
|
966
|
+
const bytes = dedupeCountRanges(st.bytes);
|
|
967
|
+
const uncoveredBytes = [];
|
|
968
|
+
bytes.forEach((range) => {
|
|
969
|
+
if (range.count) {
|
|
970
|
+
mergedBytes.push(range);
|
|
971
|
+
} else {
|
|
972
|
+
uncoveredBytes.push(range);
|
|
973
|
+
}
|
|
974
|
+
});
|
|
975
|
+
uncoveredList.push(uncoveredBytes);
|
|
976
|
+
});
|
|
977
|
+
// just remove uncovered range
|
|
978
|
+
uncoveredList.forEach((currentBytes) => {
|
|
979
|
+
currentBytes.forEach((range) => {
|
|
980
|
+
for (const targetBytes of uncoveredList) {
|
|
981
|
+
if (targetBytes === currentBytes) {
|
|
982
|
+
continue;
|
|
983
|
+
}
|
|
984
|
+
if (isCoveredInRanges(range, targetBytes)) {
|
|
985
|
+
return;
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
mergedBytes.push(range);
|
|
989
|
+
});
|
|
990
|
+
});
|
|
991
|
+
|
|
992
|
+
// will be dedupeCountRanges in collectFileCoverage
|
|
993
|
+
state.bytes = mergedBytes;
|
|
994
|
+
|
|
995
|
+
// ===========================================================
|
|
996
|
+
// functions
|
|
997
|
+
const allFunctions = stateList.map((it) => it.functions).flat();
|
|
998
|
+
const functionComparer = (lastRange, range) => {
|
|
999
|
+
// if (lastRange.start === range.start && lastRange.end === range.end) {
|
|
1000
|
+
// return true;
|
|
1001
|
+
// }
|
|
1002
|
+
|
|
1003
|
+
// function range could be from sourcemap, not exact matched
|
|
1004
|
+
|
|
1005
|
+
// end is same
|
|
1006
|
+
// {start: 2017, end: 2315, count: 481}
|
|
1007
|
+
// {start: 2018, end: 2315, count: 14}
|
|
1008
|
+
|
|
1009
|
+
// start is same
|
|
1010
|
+
// {start: 10204, end: 10379, count: 0}
|
|
1011
|
+
// {start: 10204, end: 10393, count: 5}
|
|
1012
|
+
|
|
1013
|
+
// only one position matched could be same
|
|
1014
|
+
if (lastRange.start === range.start || lastRange.end === range.end) {
|
|
1015
|
+
// console.log(lastRange.start, range.start, lastRange.end, range.end);
|
|
1016
|
+
|
|
1017
|
+
// if (lastRange.start === range.start) {
|
|
1018
|
+
// console.log(range.end - lastRange.end, lastRange.start, lastRange.end, 'end', range.end, state.sourcePath);
|
|
1019
|
+
// } else {
|
|
1020
|
+
// console.log(range.start - lastRange.start, lastRange.start, lastRange.end, 'start', range.start, state.sourcePath);
|
|
1021
|
+
// }
|
|
1022
|
+
|
|
1023
|
+
return true;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
return false;
|
|
1027
|
+
};
|
|
1028
|
+
const functionHandler = (lastRange, range) => {
|
|
1029
|
+
lastRange.count += range.count;
|
|
1030
|
+
};
|
|
1031
|
+
const mergedFunctions = mergeRangesWith(allFunctions, functionComparer, functionHandler);
|
|
1032
|
+
state.functions = mergedFunctions;
|
|
1033
|
+
|
|
1034
|
+
// ===========================================================
|
|
1035
|
+
// branches
|
|
1036
|
+
const allBranches = stateList.map((it) => it.branches).flat();
|
|
1037
|
+
const branchComparer = (lastRange, range) => {
|
|
1038
|
+
// exact matched because the branch range is generated from ast
|
|
1039
|
+
return lastRange.start === range.start && lastRange.end === range.end;
|
|
1040
|
+
};
|
|
1041
|
+
const branchHandler = (lastRange, range) => {
|
|
1042
|
+
// merge locations count
|
|
1043
|
+
lastRange.locations.forEach((item, i) => {
|
|
1044
|
+
const loc = range.locations[i];
|
|
1045
|
+
if (loc) {
|
|
1046
|
+
item.count += loc.count;
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
1049
|
+
};
|
|
1050
|
+
const mergedBranches = mergeRangesWith(allBranches, branchComparer, branchHandler);
|
|
1051
|
+
state.branches = mergedBranches;
|
|
1052
|
+
|
|
1053
|
+
// if (sourcePath.endsWith('scroll_zoom.ts')) {
|
|
1054
|
+
// console.log(mergedBytes);
|
|
1055
|
+
// console.log(mergedFunctions);
|
|
1056
|
+
// console.log(mergedBranches.map((b) => [`${b.start}-${b.end}`, JSON.stringify(b.locations.map((l) => l.count))]));
|
|
1057
|
+
// }
|
|
1058
|
+
|
|
1059
|
+
|
|
913
1060
|
};
|
|
914
1061
|
|
|
915
|
-
const
|
|
1062
|
+
const generateV8DataList = (stateList, options) => {
|
|
1063
|
+
|
|
1064
|
+
const stateMap = new Map();
|
|
1065
|
+
|
|
1066
|
+
// all original files from dist
|
|
1067
|
+
const allOriginalList = [];
|
|
1068
|
+
stateList.forEach((state) => {
|
|
1069
|
+
const { v8Data, originalList } = state;
|
|
1070
|
+
// dedupe dist file if not debug
|
|
1071
|
+
if (!v8Data.dedupe) {
|
|
1072
|
+
stateMap.set(v8Data.id, state);
|
|
1073
|
+
}
|
|
1074
|
+
allOriginalList.push(originalList);
|
|
1075
|
+
});
|
|
1076
|
+
|
|
1077
|
+
// merge istanbul and v8(converted)
|
|
1078
|
+
const mergeMap = new Map();
|
|
1079
|
+
allOriginalList.flat().forEach((originalState) => {
|
|
1080
|
+
const { v8Data } = originalState;
|
|
1081
|
+
const id = v8Data.id;
|
|
1082
|
+
// exists item
|
|
1083
|
+
const prevState = stateMap.get(id);
|
|
1084
|
+
if (prevState) {
|
|
1085
|
+
// ignore empty item, just override it
|
|
1086
|
+
if (!prevState.v8Data.empty) {
|
|
1087
|
+
if (mergeMap.has(id)) {
|
|
1088
|
+
mergeMap.get(id).push(originalState);
|
|
1089
|
+
} else {
|
|
1090
|
+
mergeMap.set(id, [prevState, originalState]);
|
|
1091
|
+
}
|
|
1092
|
+
return;
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
stateMap.set(id, originalState);
|
|
1096
|
+
});
|
|
1097
|
+
|
|
1098
|
+
const mergeIds = mergeMap.keys();
|
|
1099
|
+
for (const id of mergeIds) {
|
|
1100
|
+
const state = stateMap.get(id);
|
|
1101
|
+
// for source the type could be ts, so just use js (boolean)
|
|
1102
|
+
if (state.js) {
|
|
1103
|
+
mergeV8Data(state, mergeMap.get(id));
|
|
1104
|
+
} else {
|
|
1105
|
+
// should no css here, css can not be in sources
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
916
1108
|
|
|
917
|
-
//
|
|
1109
|
+
// new v8 data list (includes sources)
|
|
1110
|
+
const v8DataList = [];
|
|
1111
|
+
// global file sources and istanbul coverage data
|
|
918
1112
|
const fileSources = {};
|
|
919
1113
|
const coverageData = {};
|
|
920
|
-
|
|
1114
|
+
stateMap.forEach((state) => {
|
|
1115
|
+
const { v8Data } = state;
|
|
1116
|
+
const istanbulData = collectFileCoverage(v8Data, state, options);
|
|
1117
|
+
const { sourcePath, source } = v8Data;
|
|
1118
|
+
v8DataList.push(v8Data);
|
|
1119
|
+
fileSources[sourcePath] = source;
|
|
1120
|
+
coverageData[sourcePath] = istanbulData;
|
|
1121
|
+
});
|
|
1122
|
+
|
|
1123
|
+
return {
|
|
1124
|
+
v8DataList,
|
|
1125
|
+
fileSources,
|
|
1126
|
+
coverageData
|
|
1127
|
+
};
|
|
1128
|
+
};
|
|
1129
|
+
|
|
1130
|
+
const convertV8List = (v8list, options) => {
|
|
1131
|
+
|
|
1132
|
+
const stateList = [];
|
|
921
1133
|
|
|
922
1134
|
for (const item of v8list) {
|
|
923
1135
|
// console.log([item.id]);
|
|
@@ -930,14 +1142,11 @@ const convertV8List = async (v8list, options) => {
|
|
|
930
1142
|
const js = type === 'js';
|
|
931
1143
|
item.js = js;
|
|
932
1144
|
|
|
933
|
-
// append file source
|
|
934
|
-
fileSources[sourcePath] = source;
|
|
935
|
-
|
|
936
1145
|
// source mapping
|
|
937
1146
|
const locator = new Locator(source);
|
|
938
1147
|
|
|
939
1148
|
// ============================
|
|
940
|
-
// move
|
|
1149
|
+
// move sourceMap
|
|
941
1150
|
const sourceMap = item.sourceMap;
|
|
942
1151
|
if (sourceMap) {
|
|
943
1152
|
delete item.sourceMap;
|
|
@@ -948,7 +1157,7 @@ const convertV8List = async (v8list, options) => {
|
|
|
948
1157
|
let coverageList = [];
|
|
949
1158
|
let astInfo;
|
|
950
1159
|
if (js) {
|
|
951
|
-
coverageList = item
|
|
1160
|
+
coverageList = filterCoverageList(item);
|
|
952
1161
|
// remove original functions
|
|
953
1162
|
if (Util.loggingType !== 'debug') {
|
|
954
1163
|
delete item.functions;
|
|
@@ -966,57 +1175,34 @@ const convertV8List = async (v8list, options) => {
|
|
|
966
1175
|
// ============================
|
|
967
1176
|
|
|
968
1177
|
// current file and it's sources from sourceMap
|
|
1178
|
+
// see const originalState
|
|
969
1179
|
const state = {
|
|
970
1180
|
js,
|
|
971
1181
|
type,
|
|
1182
|
+
source,
|
|
972
1183
|
sourcePath,
|
|
973
1184
|
sourceMap,
|
|
974
|
-
coverageList,
|
|
975
1185
|
locator,
|
|
1186
|
+
decodedMappings: [],
|
|
976
1187
|
// coverage info
|
|
977
1188
|
bytes: [],
|
|
978
1189
|
functions: [],
|
|
979
1190
|
branches: [],
|
|
980
1191
|
astInfo,
|
|
981
|
-
// for
|
|
982
|
-
|
|
983
|
-
|
|
1192
|
+
// for sub source files
|
|
1193
|
+
coverageList,
|
|
1194
|
+
originalList: [],
|
|
1195
|
+
// coverage data
|
|
1196
|
+
v8Data: item
|
|
984
1197
|
};
|
|
985
1198
|
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
// merge state
|
|
989
|
-
Object.assign(fileSources, state.fileSources);
|
|
990
|
-
Object.assign(coverageData, state.coverageData);
|
|
991
|
-
|
|
992
|
-
if (Util.isList(state.sourceList)) {
|
|
993
|
-
sourceList = sourceList.concat(state.sourceList);
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
// add all sources
|
|
999
|
-
if (sourceList.length) {
|
|
1000
|
-
sourceList.forEach((item) => {
|
|
1199
|
+
unpackDistFile(item, state, options);
|
|
1001
1200
|
|
|
1002
|
-
|
|
1003
|
-
// exists same id, mark previous item as dedupe
|
|
1004
|
-
const prevItem = v8list.find((it) => it.id === item.id);
|
|
1005
|
-
if (prevItem) {
|
|
1006
|
-
prevItem.dedupe = true;
|
|
1007
|
-
}
|
|
1201
|
+
stateList.push(state);
|
|
1008
1202
|
|
|
1009
|
-
v8list.push(item);
|
|
1010
|
-
});
|
|
1011
1203
|
}
|
|
1012
1204
|
|
|
1013
|
-
|
|
1014
|
-
dedupeV8List(v8list);
|
|
1015
|
-
|
|
1016
|
-
return {
|
|
1017
|
-
fileSources,
|
|
1018
|
-
coverageData
|
|
1019
|
-
};
|
|
1205
|
+
return generateV8DataList(stateList, options);
|
|
1020
1206
|
|
|
1021
1207
|
};
|
|
1022
1208
|
|
|
@@ -545,6 +545,11 @@ const findEndMapping = (range, state, startMapping) => {
|
|
|
545
545
|
|
|
546
546
|
const findOriginalRange = (range, state, originalMap) => {
|
|
547
547
|
|
|
548
|
+
// if (typeof range.startOffset !== 'number') {
|
|
549
|
+
// console.log('=========================================================================', state.sourcePath);
|
|
550
|
+
// console.log(range);
|
|
551
|
+
// }
|
|
552
|
+
|
|
548
553
|
// startOffset: inclusive
|
|
549
554
|
// endOffset: exclusive
|
|
550
555
|
const startResult = findStartMapping(range, state, originalMap);
|