monocart-reporter 1.7.0 → 1.7.2
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 +8 -12
- package/lib/cli.js +1 -1
- package/lib/common.js +2 -3
- package/lib/default/options.js +4 -3
- package/lib/generate-data.js +2 -7
- package/lib/generate-report.js +10 -11
- package/lib/index.d.ts +2 -9
- package/lib/index.js +6 -0
- package/lib/merge-data.js +7 -6
- package/lib/plugins/audit/audit.js +4 -2
- package/lib/plugins/comments.js +2 -3
- package/lib/plugins/coverage/converter/collect-source-maps.js +194 -0
- package/lib/plugins/coverage/converter/converter.js +547 -0
- package/lib/plugins/coverage/converter/decode-mappings.js +49 -0
- package/lib/plugins/coverage/{v8 → converter}/dedupe.js +8 -1
- package/lib/plugins/coverage/converter/find-original-range.js +576 -0
- package/lib/plugins/coverage/converter/info-branch.js +30 -0
- package/lib/plugins/coverage/converter/info-function.js +29 -0
- package/lib/plugins/coverage/converter/info-line.js +20 -0
- package/lib/plugins/coverage/converter/position-mapping.js +183 -0
- package/lib/plugins/coverage/{coverage-utils.js → converter/source-path.js} +26 -42
- package/lib/plugins/coverage/coverage.js +61 -57
- package/lib/plugins/coverage/istanbul/istanbul.js +21 -174
- package/lib/plugins/coverage/v8/v8.js +22 -30
- package/lib/plugins/network/network.js +4 -13
- package/lib/plugins/state/client.js +3 -4
- package/lib/plugins/state/state.js +6 -3
- package/lib/runtime/monocart-code-viewer.js +1 -1
- package/lib/runtime/monocart-coverage.js +13 -14
- package/lib/runtime/monocart-formatter.js +1 -1
- package/lib/runtime/monocart-network.js +1 -1
- package/lib/runtime/monocart-reporter.js +1 -1
- package/lib/runtime/monocart-v8.js +1 -1
- package/lib/runtime/monocart-vendor.js +13 -13
- package/lib/utils/util.js +97 -3
- package/package.json +5 -6
- package/lib/plugins/coverage/v8/position-mapping.js +0 -92
- package/lib/plugins/coverage/v8/source-map.js +0 -464
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
|
|
3
|
+
const Util = require('../../../utils/util.js');
|
|
4
|
+
|
|
5
|
+
// position mapping for conversion between offset and line/column
|
|
6
|
+
const PositionMapping = require('./position-mapping.js');
|
|
7
|
+
|
|
8
|
+
const decodeMappings = require('./decode-mappings.js');
|
|
9
|
+
const findOriginalRange = require('./find-original-range.js');
|
|
10
|
+
|
|
11
|
+
const { dedupeCountRanges } = require('./dedupe.js');
|
|
12
|
+
const { getSourceType, initSourceMapSourcePath } = require('./source-path.js');
|
|
13
|
+
|
|
14
|
+
const InfoLine = require('./info-line.js');
|
|
15
|
+
const InfoBranch = require('./info-branch.js');
|
|
16
|
+
const InfoFunction = require('./info-function.js');
|
|
17
|
+
|
|
18
|
+
// ========================================================================================================
|
|
19
|
+
|
|
20
|
+
// istanbul coverage format
|
|
21
|
+
/**
|
|
22
|
+
* * `path` - the file path for which coverage is being tracked
|
|
23
|
+
* * `statementMap` - map of statement locations keyed by statement index
|
|
24
|
+
* * `fnMap` - map of function metadata keyed by function index
|
|
25
|
+
* * `branchMap` - map of branch metadata keyed by branch index
|
|
26
|
+
* * `s` - hit counts for statements
|
|
27
|
+
* * `f` - hit count for functions
|
|
28
|
+
* * `b` - hit count for branches
|
|
29
|
+
*/
|
|
30
|
+
const getFileCoverage = (sourcePath, inputData) => {
|
|
31
|
+
|
|
32
|
+
const {
|
|
33
|
+
lines, functions, branches, ranges
|
|
34
|
+
} = inputData;
|
|
35
|
+
|
|
36
|
+
// v8 ranges
|
|
37
|
+
inputData.ranges = dedupeCountRanges(ranges);
|
|
38
|
+
|
|
39
|
+
// istanbul coverage
|
|
40
|
+
const coverage = {
|
|
41
|
+
path: sourcePath,
|
|
42
|
+
|
|
43
|
+
statementMap: {},
|
|
44
|
+
s: {},
|
|
45
|
+
|
|
46
|
+
fnMap: {},
|
|
47
|
+
f: {},
|
|
48
|
+
|
|
49
|
+
branchMap: {},
|
|
50
|
+
b: {}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
lines.forEach((line, index) => {
|
|
54
|
+
coverage.statementMap[`${index}`] = line.generate();
|
|
55
|
+
coverage.s[`${index}`] = line.count;
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
functions.forEach((fn, index) => {
|
|
59
|
+
coverage.fnMap[`${index}`] = fn.generate();
|
|
60
|
+
coverage.f[`${index}`] = fn.count;
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
branches.forEach((branch, index) => {
|
|
64
|
+
coverage.branchMap[`${index}`] = branch.generate();
|
|
65
|
+
coverage.b[`${index}`] = [branch.count];
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return coverage;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// ========================================================================================================
|
|
72
|
+
|
|
73
|
+
const setLineCount = (lineMap, line, count) => {
|
|
74
|
+
const lineInfo = lineMap[line];
|
|
75
|
+
if (lineInfo) {
|
|
76
|
+
lineInfo.count = count;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const setSingleLineCount = (lineMap, sLoc, eLoc, count) => {
|
|
81
|
+
// nothing between
|
|
82
|
+
if (sLoc.column >= eLoc.column) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// sometimes column > length
|
|
87
|
+
if (sLoc.column <= sLoc.indent && eLoc.column >= eLoc.length) {
|
|
88
|
+
// console.log('single', sLoc.line);
|
|
89
|
+
setLineCount(lineMap, sLoc.line, count);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const updateLinesCount = (lineMap, sLoc, eLoc, count) => {
|
|
95
|
+
|
|
96
|
+
// single line
|
|
97
|
+
if (sLoc.line === eLoc.line) {
|
|
98
|
+
setSingleLineCount(lineMap, sLoc, eLoc, count);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const firstELoc = {
|
|
103
|
+
... sLoc,
|
|
104
|
+
column: sLoc.length
|
|
105
|
+
};
|
|
106
|
+
setSingleLineCount(lineMap, sLoc, firstELoc, count);
|
|
107
|
+
|
|
108
|
+
for (let i = sLoc.line + 1; i < eLoc.line; i++) {
|
|
109
|
+
setLineCount(lineMap, i, count);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const lastSLoc = {
|
|
113
|
+
... eLoc,
|
|
114
|
+
column: eLoc.indent
|
|
115
|
+
};
|
|
116
|
+
setSingleLineCount(lineMap, lastSLoc, eLoc, count);
|
|
117
|
+
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const initFileCoverage = (positionMapping) => {
|
|
121
|
+
|
|
122
|
+
// istanbul
|
|
123
|
+
const lines = [];
|
|
124
|
+
const functions = [];
|
|
125
|
+
const branches = [];
|
|
126
|
+
// v8
|
|
127
|
+
const ranges = [];
|
|
128
|
+
|
|
129
|
+
// add all lines
|
|
130
|
+
const lineMap = {};
|
|
131
|
+
|
|
132
|
+
const { commentedLines, blankLines } = positionMapping;
|
|
133
|
+
positionMapping.lines.forEach((it) => {
|
|
134
|
+
// exclude comments and blanks
|
|
135
|
+
if (commentedLines.includes(it.line) || blankLines.includes(it.line)) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
// line 1-base
|
|
139
|
+
const line = it.line + 1;
|
|
140
|
+
const lineInfo = new InfoLine(line, it.length);
|
|
141
|
+
lineMap[line] = lineInfo;
|
|
142
|
+
lines.push(lineInfo);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
lines, functions, branches, ranges, lineMap
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
// https://github.com/demurgos/v8-coverage
|
|
152
|
+
/**
|
|
153
|
+
* @ranges is always non-empty. The first range is called the "root range".
|
|
154
|
+
* @isBlockCoverage indicates if the function has block coverage information
|
|
155
|
+
* @false means that there is a single range and its count is the number of times the function was called.
|
|
156
|
+
* @true means that the ranges form a tree of blocks representing how many times each statement or expression inside was executed.
|
|
157
|
+
* It detects skipped or repeated statements. The root range counts the number of function calls.
|
|
158
|
+
*
|
|
159
|
+
* @functionName can be an empty string. This is common for the FunctionCov representing the whole module.
|
|
160
|
+
*/
|
|
161
|
+
const addCoverage = (coverage, block, range, index, positionMapping) => {
|
|
162
|
+
|
|
163
|
+
const {
|
|
164
|
+
functions, branches, ranges, lineMap
|
|
165
|
+
} = coverage;
|
|
166
|
+
|
|
167
|
+
const { isBlockCoverage, functionName } = block;
|
|
168
|
+
const {
|
|
169
|
+
startOffset, endOffset, count
|
|
170
|
+
} = range;
|
|
171
|
+
|
|
172
|
+
ranges.push({
|
|
173
|
+
start: startOffset,
|
|
174
|
+
end: endOffset,
|
|
175
|
+
count
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const sLoc = positionMapping.offsetToLocation(startOffset);
|
|
179
|
+
const eLoc = positionMapping.offsetToLocation(endOffset);
|
|
180
|
+
|
|
181
|
+
// line, column
|
|
182
|
+
updateLinesCount(lineMap, sLoc, eLoc, count);
|
|
183
|
+
|
|
184
|
+
if (isBlockCoverage) {
|
|
185
|
+
if (index === 0) {
|
|
186
|
+
// The root range counts the number of function calls
|
|
187
|
+
functions.push(new InfoFunction(sLoc, eLoc, count, functionName));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// index 0 not really a branch, but for covered whole function
|
|
191
|
+
branches.push(new InfoBranch(sLoc, eLoc, count));
|
|
192
|
+
|
|
193
|
+
} else {
|
|
194
|
+
functions.push(new InfoFunction(sLoc, eLoc, count, functionName));
|
|
195
|
+
|
|
196
|
+
// possible have branches in the function but no information for it
|
|
197
|
+
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// ========================================================================================================
|
|
202
|
+
|
|
203
|
+
const unpackDistSource = (item, state) => {
|
|
204
|
+
|
|
205
|
+
const positionMapping = state.positionMapping;
|
|
206
|
+
const coverage = initFileCoverage(positionMapping);
|
|
207
|
+
|
|
208
|
+
item.functions.forEach((block) => {
|
|
209
|
+
block.ranges.forEach((range, index) => {
|
|
210
|
+
addCoverage(coverage, block, range, index, positionMapping);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
const sourcePath = item.sourcePath;
|
|
215
|
+
state.coverageData[sourcePath] = getFileCoverage(sourcePath, coverage);
|
|
216
|
+
item.ranges = coverage.ranges;
|
|
217
|
+
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
// ========================================================================================================
|
|
221
|
+
|
|
222
|
+
const getOriginalDecodedMappings = (originalIndexMap, sourceIndex, positionMapping) => {
|
|
223
|
+
// all mappings for the original file sorted
|
|
224
|
+
const decodedMappings = originalIndexMap.get(sourceIndex);
|
|
225
|
+
|
|
226
|
+
if (!decodeMappings) {
|
|
227
|
+
return [];
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// sort by original line/column
|
|
231
|
+
decodedMappings.sort((a, b) => {
|
|
232
|
+
if (a.originalLine === b.originalLine) {
|
|
233
|
+
return a.originalColumn - b.originalColumn;
|
|
234
|
+
}
|
|
235
|
+
return a.originalLine - b.originalLine;
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// add offset and index
|
|
239
|
+
decodedMappings.forEach((item, i) => {
|
|
240
|
+
item.originalIndex = i;
|
|
241
|
+
item.originalOffset = positionMapping.locationToOffset({
|
|
242
|
+
line: item.originalLine + 1,
|
|
243
|
+
column: item.originalColumn
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
return decodedMappings;
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const initOriginalList = (sourceMap, originalIndexMap, fileSources, options) => {
|
|
251
|
+
|
|
252
|
+
// source filter
|
|
253
|
+
const { sources, sourcesContent } = sourceMap;
|
|
254
|
+
|
|
255
|
+
let sourceFilter = options.sourceFilter;
|
|
256
|
+
if (typeof sourceFilter !== 'function') {
|
|
257
|
+
sourceFilter = () => true;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// create original content mappings
|
|
261
|
+
const map = new Map();
|
|
262
|
+
|
|
263
|
+
sources.forEach((sourcePath, sourceIndex) => {
|
|
264
|
+
|
|
265
|
+
// filter
|
|
266
|
+
if (!sourceFilter(sourcePath)) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// console.log(`add source: ${k}`);
|
|
271
|
+
const sourceContent = sourcesContent[sourceIndex];
|
|
272
|
+
if (typeof sourceContent !== 'string') {
|
|
273
|
+
Util.logError(`not found source content: ${sourcePath}`);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// keep original formatted content
|
|
278
|
+
fileSources[sourcePath] = sourceContent;
|
|
279
|
+
|
|
280
|
+
const positionMapping = new PositionMapping(sourceContent);
|
|
281
|
+
|
|
282
|
+
const decodedMappings = getOriginalDecodedMappings(originalIndexMap, sourceIndex, positionMapping);
|
|
283
|
+
|
|
284
|
+
const coverage = initFileCoverage(positionMapping);
|
|
285
|
+
|
|
286
|
+
const type = getSourceType(sourcePath);
|
|
287
|
+
|
|
288
|
+
const originalState = {
|
|
289
|
+
source: sourceContent,
|
|
290
|
+
type,
|
|
291
|
+
sourcePath,
|
|
292
|
+
positionMapping,
|
|
293
|
+
decodedMappings,
|
|
294
|
+
coverage
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
map.set(sourceIndex, originalState);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
return map;
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
const decodeSourceMappings = async (sourceMap, generatedPositionMapping) => {
|
|
304
|
+
|
|
305
|
+
const decodedList = await decodeMappings(sourceMap.mappings);
|
|
306
|
+
|
|
307
|
+
const originalIndexMap = new Map();
|
|
308
|
+
sourceMap.sources.forEach((item, i) => {
|
|
309
|
+
originalIndexMap.set(i, []);
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
const allDecodedMappings = [];
|
|
313
|
+
let generatedIndex = 0;
|
|
314
|
+
decodedList.forEach((segments, generatedLine) => {
|
|
315
|
+
let item = null;
|
|
316
|
+
segments.forEach((segment) => {
|
|
317
|
+
const [generatedColumn, sourceIndex, originalLine, originalColumn] = segment;
|
|
318
|
+
const generatedOffset = generatedPositionMapping.locationToOffset({
|
|
319
|
+
// 1-base
|
|
320
|
+
line: generatedLine + 1,
|
|
321
|
+
column: generatedColumn
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
item = {
|
|
325
|
+
generatedOffset,
|
|
326
|
+
generatedLine,
|
|
327
|
+
generatedColumn,
|
|
328
|
+
generatedIndex,
|
|
329
|
+
|
|
330
|
+
sourceIndex,
|
|
331
|
+
originalLine,
|
|
332
|
+
originalColumn
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
allDecodedMappings.push(item);
|
|
336
|
+
generatedIndex += 1;
|
|
337
|
+
|
|
338
|
+
if (typeof sourceIndex === 'undefined') {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
originalIndexMap.get(sourceIndex).push(item);
|
|
343
|
+
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
// line last one
|
|
347
|
+
if (item) {
|
|
348
|
+
const line = generatedPositionMapping.getLine(item.generatedLine + 1);
|
|
349
|
+
// last column
|
|
350
|
+
item.generatedEndOffset = item.generatedOffset + (line.length - item.generatedColumn);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
// defaults to sort by generated offset, not need sort
|
|
356
|
+
// allDecodedMappings.sort((a, b) => {
|
|
357
|
+
// return a.generatedOffset - b.generatedOffset;
|
|
358
|
+
// });
|
|
359
|
+
|
|
360
|
+
return {
|
|
361
|
+
allDecodedMappings,
|
|
362
|
+
originalIndexMap
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
const unpackSourceMap = async (item, state, options) => {
|
|
368
|
+
const sourceMap = item.sourceMap;
|
|
369
|
+
const generatedPositionMapping = state.positionMapping;
|
|
370
|
+
const distFile = sourceMap.file || path.basename(item.sourcePath);
|
|
371
|
+
|
|
372
|
+
// keep original urls
|
|
373
|
+
const fileUrls = {};
|
|
374
|
+
initSourceMapSourcePath(sourceMap, fileUrls, options.sourcePath);
|
|
375
|
+
|
|
376
|
+
// decode mappings for each original file
|
|
377
|
+
const time_start_decode = Date.now();
|
|
378
|
+
const { allDecodedMappings, originalIndexMap } = await decodeSourceMappings(sourceMap, generatedPositionMapping);
|
|
379
|
+
// only debug level
|
|
380
|
+
Util.logTime(`decode source mappings ${distFile}`, time_start_decode);
|
|
381
|
+
|
|
382
|
+
// filter original list and init list
|
|
383
|
+
const fileSources = state.fileSources;
|
|
384
|
+
const originalMap = initOriginalList(sourceMap, originalIndexMap, fileSources, options);
|
|
385
|
+
|
|
386
|
+
originalIndexMap.clear();
|
|
387
|
+
|
|
388
|
+
const generatedState = {
|
|
389
|
+
decodedMappings: allDecodedMappings,
|
|
390
|
+
positionMapping: generatedPositionMapping
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
// const time_start_mapping = Date.now();
|
|
394
|
+
item.functions.forEach((block) => {
|
|
395
|
+
block.ranges.forEach((range, index) => {
|
|
396
|
+
|
|
397
|
+
const result = findOriginalRange(range, generatedState, originalMap);
|
|
398
|
+
if (!result) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const { originalRange, originalState } = result;
|
|
403
|
+
const { coverage, positionMapping } = originalState;
|
|
404
|
+
addCoverage(coverage, block, originalRange, index, positionMapping);
|
|
405
|
+
|
|
406
|
+
});
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
// collect original files
|
|
410
|
+
const sourceList = [];
|
|
411
|
+
originalMap.forEach((originalState) => {
|
|
412
|
+
const {
|
|
413
|
+
source, type, sourcePath, coverage
|
|
414
|
+
} = originalState;
|
|
415
|
+
|
|
416
|
+
// generate coverage
|
|
417
|
+
state.coverageData[sourcePath] = getFileCoverage(sourcePath, coverage);
|
|
418
|
+
const ranges = coverage.ranges;
|
|
419
|
+
|
|
420
|
+
// add file item
|
|
421
|
+
const url = fileUrls[sourcePath] || sourcePath;
|
|
422
|
+
const id = Util.calculateSha1(url + source);
|
|
423
|
+
|
|
424
|
+
const sourceItem = {
|
|
425
|
+
url,
|
|
426
|
+
id,
|
|
427
|
+
type,
|
|
428
|
+
sourcePath,
|
|
429
|
+
distFile,
|
|
430
|
+
ranges,
|
|
431
|
+
source
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
sourceList.push(sourceItem);
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
state.sourceList = sourceList;
|
|
438
|
+
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
// ========================================================================================================
|
|
442
|
+
|
|
443
|
+
const unpackDistFile = async (item, state, options) => {
|
|
444
|
+
|
|
445
|
+
if (item.sourceMap) {
|
|
446
|
+
if (Util.loggingType === 'debug') {
|
|
447
|
+
// js self
|
|
448
|
+
unpackDistSource(item, state, options);
|
|
449
|
+
} else {
|
|
450
|
+
item.dedupe = true;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// unpack source map
|
|
454
|
+
await unpackSourceMap(item, state, options);
|
|
455
|
+
|
|
456
|
+
// remove sourceMap
|
|
457
|
+
delete item.sourceMap;
|
|
458
|
+
|
|
459
|
+
} else {
|
|
460
|
+
|
|
461
|
+
// js self
|
|
462
|
+
unpackDistSource(item, state, options);
|
|
463
|
+
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// clean after all
|
|
467
|
+
delete item.functions;
|
|
468
|
+
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
// ========================================================================================================
|
|
472
|
+
|
|
473
|
+
const dedupeV8List = (v8list) => {
|
|
474
|
+
const indexes = [];
|
|
475
|
+
v8list.forEach((item, i) => {
|
|
476
|
+
if (item.dedupe) {
|
|
477
|
+
indexes.push(i);
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
if (indexes.length) {
|
|
481
|
+
indexes.reverse();
|
|
482
|
+
indexes.forEach((i) => {
|
|
483
|
+
v8list.splice(i, 1);
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
const convertV8List = async (v8list, options) => {
|
|
490
|
+
|
|
491
|
+
// TODO css to istanbul
|
|
492
|
+
const jsList = v8list.filter((it) => it.type === 'js');
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
// global file sources and coverage data
|
|
496
|
+
const fileSources = {};
|
|
497
|
+
const coverageData = {};
|
|
498
|
+
let sourceList = [];
|
|
499
|
+
|
|
500
|
+
for (const item of jsList) {
|
|
501
|
+
// console.log([item.id]);
|
|
502
|
+
|
|
503
|
+
const { source, sourcePath } = item;
|
|
504
|
+
|
|
505
|
+
const positionMapping = new PositionMapping(source);
|
|
506
|
+
|
|
507
|
+
// append file source
|
|
508
|
+
fileSources[sourcePath] = source;
|
|
509
|
+
|
|
510
|
+
// current file and it's sources from sourceMap
|
|
511
|
+
const state = {
|
|
512
|
+
fileSources: {},
|
|
513
|
+
coverageData: {},
|
|
514
|
+
positionMapping
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
await unpackDistFile(item, state, options);
|
|
518
|
+
|
|
519
|
+
// merge state
|
|
520
|
+
Object.assign(fileSources, state.fileSources);
|
|
521
|
+
Object.assign(coverageData, state.coverageData);
|
|
522
|
+
if (state.sourceList) {
|
|
523
|
+
sourceList = sourceList.concat(state.sourceList);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// dedupe
|
|
529
|
+
dedupeV8List(v8list);
|
|
530
|
+
|
|
531
|
+
// add all sources
|
|
532
|
+
if (sourceList.length) {
|
|
533
|
+
sourceList.forEach((item) => {
|
|
534
|
+
v8list.push(item);
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
return {
|
|
539
|
+
fileSources,
|
|
540
|
+
coverageData
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
module.exports = {
|
|
546
|
+
convertV8List
|
|
547
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const {
|
|
2
|
+
Worker, isMainThread, parentPort
|
|
3
|
+
} = require('worker_threads');
|
|
4
|
+
|
|
5
|
+
if (isMainThread) {
|
|
6
|
+
|
|
7
|
+
const decodeMappings = (mappings = '') => {
|
|
8
|
+
if (typeof text !== 'string') {
|
|
9
|
+
mappings = String(mappings);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return new Promise((resolve) => {
|
|
13
|
+
|
|
14
|
+
const worker = new Worker(__filename);
|
|
15
|
+
|
|
16
|
+
worker.on('message', (message) => {
|
|
17
|
+
if (message === 'workerReady') {
|
|
18
|
+
worker.postMessage(mappings);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
resolve(message);
|
|
22
|
+
worker.terminate();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
worker.on('error', (err) => {
|
|
26
|
+
resolve({
|
|
27
|
+
error: err
|
|
28
|
+
});
|
|
29
|
+
worker.terminate();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
module.exports = decodeMappings;
|
|
36
|
+
|
|
37
|
+
} else {
|
|
38
|
+
|
|
39
|
+
const { decode } = require('../../../runtime/monocart-coverage.js');
|
|
40
|
+
|
|
41
|
+
parentPort.on('message', (message) => {
|
|
42
|
+
const result = decode(message);
|
|
43
|
+
parentPort.postMessage(result);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
parentPort.postMessage('workerReady');
|
|
47
|
+
|
|
48
|
+
}
|
|
49
|
+
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
|
|
2
|
-
const
|
|
2
|
+
const sortRanges = (ranges) => {
|
|
3
|
+
ranges.sort((a, b) => {
|
|
4
|
+
if (a.start === b.start) {
|
|
5
|
+
return a.end - b.end;
|
|
6
|
+
}
|
|
7
|
+
return a.start - b.start;
|
|
8
|
+
});
|
|
9
|
+
};
|
|
3
10
|
|
|
4
11
|
const filterRanges = (ranges) => {
|
|
5
12
|
// remove start = end
|