monocart-coverage-reports 2.5.9 → 2.6.1
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/LICENSE +21 -21
- package/README.md +791 -778
- package/lib/cli.js +250 -215
- package/lib/converter/ast-visitor.js +675 -666
- package/lib/converter/ast.js +353 -353
- package/lib/converter/collect-source-maps.js +201 -201
- package/lib/converter/converter.js +1487 -1429
- package/lib/converter/find-original-range.js +737 -737
- package/lib/converter/ignore.js +163 -163
- package/lib/converter/info-branch.js +93 -93
- package/lib/converter/info-function.js +63 -63
- package/lib/converter/info-statement.js +43 -43
- package/lib/default/options.js +84 -84
- package/lib/default/template.html +47 -47
- package/lib/generate.js +720 -532
- package/lib/index.d.ts +360 -324
- package/lib/index.js +187 -180
- package/lib/index.mjs +5 -3
- package/lib/istanbul/istanbul-summary.js +70 -63
- package/lib/istanbul/istanbul.js +146 -146
- package/lib/packages/monocart-coverage-v8.js +1 -1
- package/lib/platform/concurrency.js +74 -74
- package/lib/platform/share.js +484 -484
- package/lib/utils/dedupe.js +118 -118
- package/lib/utils/request.js +62 -62
- package/lib/utils/snapshot.js +381 -0
- package/lib/utils/source-path.js +179 -179
- package/lib/utils/util.js +526 -526
- package/lib/v8/v8-summary.js +138 -138
- package/lib/v8/v8.js +400 -630
- package/package.json +81 -80
|
@@ -1,1429 +1,1487 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* V8 Coverage Data Converter
|
|
3
|
-
* @copyright https://github.com/cenfun/monocart-coverage-reports
|
|
4
|
-
* @author cenfun@gmail.com
|
|
5
|
-
*/
|
|
6
|
-
const Util = require('../utils/util.js');
|
|
7
|
-
|
|
8
|
-
// position mapping for conversion between offset and line/column
|
|
9
|
-
const { Locator } = require('monocart-formatter');
|
|
10
|
-
const findOriginalRange = require('./find-original-range.js');
|
|
11
|
-
const { getJsAstInfo, getCssAstInfo } = require('./ast.js');
|
|
12
|
-
const { getIgnoredRanges } = require('./ignore.js');
|
|
13
|
-
|
|
14
|
-
const {
|
|
15
|
-
sortRanges, dedupeCountRanges, mergeRangesWith
|
|
16
|
-
} = require('../utils/dedupe.js');
|
|
17
|
-
const {
|
|
18
|
-
getSourceType, getSourcePathHandler, initSourceMapSourcePath
|
|
19
|
-
} = require('../utils/source-path.js');
|
|
20
|
-
const { decode, minimatch } = require('../packages/monocart-coverage-vendor.js');
|
|
21
|
-
|
|
22
|
-
const InfoBranch = require('./info-branch.js');
|
|
23
|
-
const InfoFunction = require('./info-function.js');
|
|
24
|
-
const InfoStatement = require('./info-statement.js');
|
|
25
|
-
|
|
26
|
-
// ========================================================================================================
|
|
27
|
-
|
|
28
|
-
// debug info
|
|
29
|
-
const logMappingErrors = (type, result) => {
|
|
30
|
-
|
|
31
|
-
// const {
|
|
32
|
-
// errors, start, end, sourcePath
|
|
33
|
-
// } = result;
|
|
34
|
-
// // if (!sourcePath.endsWith('monocart-v8.js') || type !== 'byte') {
|
|
35
|
-
// // return;
|
|
36
|
-
// // }
|
|
37
|
-
// const list = [
|
|
38
|
-
// Util.EC.red('[Mapping]'),
|
|
39
|
-
// Util.EC.magenta(type),
|
|
40
|
-
// errors.join(' -> '),
|
|
41
|
-
// Util.EC.blue(`${start} ~ ${end}`),
|
|
42
|
-
// sourcePath
|
|
43
|
-
// ];
|
|
44
|
-
// console.log(list.join(' '));
|
|
45
|
-
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
// ========================================================================================================
|
|
49
|
-
|
|
50
|
-
const handleIgnoredRanges = (list, ignoredRanges) => {
|
|
51
|
-
list.forEach((item) => {
|
|
52
|
-
const range = Util.findInRanges(item.start, item.end, ignoredRanges, 'start', 'end');
|
|
53
|
-
if (range) {
|
|
54
|
-
// console.log(item, range);
|
|
55
|
-
item.ignored = true;
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const applyBytesToLines = (bytes, locator, lineMap) => {
|
|
62
|
-
bytes.forEach((range) => {
|
|
63
|
-
const {
|
|
64
|
-
start, end, count, ignored
|
|
65
|
-
} = range;
|
|
66
|
-
|
|
67
|
-
// no need handle ignored and uncovered byte
|
|
68
|
-
if (count === 0 && ignored) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const sLoc = locator.offsetToLocation(start);
|
|
73
|
-
const eLoc = locator.offsetToLocation(end);
|
|
74
|
-
|
|
75
|
-
// update lines coverage
|
|
76
|
-
const lines = Util.getRangeLines(sLoc, eLoc);
|
|
77
|
-
|
|
78
|
-
lines.forEach((it) => {
|
|
79
|
-
const lineItem = lineMap.get(it.line);
|
|
80
|
-
if (!lineItem) {
|
|
81
|
-
// not found line, could be comment or blank line
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
if (lineItem.ignored) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
it.count = count;
|
|
89
|
-
|
|
90
|
-
// default is covered, so only focus on
|
|
91
|
-
// 1, biggest covered count
|
|
92
|
-
// 2, uncovered entire and pieces
|
|
93
|
-
if (count > 0) {
|
|
94
|
-
lineItem.coveredCount = Math.max(lineItem.coveredCount, count);
|
|
95
|
-
} else {
|
|
96
|
-
if (it.entire) {
|
|
97
|
-
lineItem.uncoveredEntire = it;
|
|
98
|
-
} else {
|
|
99
|
-
lineItem.uncoveredPieces.push(it);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
// no ignore items
|
|
107
|
-
lineMap.forEach((lineItem, line) => {
|
|
108
|
-
|
|
109
|
-
const {
|
|
110
|
-
uncoveredEntire, uncoveredPieces, coveredCount
|
|
111
|
-
} = lineItem;
|
|
112
|
-
|
|
113
|
-
// default count to 1, both js and css
|
|
114
|
-
let count = 1;
|
|
115
|
-
// full covered true/false for entire line
|
|
116
|
-
let covered = true;
|
|
117
|
-
|
|
118
|
-
if (uncoveredEntire) {
|
|
119
|
-
count = 0;
|
|
120
|
-
covered = false;
|
|
121
|
-
} else {
|
|
122
|
-
count = coveredCount;
|
|
123
|
-
const uncoveredLen = uncoveredPieces.length;
|
|
124
|
-
if (uncoveredLen > 0) {
|
|
125
|
-
covered = false;
|
|
126
|
-
// uncovered
|
|
127
|
-
count = `1/${uncoveredLen + 1}`;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
lineItem.covered = covered;
|
|
132
|
-
lineItem.count = count;
|
|
133
|
-
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
const handleLinesCoverage = (bytes, locator, ignoredRanges) => {
|
|
139
|
-
|
|
140
|
-
// init lines
|
|
141
|
-
let blankCount = 0;
|
|
142
|
-
let commentCount = 0;
|
|
143
|
-
// line 1 based
|
|
144
|
-
const lineMap = new Map();
|
|
145
|
-
locator.lines.forEach((lineItem) => {
|
|
146
|
-
// exclude blank and comment
|
|
147
|
-
if (lineItem.blank) {
|
|
148
|
-
blankCount += 1;
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
if (lineItem.comment) {
|
|
152
|
-
commentCount += 1;
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
const ignored = Util.findInRanges(lineItem.start, lineItem.end, ignoredRanges);
|
|
156
|
-
if (ignored) {
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
// line 1-base
|
|
160
|
-
const line = lineItem.line + 1;
|
|
161
|
-
lineItem.coveredCount = 1;
|
|
162
|
-
lineItem.uncoveredEntire = null;
|
|
163
|
-
lineItem.uncoveredPieces = [];
|
|
164
|
-
lineMap.set(line, lineItem);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
applyBytesToLines(bytes, locator, lineMap);
|
|
168
|
-
|
|
169
|
-
const summaryLines = {
|
|
170
|
-
total: 0,
|
|
171
|
-
covered: 0,
|
|
172
|
-
blank: blankCount,
|
|
173
|
-
comment: commentCount
|
|
174
|
-
};
|
|
175
|
-
// data lines for codecov
|
|
176
|
-
// https://docs.codecov.com/docs/codecov-custom-coverage-format
|
|
177
|
-
const dataLines = {};
|
|
178
|
-
|
|
179
|
-
// no ignore items
|
|
180
|
-
lineMap.forEach((lineItem, line) => {
|
|
181
|
-
const { count, covered } = lineItem;
|
|
182
|
-
// data lines
|
|
183
|
-
dataLines[line] = count;
|
|
184
|
-
|
|
185
|
-
summaryLines.total += 1;
|
|
186
|
-
if (covered) {
|
|
187
|
-
summaryLines.covered += 1;
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
return {
|
|
192
|
-
dataLines,
|
|
193
|
-
summaryLines
|
|
194
|
-
};
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
// ========================================================================================================
|
|
198
|
-
|
|
199
|
-
const calculateV8Summary = (list) => {
|
|
200
|
-
|
|
201
|
-
const summary = {
|
|
202
|
-
total: 0,
|
|
203
|
-
covered: 0
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
list.forEach((item) => {
|
|
207
|
-
if (item.ignored) {
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
summary.total += 1;
|
|
212
|
-
if (item.count > 0) {
|
|
213
|
-
summary.covered += 1;
|
|
214
|
-
}
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
return summary;
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
// ========================================================================================================
|
|
221
|
-
// istanbul coverage format
|
|
222
|
-
// https://github.com/istanbuljs/istanbuljs/blob/master/docs/raw-output.md
|
|
223
|
-
/**
|
|
224
|
-
* * `path` - the file path for which coverage is being tracked
|
|
225
|
-
* * `statementMap` - map of statement locations keyed by statement index
|
|
226
|
-
* * `fnMap` - map of function metadata keyed by function index
|
|
227
|
-
* * `branchMap` - map of branch metadata keyed by branch index
|
|
228
|
-
* * `s` - hit counts for statements
|
|
229
|
-
* * `f` - hit count for functions
|
|
230
|
-
* * `b` - hit count for branches
|
|
231
|
-
*/
|
|
232
|
-
const collectFileCoverage = (v8Data, state, options) => {
|
|
233
|
-
|
|
234
|
-
const {
|
|
235
|
-
bytes,
|
|
236
|
-
functions,
|
|
237
|
-
branches,
|
|
238
|
-
statements,
|
|
239
|
-
|
|
240
|
-
sourcePath,
|
|
241
|
-
locator
|
|
242
|
-
} = state;
|
|
243
|
-
|
|
244
|
-
// ==========================================
|
|
245
|
-
// v8 data
|
|
246
|
-
const data = {
|
|
247
|
-
bytes: dedupeCountRanges(bytes),
|
|
248
|
-
functions: [],
|
|
249
|
-
branches: [],
|
|
250
|
-
statements: []
|
|
251
|
-
};
|
|
252
|
-
|
|
253
|
-
// ==========================================
|
|
254
|
-
// ignore
|
|
255
|
-
const ignoredRanges = getIgnoredRanges(locator, options);
|
|
256
|
-
if (ignoredRanges) {
|
|
257
|
-
|
|
258
|
-
data.ignores = ignoredRanges;
|
|
259
|
-
|
|
260
|
-
// data bytes is start/end/count object
|
|
261
|
-
handleIgnoredRanges(data.bytes, ignoredRanges);
|
|
262
|
-
|
|
263
|
-
// functions start/end/count instance
|
|
264
|
-
handleIgnoredRanges(functions, ignoredRanges);
|
|
265
|
-
|
|
266
|
-
// branches start/end/count instance
|
|
267
|
-
handleIgnoredRanges(branches, ignoredRanges);
|
|
268
|
-
|
|
269
|
-
// branch locations start/end/count object
|
|
270
|
-
branches.forEach((group) => {
|
|
271
|
-
if (group.ignored) {
|
|
272
|
-
// all branch group ignored
|
|
273
|
-
group.locations.forEach((it) => {
|
|
274
|
-
it.ignored = true;
|
|
275
|
-
});
|
|
276
|
-
} else {
|
|
277
|
-
handleIgnoredRanges(group.locations, ignoredRanges);
|
|
278
|
-
}
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
// statements start/end/count instance
|
|
282
|
-
handleIgnoredRanges(statements, ignoredRanges);
|
|
283
|
-
|
|
284
|
-
// console.log(ignoredRanges);
|
|
285
|
-
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// ==========================================
|
|
289
|
-
// lines
|
|
290
|
-
// after bytes with ignored, before calculateV8Lines
|
|
291
|
-
const { dataLines, summaryLines } = handleLinesCoverage(data.bytes, locator, ignoredRanges);
|
|
292
|
-
|
|
293
|
-
data.lines = dataLines;
|
|
294
|
-
|
|
295
|
-
// console.log('statements', state.sourcePath, statements.length);
|
|
296
|
-
|
|
297
|
-
// ==========================================
|
|
298
|
-
|
|
299
|
-
data.functions = functions.map((info) => {
|
|
300
|
-
return info.getRange();
|
|
301
|
-
});
|
|
302
|
-
sortRanges(data.functions);
|
|
303
|
-
|
|
304
|
-
// branch group with locations to flat branches
|
|
305
|
-
data.branches = branches.map((info) => {
|
|
306
|
-
return info.getRanges();
|
|
307
|
-
}).flat();
|
|
308
|
-
sortRanges(data.branches);
|
|
309
|
-
|
|
310
|
-
data.statements = statements.map((info) => {
|
|
311
|
-
return info.getRange();
|
|
312
|
-
});
|
|
313
|
-
sortRanges(data.statements);
|
|
314
|
-
|
|
315
|
-
// ==========================================
|
|
316
|
-
|
|
317
|
-
const summary = {
|
|
318
|
-
functions: calculateV8Summary(data.functions),
|
|
319
|
-
branches: calculateV8Summary(data.branches),
|
|
320
|
-
statements: calculateV8Summary(data.statements),
|
|
321
|
-
lines: summaryLines
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
// ==========================================
|
|
325
|
-
// v8 data and summary
|
|
326
|
-
v8Data.data = data;
|
|
327
|
-
v8Data.summary = summary;
|
|
328
|
-
|
|
329
|
-
// ==========================================
|
|
330
|
-
// istanbul
|
|
331
|
-
const istanbulData = {
|
|
332
|
-
path: sourcePath,
|
|
333
|
-
|
|
334
|
-
statementMap: {},
|
|
335
|
-
fnMap: {},
|
|
336
|
-
branchMap: {},
|
|
337
|
-
|
|
338
|
-
s: {},
|
|
339
|
-
f: {},
|
|
340
|
-
b: {}
|
|
341
|
-
};
|
|
342
|
-
|
|
343
|
-
statements.filter((it) => !it.ignored).forEach((statement, index) => {
|
|
344
|
-
istanbulData.statementMap[`${index}`] = statement.generate(locator);
|
|
345
|
-
istanbulData.s[`${index}`] = statement.count;
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
functions.filter((it) => !it.ignored).forEach((fn, index) => {
|
|
349
|
-
istanbulData.fnMap[`${index}`] = fn.generate(locator, index);
|
|
350
|
-
istanbulData.f[`${index}`] = fn.count;
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
branches.filter((it) => !it.ignored).forEach((branch, index) => {
|
|
354
|
-
const { map, counts } = branch.generate(locator);
|
|
355
|
-
istanbulData.branchMap[`${index}`] = map;
|
|
356
|
-
istanbulData.b[`${index}`] = counts;
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
return istanbulData;
|
|
360
|
-
|
|
361
|
-
};
|
|
362
|
-
|
|
363
|
-
// ========================================================================================================
|
|
364
|
-
|
|
365
|
-
const addJsBytesCoverage = (state, range) => {
|
|
366
|
-
const {
|
|
367
|
-
startOffset, endOffset, count
|
|
368
|
-
} = range;
|
|
369
|
-
// add bytes range
|
|
370
|
-
const byte = {
|
|
371
|
-
start: startOffset,
|
|
372
|
-
end: endOffset,
|
|
373
|
-
count
|
|
374
|
-
};
|
|
375
|
-
// for debug
|
|
376
|
-
if (Util.isDebug() && state.original) {
|
|
377
|
-
byte.generatedStart = range.generatedStart;
|
|
378
|
-
byte.generatedEnd = range.generatedEnd;
|
|
379
|
-
}
|
|
380
|
-
state.bytes.push(byte);
|
|
381
|
-
};
|
|
382
|
-
|
|
383
|
-
const addCssBytesCoverage = (state, range) => {
|
|
384
|
-
const {
|
|
385
|
-
start, end, count
|
|
386
|
-
} = range;
|
|
387
|
-
// add css bytes range, already start, end
|
|
388
|
-
state.bytes.push({
|
|
389
|
-
start,
|
|
390
|
-
end,
|
|
391
|
-
count
|
|
392
|
-
});
|
|
393
|
-
};
|
|
394
|
-
|
|
395
|
-
// ========================================================================================================
|
|
396
|
-
|
|
397
|
-
const
|
|
398
|
-
|
|
399
|
-
//
|
|
400
|
-
if (!state.
|
|
401
|
-
return;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
const {
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
return;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
};
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
const
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
const
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
//
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
//
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
const
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
//
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
};
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
//
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
if (
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
};
|
|
1143
|
-
|
|
1144
|
-
// ========================================================================================================
|
|
1145
|
-
|
|
1146
|
-
const
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
}
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
const
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
//
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
state.
|
|
1261
|
-
|
|
1262
|
-
//
|
|
1263
|
-
//
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
}
|
|
1316
|
-
}
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
//
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
if (js) {
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1
|
+
/**
|
|
2
|
+
* V8 Coverage Data Converter
|
|
3
|
+
* @copyright https://github.com/cenfun/monocart-coverage-reports
|
|
4
|
+
* @author cenfun@gmail.com
|
|
5
|
+
*/
|
|
6
|
+
const Util = require('../utils/util.js');
|
|
7
|
+
|
|
8
|
+
// position mapping for conversion between offset and line/column
|
|
9
|
+
const { Locator } = require('monocart-formatter');
|
|
10
|
+
const findOriginalRange = require('./find-original-range.js');
|
|
11
|
+
const { getJsAstInfo, getCssAstInfo } = require('./ast.js');
|
|
12
|
+
const { getIgnoredRanges } = require('./ignore.js');
|
|
13
|
+
|
|
14
|
+
const {
|
|
15
|
+
sortRanges, dedupeCountRanges, mergeRangesWith
|
|
16
|
+
} = require('../utils/dedupe.js');
|
|
17
|
+
const {
|
|
18
|
+
getSourceType, getSourcePathHandler, initSourceMapSourcePath
|
|
19
|
+
} = require('../utils/source-path.js');
|
|
20
|
+
const { decode, minimatch } = require('../packages/monocart-coverage-vendor.js');
|
|
21
|
+
|
|
22
|
+
const InfoBranch = require('./info-branch.js');
|
|
23
|
+
const InfoFunction = require('./info-function.js');
|
|
24
|
+
const InfoStatement = require('./info-statement.js');
|
|
25
|
+
|
|
26
|
+
// ========================================================================================================
|
|
27
|
+
|
|
28
|
+
// debug info
|
|
29
|
+
const logMappingErrors = (type, result) => {
|
|
30
|
+
|
|
31
|
+
// const {
|
|
32
|
+
// errors, start, end, sourcePath
|
|
33
|
+
// } = result;
|
|
34
|
+
// // if (!sourcePath.endsWith('monocart-v8.js') || type !== 'byte') {
|
|
35
|
+
// // return;
|
|
36
|
+
// // }
|
|
37
|
+
// const list = [
|
|
38
|
+
// Util.EC.red('[Mapping]'),
|
|
39
|
+
// Util.EC.magenta(type),
|
|
40
|
+
// errors.join(' -> '),
|
|
41
|
+
// Util.EC.blue(`${start} ~ ${end}`),
|
|
42
|
+
// sourcePath
|
|
43
|
+
// ];
|
|
44
|
+
// console.log(list.join(' '));
|
|
45
|
+
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// ========================================================================================================
|
|
49
|
+
|
|
50
|
+
const handleIgnoredRanges = (list, ignoredRanges) => {
|
|
51
|
+
list.forEach((item) => {
|
|
52
|
+
const range = Util.findInRanges(item.start, item.end, ignoredRanges, 'start', 'end');
|
|
53
|
+
if (range) {
|
|
54
|
+
// console.log(item, range);
|
|
55
|
+
item.ignored = true;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
const applyBytesToLines = (bytes, locator, lineMap) => {
|
|
62
|
+
bytes.forEach((range) => {
|
|
63
|
+
const {
|
|
64
|
+
start, end, count, ignored
|
|
65
|
+
} = range;
|
|
66
|
+
|
|
67
|
+
// no need handle ignored and uncovered byte
|
|
68
|
+
if (count === 0 && ignored) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const sLoc = locator.offsetToLocation(start);
|
|
73
|
+
const eLoc = locator.offsetToLocation(end);
|
|
74
|
+
|
|
75
|
+
// update lines coverage
|
|
76
|
+
const lines = Util.getRangeLines(sLoc, eLoc);
|
|
77
|
+
|
|
78
|
+
lines.forEach((it) => {
|
|
79
|
+
const lineItem = lineMap.get(it.line);
|
|
80
|
+
if (!lineItem) {
|
|
81
|
+
// not found line, could be comment or blank line
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (lineItem.ignored) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
it.count = count;
|
|
89
|
+
|
|
90
|
+
// default is covered, so only focus on
|
|
91
|
+
// 1, biggest covered count
|
|
92
|
+
// 2, uncovered entire and pieces
|
|
93
|
+
if (count > 0) {
|
|
94
|
+
lineItem.coveredCount = Math.max(lineItem.coveredCount, count);
|
|
95
|
+
} else {
|
|
96
|
+
if (it.entire) {
|
|
97
|
+
lineItem.uncoveredEntire = it;
|
|
98
|
+
} else {
|
|
99
|
+
lineItem.uncoveredPieces.push(it);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// no ignore items
|
|
107
|
+
lineMap.forEach((lineItem, line) => {
|
|
108
|
+
|
|
109
|
+
const {
|
|
110
|
+
uncoveredEntire, uncoveredPieces, coveredCount
|
|
111
|
+
} = lineItem;
|
|
112
|
+
|
|
113
|
+
// default count to 1, both js and css
|
|
114
|
+
let count = 1;
|
|
115
|
+
// full covered true/false for entire line
|
|
116
|
+
let covered = true;
|
|
117
|
+
|
|
118
|
+
if (uncoveredEntire) {
|
|
119
|
+
count = 0;
|
|
120
|
+
covered = false;
|
|
121
|
+
} else {
|
|
122
|
+
count = coveredCount;
|
|
123
|
+
const uncoveredLen = uncoveredPieces.length;
|
|
124
|
+
if (uncoveredLen > 0) {
|
|
125
|
+
covered = false;
|
|
126
|
+
// uncovered
|
|
127
|
+
count = `1/${uncoveredLen + 1}`;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
lineItem.covered = covered;
|
|
132
|
+
lineItem.count = count;
|
|
133
|
+
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const handleLinesCoverage = (bytes, locator, ignoredRanges) => {
|
|
139
|
+
|
|
140
|
+
// init lines
|
|
141
|
+
let blankCount = 0;
|
|
142
|
+
let commentCount = 0;
|
|
143
|
+
// line 1 based
|
|
144
|
+
const lineMap = new Map();
|
|
145
|
+
locator.lines.forEach((lineItem) => {
|
|
146
|
+
// exclude blank and comment
|
|
147
|
+
if (lineItem.blank) {
|
|
148
|
+
blankCount += 1;
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (lineItem.comment) {
|
|
152
|
+
commentCount += 1;
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const ignored = Util.findInRanges(lineItem.start, lineItem.end, ignoredRanges);
|
|
156
|
+
if (ignored) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
// line 1-base
|
|
160
|
+
const line = lineItem.line + 1;
|
|
161
|
+
lineItem.coveredCount = 1;
|
|
162
|
+
lineItem.uncoveredEntire = null;
|
|
163
|
+
lineItem.uncoveredPieces = [];
|
|
164
|
+
lineMap.set(line, lineItem);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
applyBytesToLines(bytes, locator, lineMap);
|
|
168
|
+
|
|
169
|
+
const summaryLines = {
|
|
170
|
+
total: 0,
|
|
171
|
+
covered: 0,
|
|
172
|
+
blank: blankCount,
|
|
173
|
+
comment: commentCount
|
|
174
|
+
};
|
|
175
|
+
// data lines for codecov
|
|
176
|
+
// https://docs.codecov.com/docs/codecov-custom-coverage-format
|
|
177
|
+
const dataLines = {};
|
|
178
|
+
|
|
179
|
+
// no ignore items
|
|
180
|
+
lineMap.forEach((lineItem, line) => {
|
|
181
|
+
const { count, covered } = lineItem;
|
|
182
|
+
// data lines
|
|
183
|
+
dataLines[line] = count;
|
|
184
|
+
|
|
185
|
+
summaryLines.total += 1;
|
|
186
|
+
if (covered) {
|
|
187
|
+
summaryLines.covered += 1;
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
dataLines,
|
|
193
|
+
summaryLines
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
// ========================================================================================================
|
|
198
|
+
|
|
199
|
+
const calculateV8Summary = (list) => {
|
|
200
|
+
|
|
201
|
+
const summary = {
|
|
202
|
+
total: 0,
|
|
203
|
+
covered: 0
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
list.forEach((item) => {
|
|
207
|
+
if (item.ignored) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
summary.total += 1;
|
|
212
|
+
if (item.count > 0) {
|
|
213
|
+
summary.covered += 1;
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
return summary;
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
// ========================================================================================================
|
|
221
|
+
// istanbul coverage format
|
|
222
|
+
// https://github.com/istanbuljs/istanbuljs/blob/master/docs/raw-output.md
|
|
223
|
+
/**
|
|
224
|
+
* * `path` - the file path for which coverage is being tracked
|
|
225
|
+
* * `statementMap` - map of statement locations keyed by statement index
|
|
226
|
+
* * `fnMap` - map of function metadata keyed by function index
|
|
227
|
+
* * `branchMap` - map of branch metadata keyed by branch index
|
|
228
|
+
* * `s` - hit counts for statements
|
|
229
|
+
* * `f` - hit count for functions
|
|
230
|
+
* * `b` - hit count for branches
|
|
231
|
+
*/
|
|
232
|
+
const collectFileCoverage = (v8Data, state, options) => {
|
|
233
|
+
|
|
234
|
+
const {
|
|
235
|
+
bytes,
|
|
236
|
+
functions,
|
|
237
|
+
branches,
|
|
238
|
+
statements,
|
|
239
|
+
|
|
240
|
+
sourcePath,
|
|
241
|
+
locator
|
|
242
|
+
} = state;
|
|
243
|
+
|
|
244
|
+
// ==========================================
|
|
245
|
+
// v8 data
|
|
246
|
+
const data = {
|
|
247
|
+
bytes: dedupeCountRanges(bytes),
|
|
248
|
+
functions: [],
|
|
249
|
+
branches: [],
|
|
250
|
+
statements: []
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
// ==========================================
|
|
254
|
+
// ignore
|
|
255
|
+
const ignoredRanges = getIgnoredRanges(locator, options);
|
|
256
|
+
if (ignoredRanges) {
|
|
257
|
+
|
|
258
|
+
data.ignores = ignoredRanges;
|
|
259
|
+
|
|
260
|
+
// data bytes is start/end/count object
|
|
261
|
+
handleIgnoredRanges(data.bytes, ignoredRanges);
|
|
262
|
+
|
|
263
|
+
// functions start/end/count instance
|
|
264
|
+
handleIgnoredRanges(functions, ignoredRanges);
|
|
265
|
+
|
|
266
|
+
// branches start/end/count instance
|
|
267
|
+
handleIgnoredRanges(branches, ignoredRanges);
|
|
268
|
+
|
|
269
|
+
// branch locations start/end/count object
|
|
270
|
+
branches.forEach((group) => {
|
|
271
|
+
if (group.ignored) {
|
|
272
|
+
// all branch group ignored
|
|
273
|
+
group.locations.forEach((it) => {
|
|
274
|
+
it.ignored = true;
|
|
275
|
+
});
|
|
276
|
+
} else {
|
|
277
|
+
handleIgnoredRanges(group.locations, ignoredRanges);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// statements start/end/count instance
|
|
282
|
+
handleIgnoredRanges(statements, ignoredRanges);
|
|
283
|
+
|
|
284
|
+
// console.log(ignoredRanges);
|
|
285
|
+
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// ==========================================
|
|
289
|
+
// lines
|
|
290
|
+
// after bytes with ignored, before calculateV8Lines
|
|
291
|
+
const { dataLines, summaryLines } = handleLinesCoverage(data.bytes, locator, ignoredRanges);
|
|
292
|
+
|
|
293
|
+
data.lines = dataLines;
|
|
294
|
+
|
|
295
|
+
// console.log('statements', state.sourcePath, statements.length);
|
|
296
|
+
|
|
297
|
+
// ==========================================
|
|
298
|
+
|
|
299
|
+
data.functions = functions.map((info) => {
|
|
300
|
+
return info.getRange();
|
|
301
|
+
});
|
|
302
|
+
sortRanges(data.functions);
|
|
303
|
+
|
|
304
|
+
// branch group with locations to flat branches
|
|
305
|
+
data.branches = branches.map((info) => {
|
|
306
|
+
return info.getRanges();
|
|
307
|
+
}).flat();
|
|
308
|
+
sortRanges(data.branches);
|
|
309
|
+
|
|
310
|
+
data.statements = statements.map((info) => {
|
|
311
|
+
return info.getRange();
|
|
312
|
+
});
|
|
313
|
+
sortRanges(data.statements);
|
|
314
|
+
|
|
315
|
+
// ==========================================
|
|
316
|
+
|
|
317
|
+
const summary = {
|
|
318
|
+
functions: calculateV8Summary(data.functions),
|
|
319
|
+
branches: calculateV8Summary(data.branches),
|
|
320
|
+
statements: calculateV8Summary(data.statements),
|
|
321
|
+
lines: summaryLines
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
// ==========================================
|
|
325
|
+
// v8 data and summary
|
|
326
|
+
v8Data.data = data;
|
|
327
|
+
v8Data.summary = summary;
|
|
328
|
+
|
|
329
|
+
// ==========================================
|
|
330
|
+
// istanbul
|
|
331
|
+
const istanbulData = {
|
|
332
|
+
path: sourcePath,
|
|
333
|
+
|
|
334
|
+
statementMap: {},
|
|
335
|
+
fnMap: {},
|
|
336
|
+
branchMap: {},
|
|
337
|
+
|
|
338
|
+
s: {},
|
|
339
|
+
f: {},
|
|
340
|
+
b: {}
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
statements.filter((it) => !it.ignored).forEach((statement, index) => {
|
|
344
|
+
istanbulData.statementMap[`${index}`] = statement.generate(locator);
|
|
345
|
+
istanbulData.s[`${index}`] = statement.count;
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
functions.filter((it) => !it.ignored).forEach((fn, index) => {
|
|
349
|
+
istanbulData.fnMap[`${index}`] = fn.generate(locator, index);
|
|
350
|
+
istanbulData.f[`${index}`] = fn.count;
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
branches.filter((it) => !it.ignored).forEach((branch, index) => {
|
|
354
|
+
const { map, counts } = branch.generate(locator);
|
|
355
|
+
istanbulData.branchMap[`${index}`] = map;
|
|
356
|
+
istanbulData.b[`${index}`] = counts;
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
return istanbulData;
|
|
360
|
+
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
// ========================================================================================================
|
|
364
|
+
|
|
365
|
+
const addJsBytesCoverage = (state, range) => {
|
|
366
|
+
const {
|
|
367
|
+
startOffset, endOffset, count
|
|
368
|
+
} = range;
|
|
369
|
+
// add bytes range
|
|
370
|
+
const byte = {
|
|
371
|
+
start: startOffset,
|
|
372
|
+
end: endOffset,
|
|
373
|
+
count
|
|
374
|
+
};
|
|
375
|
+
// for debug
|
|
376
|
+
if (Util.isDebug() && state.original) {
|
|
377
|
+
byte.generatedStart = range.generatedStart;
|
|
378
|
+
byte.generatedEnd = range.generatedEnd;
|
|
379
|
+
}
|
|
380
|
+
state.bytes.push(byte);
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
const addCssBytesCoverage = (state, range) => {
|
|
384
|
+
const {
|
|
385
|
+
start, end, count
|
|
386
|
+
} = range;
|
|
387
|
+
// add css bytes range, already start, end
|
|
388
|
+
state.bytes.push({
|
|
389
|
+
start,
|
|
390
|
+
end,
|
|
391
|
+
count
|
|
392
|
+
});
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
// ========================================================================================================
|
|
396
|
+
|
|
397
|
+
const checkOriginalRangeCode = (range, state, startEndMap, type) => {
|
|
398
|
+
|
|
399
|
+
// only for original
|
|
400
|
+
if (!state.original) {
|
|
401
|
+
return true;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
const { start, end } = range;
|
|
405
|
+
if (start >= end) {
|
|
406
|
+
// console.log('invalid branch', state.sourcePath, range);
|
|
407
|
+
return false;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// could be vue code
|
|
411
|
+
const text = state.locator.getSlice(start, end).trim();
|
|
412
|
+
if (!text) {
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// invalid original code
|
|
417
|
+
// Matches any character that is not a word character from the basic Latin alphabet.
|
|
418
|
+
// Equivalent to [^A-Za-z0-9_]
|
|
419
|
+
if (text.length === 1 && (/\W/).test(text)) {
|
|
420
|
+
// ; } =
|
|
421
|
+
// console.log(text, type, state.sourcePath, range);
|
|
422
|
+
return false;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// type: bytes, functions, branches, statements
|
|
426
|
+
|
|
427
|
+
// do not check repeated range for `bytes`
|
|
428
|
+
// instead, use `dedupeCountRanges` to accumulate count
|
|
429
|
+
if (type === 'bytes') {
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// check repeated range
|
|
434
|
+
const key = `${start}_${end}`;
|
|
435
|
+
if (startEndMap.has(key)) {
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
438
|
+
startEndMap.set(key, range);
|
|
439
|
+
|
|
440
|
+
return true;
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
const handleFunctionsCoverage = (state) => {
|
|
444
|
+
|
|
445
|
+
// functions only for js
|
|
446
|
+
if (!state.js) {
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const startEndMap = new Map();
|
|
451
|
+
const { functions, astInfo } = state;
|
|
452
|
+
astInfo.functions.forEach((it) => {
|
|
453
|
+
|
|
454
|
+
if (!checkOriginalRangeCode(it, state, startEndMap, 'functions')) {
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
functions.push(new InfoFunction(it, state.original));
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
const handleBranchesCoverage = (state) => {
|
|
464
|
+
|
|
465
|
+
// functions only for js
|
|
466
|
+
if (!state.js) {
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const startEndMap = new Map();
|
|
471
|
+
const { branches, astInfo } = state;
|
|
472
|
+
astInfo.branches.forEach((it) => {
|
|
473
|
+
|
|
474
|
+
if (!checkOriginalRangeCode(it, state, startEndMap, 'branches')) {
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
branches.push(new InfoBranch(it, state.original));
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
const handleStatementsCoverage = (state) => {
|
|
484
|
+
|
|
485
|
+
// statement only for js
|
|
486
|
+
if (!state.js) {
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
const startEndMap = new Map();
|
|
491
|
+
const { statements, astInfo } = state;
|
|
492
|
+
astInfo.statements.forEach((it) => {
|
|
493
|
+
|
|
494
|
+
if (!checkOriginalRangeCode(it, state, startEndMap, 'statements')) {
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
statements.push(new InfoStatement(it, state.original));
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
const handleOriginalBytesCoverage = (state) => {
|
|
504
|
+
const startEndMap = new Map();
|
|
505
|
+
state.bytes = state.bytes.filter((it) => {
|
|
506
|
+
return checkOriginalRangeCode(it, state, startEndMap, 'bytes');
|
|
507
|
+
});
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
const handleGeneratedBytesCoverage = (state) => {
|
|
511
|
+
|
|
512
|
+
const { js, coverageList } = state;
|
|
513
|
+
|
|
514
|
+
if (js) {
|
|
515
|
+
coverageList.forEach((block) => {
|
|
516
|
+
block.ranges.forEach((range) => {
|
|
517
|
+
addJsBytesCoverage(state, range);
|
|
518
|
+
});
|
|
519
|
+
});
|
|
520
|
+
} else {
|
|
521
|
+
coverageList.forEach((range) => {
|
|
522
|
+
addCssBytesCoverage(state, range);
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
// ========================================================================================================
|
|
529
|
+
|
|
530
|
+
const handleOriginalFunctionsCoverage = (state, originalStateMap) => {
|
|
531
|
+
|
|
532
|
+
// functions only for js
|
|
533
|
+
if (!state.js) {
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// console.log(state.astInfo.functions);
|
|
538
|
+
|
|
539
|
+
const updateFunctionBodyRange = (start, end, bodyStart, bodyEnd, originalFunction) => {
|
|
540
|
+
if (bodyStart !== start || bodyEnd !== end) {
|
|
541
|
+
const result = findOriginalRange(bodyStart, bodyEnd, state, originalStateMap);
|
|
542
|
+
if (result.error) {
|
|
543
|
+
logMappingErrors('function body', result);
|
|
544
|
+
} else {
|
|
545
|
+
originalFunction.bodyStart = result.start;
|
|
546
|
+
originalFunction.bodyEnd = result.end;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
// function count
|
|
552
|
+
state.astInfo.functions.forEach((it) => {
|
|
553
|
+
const {
|
|
554
|
+
start, end, bodyStart, bodyEnd, wrap
|
|
555
|
+
} = it;
|
|
556
|
+
|
|
557
|
+
// remove webpack wrap functions for functions count, not for ranges here
|
|
558
|
+
if (wrap) {
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
const result = findOriginalRange(start, end, state, originalStateMap);
|
|
563
|
+
if (result.error) {
|
|
564
|
+
logMappingErrors('function', result);
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
const originalFunction = {
|
|
569
|
+
... it,
|
|
570
|
+
generatedStart: start,
|
|
571
|
+
generatedEnd: end,
|
|
572
|
+
start: result.start,
|
|
573
|
+
end: result.end,
|
|
574
|
+
bodyStart: result.start,
|
|
575
|
+
bodyEnd: result.end
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
// body start and end
|
|
579
|
+
updateFunctionBodyRange(start, end, bodyStart, bodyEnd, originalFunction);
|
|
580
|
+
|
|
581
|
+
// add back to original ast
|
|
582
|
+
result.originalState.astInfo.functions.push(originalFunction);
|
|
583
|
+
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
const handleOriginalBranchesCoverage = (state, originalStateMap) => {
|
|
589
|
+
|
|
590
|
+
// branches only for js
|
|
591
|
+
if (!state.js) {
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// console.log(state.astInfo.branches);
|
|
596
|
+
|
|
597
|
+
// function count
|
|
598
|
+
state.astInfo.branches.forEach((group) => {
|
|
599
|
+
|
|
600
|
+
const { type, locations } = group;
|
|
601
|
+
|
|
602
|
+
// start
|
|
603
|
+
const result = findOriginalRange(group.start, group.end, state, originalStateMap);
|
|
604
|
+
if (result.error) {
|
|
605
|
+
logMappingErrors('branch group', result);
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// new group start and end
|
|
610
|
+
const groupStart = result.start;
|
|
611
|
+
const groupEnd = result.end;
|
|
612
|
+
|
|
613
|
+
let hasError;
|
|
614
|
+
const newLocations = locations.map((oLoc) => {
|
|
615
|
+
|
|
616
|
+
const newLoc = {
|
|
617
|
+
... oLoc
|
|
618
|
+
};
|
|
619
|
+
|
|
620
|
+
if (newLoc.none) {
|
|
621
|
+
newLoc.start = groupStart;
|
|
622
|
+
newLoc.end = groupEnd;
|
|
623
|
+
return newLoc;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
const locResult = findOriginalRange(newLoc.start, newLoc.end, state, originalStateMap);
|
|
627
|
+
if (locResult.error) {
|
|
628
|
+
// It should not happen unless it is minify files, the SourceMap has some order problems
|
|
629
|
+
logMappingErrors('branch', locResult);
|
|
630
|
+
hasError = true;
|
|
631
|
+
return newLoc;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// before new range
|
|
635
|
+
newLoc.generatedStart = newLoc.start;
|
|
636
|
+
newLoc.generatedEnd = newLoc.end;
|
|
637
|
+
// mapping to new range
|
|
638
|
+
newLoc.start = locResult.start;
|
|
639
|
+
newLoc.end = locResult.end;
|
|
640
|
+
|
|
641
|
+
return newLoc;
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
// ignored group when found error
|
|
645
|
+
if (hasError) {
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// add back to original ast
|
|
650
|
+
result.originalState.astInfo.branches.push({
|
|
651
|
+
type,
|
|
652
|
+
start: groupStart,
|
|
653
|
+
end: groupEnd,
|
|
654
|
+
locations: newLocations
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
const handleOriginalStatementsCoverage = (state, originalStateMap) => {
|
|
662
|
+
|
|
663
|
+
// statements only for js
|
|
664
|
+
if (!state.js) {
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// statement count
|
|
669
|
+
state.astInfo.statements.forEach((it) => {
|
|
670
|
+
const { start, end } = it;
|
|
671
|
+
|
|
672
|
+
const result = findOriginalRange(start, end, state, originalStateMap);
|
|
673
|
+
if (result.error) {
|
|
674
|
+
logMappingErrors('statement', result);
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// add back to original ast
|
|
679
|
+
result.originalState.astInfo.statements.push({
|
|
680
|
+
... it,
|
|
681
|
+
generatedStart: start,
|
|
682
|
+
generatedEnd: end,
|
|
683
|
+
start: result.start,
|
|
684
|
+
end: result.end
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
originalStateMap.forEach((originalState) => {
|
|
690
|
+
const statements = originalState.astInfo.statements;
|
|
691
|
+
if (Util.isList(statements)) {
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
// fake source nothing matched
|
|
695
|
+
statements.push({
|
|
696
|
+
start: 0,
|
|
697
|
+
end: originalState.source.length,
|
|
698
|
+
count: 1
|
|
699
|
+
});
|
|
700
|
+
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
};
|
|
704
|
+
|
|
705
|
+
// ========================================================================================================
|
|
706
|
+
|
|
707
|
+
const handleOriginalEmptyBytesCoverage = (state, originalStateMap) => {
|
|
708
|
+
const checkList = [];
|
|
709
|
+
|
|
710
|
+
// check original bytes if fully in a wrapper range
|
|
711
|
+
originalStateMap.forEach((originalState) => {
|
|
712
|
+
const bytes = originalState.bytes;
|
|
713
|
+
if (Util.isList(bytes)) {
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
const { decodedMappings } = originalState;
|
|
718
|
+
const len = decodedMappings.length;
|
|
719
|
+
if (len < 2) {
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
// sort by original line/column
|
|
723
|
+
const startMapping = decodedMappings[0];
|
|
724
|
+
const endMapping = decodedMappings[len - 1];
|
|
725
|
+
// console.log(startMapping, endMapping);
|
|
726
|
+
const startOffset = startMapping.generatedOffset;
|
|
727
|
+
|
|
728
|
+
if (!endMapping.generatedEndOffset) {
|
|
729
|
+
// line last one
|
|
730
|
+
const line = state.locator.getLine(endMapping.generatedLine + 1);
|
|
731
|
+
// could be no line found
|
|
732
|
+
if (line) {
|
|
733
|
+
// last column
|
|
734
|
+
endMapping.generatedEndOffset = line.end;
|
|
735
|
+
} else {
|
|
736
|
+
endMapping.generatedEndOffset = endMapping.generatedOffset;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
const endOffset = endMapping.generatedEndOffset;
|
|
740
|
+
|
|
741
|
+
// console.log('===========================================================', originalState.sourcePath);
|
|
742
|
+
// console.log(originalState.source.length, endMapping);
|
|
743
|
+
|
|
744
|
+
checkList.push({
|
|
745
|
+
originalState,
|
|
746
|
+
startOffset,
|
|
747
|
+
endOffset
|
|
748
|
+
});
|
|
749
|
+
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
// no file to handle
|
|
753
|
+
if (!checkList.length) {
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// there is no state.bytes if not in debug
|
|
758
|
+
// should using coverageList to generate bytes first
|
|
759
|
+
handleGeneratedBytesCoverage(state);
|
|
760
|
+
|
|
761
|
+
checkList.forEach((it) => {
|
|
762
|
+
|
|
763
|
+
const {
|
|
764
|
+
originalState, startOffset, endOffset
|
|
765
|
+
} = it;
|
|
766
|
+
|
|
767
|
+
// console.log('=============', 'no bytes', originalState.sourcePath);
|
|
768
|
+
|
|
769
|
+
// only check uncovered range
|
|
770
|
+
// because a uncovered range could be in a covered wrapper
|
|
771
|
+
// { start: 0, end: 12137, count: 1 }, could be { start: > 0, end: < 12137, count: 0 }
|
|
772
|
+
for (const range of state.bytes) {
|
|
773
|
+
if (range.count > 0) {
|
|
774
|
+
continue;
|
|
775
|
+
}
|
|
776
|
+
if (startOffset >= range.start && endOffset <= range.end) {
|
|
777
|
+
// console.log('------------', 'added');
|
|
778
|
+
originalState.bytes.push({
|
|
779
|
+
start: 0,
|
|
780
|
+
end: originalState.source.length,
|
|
781
|
+
count: 0
|
|
782
|
+
});
|
|
783
|
+
break;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
});
|
|
788
|
+
};
|
|
789
|
+
|
|
790
|
+
const handleAllOriginalBytesCoverage = (state, originalStateMap) => {
|
|
791
|
+
|
|
792
|
+
const { js, coverageList } = state;
|
|
793
|
+
|
|
794
|
+
// only for js, no sourcemap for css for now
|
|
795
|
+
if (!js) {
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
// v8 coverage
|
|
800
|
+
coverageList.forEach((block) => {
|
|
801
|
+
block.ranges.forEach((range, index) => {
|
|
802
|
+
|
|
803
|
+
// remove wrap functions for original files
|
|
804
|
+
if (range.wrap) {
|
|
805
|
+
// console.log(range);
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
const {
|
|
810
|
+
startOffset, endOffset, count
|
|
811
|
+
} = range;
|
|
812
|
+
|
|
813
|
+
const result = findOriginalRange(startOffset, endOffset, state, originalStateMap);
|
|
814
|
+
if (result.error) {
|
|
815
|
+
logMappingErrors('byte', result);
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
addJsBytesCoverage(result.originalState, {
|
|
820
|
+
generatedStart: startOffset,
|
|
821
|
+
generatedEnd: endOffset,
|
|
822
|
+
startOffset: result.start,
|
|
823
|
+
endOffset: result.end,
|
|
824
|
+
count
|
|
825
|
+
});
|
|
826
|
+
|
|
827
|
+
});
|
|
828
|
+
});
|
|
829
|
+
|
|
830
|
+
handleOriginalEmptyBytesCoverage(state, originalStateMap);
|
|
831
|
+
|
|
832
|
+
};
|
|
833
|
+
|
|
834
|
+
// ========================================================================================================
|
|
835
|
+
|
|
836
|
+
const decodeSourceMappings = (state, originalDecodedMap) => {
|
|
837
|
+
|
|
838
|
+
const generatedLocator = state.locator;
|
|
839
|
+
|
|
840
|
+
const { sources, mappings } = state.sourceMap;
|
|
841
|
+
|
|
842
|
+
const decodedList = decode(mappings);
|
|
843
|
+
|
|
844
|
+
sources.forEach((source, i) => {
|
|
845
|
+
originalDecodedMap.set(i, []);
|
|
846
|
+
});
|
|
847
|
+
|
|
848
|
+
const allDecodedMappings = [];
|
|
849
|
+
decodedList.forEach((segments, generatedLine) => {
|
|
850
|
+
let info = null;
|
|
851
|
+
segments.forEach((segment) => {
|
|
852
|
+
|
|
853
|
+
// const COLUMN = 0;
|
|
854
|
+
// const SOURCES_INDEX = 1;
|
|
855
|
+
// const SOURCE_LINE = 2;
|
|
856
|
+
// const SOURCE_COLUMN = 3;
|
|
857
|
+
// const NAMES_INDEX = 4;
|
|
858
|
+
const [generatedColumn, sourceIndex, originalLine, originalColumn] = segment;
|
|
859
|
+
// the segment length could be 1, 4 or 5
|
|
860
|
+
|
|
861
|
+
if (typeof sourceIndex === 'undefined') {
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
const generatedOffset = generatedLocator.locationToOffset({
|
|
866
|
+
// 1-base
|
|
867
|
+
line: generatedLine + 1,
|
|
868
|
+
column: generatedColumn
|
|
869
|
+
});
|
|
870
|
+
|
|
871
|
+
info = {
|
|
872
|
+
generatedOffset,
|
|
873
|
+
generatedLine,
|
|
874
|
+
generatedColumn,
|
|
875
|
+
|
|
876
|
+
sourceIndex,
|
|
877
|
+
originalLine,
|
|
878
|
+
originalColumn
|
|
879
|
+
};
|
|
880
|
+
|
|
881
|
+
allDecodedMappings.push(info);
|
|
882
|
+
|
|
883
|
+
originalDecodedMap.get(sourceIndex).push(info);
|
|
884
|
+
|
|
885
|
+
});
|
|
886
|
+
|
|
887
|
+
});
|
|
888
|
+
|
|
889
|
+
// defaults to sort by generated offset, not need sort
|
|
890
|
+
// allDecodedMappings.sort((a, b) => {
|
|
891
|
+
// return a.generatedOffset - b.generatedOffset;
|
|
892
|
+
// });
|
|
893
|
+
|
|
894
|
+
return allDecodedMappings;
|
|
895
|
+
};
|
|
896
|
+
|
|
897
|
+
const getOriginalDecodedMappings = (originalDecodedMap, sourceIndex, locator) => {
|
|
898
|
+
// all mappings for the original file sorted
|
|
899
|
+
const decodedMappings = originalDecodedMap.get(sourceIndex);
|
|
900
|
+
|
|
901
|
+
if (!decodedMappings) {
|
|
902
|
+
return [];
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
// sort by original line/column
|
|
906
|
+
decodedMappings.sort((a, b) => {
|
|
907
|
+
if (a.originalLine === b.originalLine) {
|
|
908
|
+
return a.originalColumn - b.originalColumn;
|
|
909
|
+
}
|
|
910
|
+
return a.originalLine - b.originalLine;
|
|
911
|
+
});
|
|
912
|
+
|
|
913
|
+
// add offset and index
|
|
914
|
+
decodedMappings.forEach((item, i) => {
|
|
915
|
+
item.originalOffset = locator.locationToOffset({
|
|
916
|
+
line: item.originalLine + 1,
|
|
917
|
+
column: item.originalColumn
|
|
918
|
+
});
|
|
919
|
+
});
|
|
920
|
+
|
|
921
|
+
return decodedMappings;
|
|
922
|
+
};
|
|
923
|
+
|
|
924
|
+
// ========================================================================================================
|
|
925
|
+
|
|
926
|
+
const getSourceFilter = (options) => {
|
|
927
|
+
const input = options.sourceFilter;
|
|
928
|
+
|
|
929
|
+
// for function handler
|
|
930
|
+
if (typeof input === 'function') {
|
|
931
|
+
return input;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
// for single minimatch pattern
|
|
935
|
+
if (input && typeof input === 'string') {
|
|
936
|
+
return (sourcePath) => {
|
|
937
|
+
return minimatch(sourcePath, input);
|
|
938
|
+
};
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
// for patterns
|
|
942
|
+
if (input && typeof input === 'object') {
|
|
943
|
+
const patterns = Object.keys(input);
|
|
944
|
+
return (sourcePath) => {
|
|
945
|
+
for (const pattern of patterns) {
|
|
946
|
+
if (minimatch(sourcePath, pattern)) {
|
|
947
|
+
return input[pattern];
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
// false if not matched
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
// default
|
|
955
|
+
return () => true;
|
|
956
|
+
};
|
|
957
|
+
|
|
958
|
+
const initOriginalList = (state, originalDecodedMap, options) => {
|
|
959
|
+
|
|
960
|
+
// source filter
|
|
961
|
+
const sourceFilter = getSourceFilter(options);
|
|
962
|
+
|
|
963
|
+
// create original content mappings
|
|
964
|
+
const originalStateMap = new Map();
|
|
965
|
+
|
|
966
|
+
const { sources, sourcesContent } = state.sourceMap;
|
|
967
|
+
|
|
968
|
+
sources.forEach((sourcePath, sourceIndex) => {
|
|
969
|
+
|
|
970
|
+
// filter
|
|
971
|
+
if (!sourceFilter(sourcePath)) {
|
|
972
|
+
// console.log('-', sourcePath);
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
// console.log(sourcePath);
|
|
976
|
+
|
|
977
|
+
// console.log(`add source: ${k}`);
|
|
978
|
+
const sourceContent = sourcesContent[sourceIndex];
|
|
979
|
+
if (typeof sourceContent !== 'string') {
|
|
980
|
+
Util.logError(`not found source content: ${sourcePath}`);
|
|
981
|
+
return;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
const locator = new Locator(sourceContent);
|
|
985
|
+
|
|
986
|
+
const decodedMappings = getOriginalDecodedMappings(originalDecodedMap, sourceIndex, locator);
|
|
987
|
+
|
|
988
|
+
// unpacked file always is js
|
|
989
|
+
|
|
990
|
+
const type = getSourceType(sourcePath);
|
|
991
|
+
|
|
992
|
+
const originalState = {
|
|
993
|
+
original: true,
|
|
994
|
+
// original file is js
|
|
995
|
+
js: true,
|
|
996
|
+
type,
|
|
997
|
+
source: sourceContent,
|
|
998
|
+
sourcePath,
|
|
999
|
+
locator,
|
|
1000
|
+
decodedMappings,
|
|
1001
|
+
// coverage info
|
|
1002
|
+
bytes: [],
|
|
1003
|
+
functions: [],
|
|
1004
|
+
branches: [],
|
|
1005
|
+
statements: [],
|
|
1006
|
+
astInfo: {
|
|
1007
|
+
functions: [],
|
|
1008
|
+
branches: [],
|
|
1009
|
+
statements: []
|
|
1010
|
+
},
|
|
1011
|
+
// coverage data
|
|
1012
|
+
v8Data: {}
|
|
1013
|
+
};
|
|
1014
|
+
|
|
1015
|
+
originalStateMap.set(sourceIndex, originalState);
|
|
1016
|
+
});
|
|
1017
|
+
|
|
1018
|
+
return originalStateMap;
|
|
1019
|
+
};
|
|
1020
|
+
|
|
1021
|
+
const collectOriginalList = (state, originalStateMap) => {
|
|
1022
|
+
|
|
1023
|
+
const { fileUrls } = state;
|
|
1024
|
+
const distFile = state.sourcePath;
|
|
1025
|
+
|
|
1026
|
+
// collect original files
|
|
1027
|
+
originalStateMap.forEach((originalState) => {
|
|
1028
|
+
|
|
1029
|
+
const {
|
|
1030
|
+
js, type, sourcePath, source
|
|
1031
|
+
} = originalState;
|
|
1032
|
+
|
|
1033
|
+
// add file item
|
|
1034
|
+
const url = fileUrls[sourcePath] || sourcePath;
|
|
1035
|
+
|
|
1036
|
+
// add dist for id
|
|
1037
|
+
const id = Util.calculateSha1(sourcePath + source);
|
|
1038
|
+
|
|
1039
|
+
const sourceItem = {
|
|
1040
|
+
url,
|
|
1041
|
+
id,
|
|
1042
|
+
js,
|
|
1043
|
+
type,
|
|
1044
|
+
sourcePath,
|
|
1045
|
+
distFile,
|
|
1046
|
+
source
|
|
1047
|
+
};
|
|
1048
|
+
|
|
1049
|
+
// save v8 data and add to originalList
|
|
1050
|
+
originalState.v8Data = sourceItem;
|
|
1051
|
+
state.originalList.push(originalState);
|
|
1052
|
+
});
|
|
1053
|
+
|
|
1054
|
+
};
|
|
1055
|
+
|
|
1056
|
+
// ========================================================================================================
|
|
1057
|
+
|
|
1058
|
+
const generateCoverageForDist = (state) => {
|
|
1059
|
+
|
|
1060
|
+
handleFunctionsCoverage(state);
|
|
1061
|
+
handleBranchesCoverage(state);
|
|
1062
|
+
handleStatementsCoverage(state);
|
|
1063
|
+
handleGeneratedBytesCoverage(state);
|
|
1064
|
+
|
|
1065
|
+
};
|
|
1066
|
+
|
|
1067
|
+
const unpackSourceMap = (state, options) => {
|
|
1068
|
+
|
|
1069
|
+
const { sourceMap } = state;
|
|
1070
|
+
|
|
1071
|
+
// keep original urls
|
|
1072
|
+
const fileUrls = {};
|
|
1073
|
+
const sourcePathHandler = getSourcePathHandler(options);
|
|
1074
|
+
initSourceMapSourcePath(sourceMap, fileUrls, sourcePathHandler);
|
|
1075
|
+
state.fileUrls = fileUrls;
|
|
1076
|
+
|
|
1077
|
+
// ===============================================
|
|
1078
|
+
// decode mappings for each original file
|
|
1079
|
+
|
|
1080
|
+
const originalDecodedMap = new Map();
|
|
1081
|
+
// for find-original-range
|
|
1082
|
+
state.decodedMappings = decodeSourceMappings(state, originalDecodedMap);
|
|
1083
|
+
|
|
1084
|
+
// filter original list and init list
|
|
1085
|
+
const originalStateMap = initOriginalList(state, originalDecodedMap, options);
|
|
1086
|
+
|
|
1087
|
+
originalDecodedMap.clear();
|
|
1088
|
+
|
|
1089
|
+
// ===============================================
|
|
1090
|
+
|
|
1091
|
+
// handle functions before handle original state functions
|
|
1092
|
+
handleOriginalFunctionsCoverage(state, originalStateMap);
|
|
1093
|
+
handleOriginalBranchesCoverage(state, originalStateMap);
|
|
1094
|
+
handleOriginalStatementsCoverage(state, originalStateMap);
|
|
1095
|
+
|
|
1096
|
+
// handle lines info before handle ranges to update line count
|
|
1097
|
+
originalStateMap.forEach((originalState) => {
|
|
1098
|
+
|
|
1099
|
+
handleFunctionsCoverage(originalState);
|
|
1100
|
+
handleBranchesCoverage(originalState);
|
|
1101
|
+
handleStatementsCoverage(originalState);
|
|
1102
|
+
|
|
1103
|
+
// if (originalState.sourcePath.endsWith('demo.js')) {
|
|
1104
|
+
// console.log('=================================', originalState.sourcePath);
|
|
1105
|
+
// }
|
|
1106
|
+
|
|
1107
|
+
});
|
|
1108
|
+
|
|
1109
|
+
// handle bytes ranges
|
|
1110
|
+
handleAllOriginalBytesCoverage(state, originalStateMap);
|
|
1111
|
+
|
|
1112
|
+
originalStateMap.forEach((originalState) => {
|
|
1113
|
+
handleOriginalBytesCoverage(originalState);
|
|
1114
|
+
});
|
|
1115
|
+
|
|
1116
|
+
// collect coverage for original list
|
|
1117
|
+
collectOriginalList(state, originalStateMap);
|
|
1118
|
+
|
|
1119
|
+
};
|
|
1120
|
+
|
|
1121
|
+
const unpackDistFile = (item, state, options) => {
|
|
1122
|
+
|
|
1123
|
+
if (state.sourceMap) {
|
|
1124
|
+
if (Util.isDebug()) {
|
|
1125
|
+
// js self
|
|
1126
|
+
item.debug = true;
|
|
1127
|
+
generateCoverageForDist(state);
|
|
1128
|
+
} else {
|
|
1129
|
+
item.dedupe = true;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
// unpack source map
|
|
1133
|
+
unpackSourceMap(state, options);
|
|
1134
|
+
|
|
1135
|
+
} else {
|
|
1136
|
+
|
|
1137
|
+
// css/js self
|
|
1138
|
+
generateCoverageForDist(state);
|
|
1139
|
+
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
};
|
|
1143
|
+
|
|
1144
|
+
// ========================================================================================================
|
|
1145
|
+
|
|
1146
|
+
const filterCoverageList = (item) => {
|
|
1147
|
+
const {
|
|
1148
|
+
functions, scriptOffset, source
|
|
1149
|
+
} = item;
|
|
1150
|
+
|
|
1151
|
+
// no script offset
|
|
1152
|
+
if (!scriptOffset) {
|
|
1153
|
+
return functions;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
// vm script offset
|
|
1157
|
+
const minOffset = scriptOffset;
|
|
1158
|
+
// the inline sourcemap could be removed
|
|
1159
|
+
const maxOffset = source.length;
|
|
1160
|
+
|
|
1161
|
+
const rootFunctionInfo = {
|
|
1162
|
+
root: true,
|
|
1163
|
+
ranges: [{
|
|
1164
|
+
startOffset: minOffset,
|
|
1165
|
+
endOffset: maxOffset,
|
|
1166
|
+
count: 1
|
|
1167
|
+
}]
|
|
1168
|
+
};
|
|
1169
|
+
|
|
1170
|
+
const coverageList = functions.filter((block) => {
|
|
1171
|
+
const { ranges } = block;
|
|
1172
|
+
|
|
1173
|
+
// first one is function coverage info
|
|
1174
|
+
const functionRange = ranges[0];
|
|
1175
|
+
const { startOffset, endOffset } = functionRange;
|
|
1176
|
+
if (startOffset >= minOffset && endOffset <= maxOffset) {
|
|
1177
|
+
return true;
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
// blocks
|
|
1181
|
+
const len = ranges.length;
|
|
1182
|
+
if (len > 1) {
|
|
1183
|
+
for (let i = 1; i < len; i++) {
|
|
1184
|
+
const range = ranges[i];
|
|
1185
|
+
if (range.startOffset >= minOffset && range.endOffset <= maxOffset) {
|
|
1186
|
+
rootFunctionInfo.ranges.push(range);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
return false;
|
|
1192
|
+
});
|
|
1193
|
+
|
|
1194
|
+
// first one for root function
|
|
1195
|
+
if (rootFunctionInfo.ranges.length > 1) {
|
|
1196
|
+
coverageList.unshift(rootFunctionInfo);
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
return coverageList;
|
|
1200
|
+
};
|
|
1201
|
+
|
|
1202
|
+
// ========================================================================================================
|
|
1203
|
+
|
|
1204
|
+
const isCoveredInRanges = (range, uncoveredBytes) => {
|
|
1205
|
+
if (!uncoveredBytes.length) {
|
|
1206
|
+
return true;
|
|
1207
|
+
}
|
|
1208
|
+
for (const item of uncoveredBytes) {
|
|
1209
|
+
if (range.start >= item.start && range.end <= item.end) {
|
|
1210
|
+
return false;
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
return true;
|
|
1214
|
+
};
|
|
1215
|
+
|
|
1216
|
+
const mergeV8Data = (state, stateList) => {
|
|
1217
|
+
// console.log(stateList);
|
|
1218
|
+
|
|
1219
|
+
// const sourcePath = state.sourcePath;
|
|
1220
|
+
// console.log(sourcePath);
|
|
1221
|
+
// if (sourcePath.endsWith('scroll_zoom.ts')) {
|
|
1222
|
+
// console.log('merge v8 data ===================================', sourcePath);
|
|
1223
|
+
// console.log(stateList.map((it) => it.bytes));
|
|
1224
|
+
// console.log(stateList.map((it) => it.functions));
|
|
1225
|
+
// console.log(stateList.map((it) => it.branches.map((b) => [`${b.start}-${b.end}`, JSON.stringify(b.locations.map((l) => l.count))])));
|
|
1226
|
+
// }
|
|
1227
|
+
|
|
1228
|
+
// ===========================================================
|
|
1229
|
+
// bytes
|
|
1230
|
+
const mergedBytes = [];
|
|
1231
|
+
const uncoveredList = [];
|
|
1232
|
+
stateList.forEach((st) => {
|
|
1233
|
+
const bytes = dedupeCountRanges(st.bytes);
|
|
1234
|
+
const uncoveredBytes = [];
|
|
1235
|
+
bytes.forEach((range) => {
|
|
1236
|
+
if (range.count) {
|
|
1237
|
+
mergedBytes.push(range);
|
|
1238
|
+
} else {
|
|
1239
|
+
uncoveredBytes.push(range);
|
|
1240
|
+
}
|
|
1241
|
+
});
|
|
1242
|
+
uncoveredList.push(uncoveredBytes);
|
|
1243
|
+
});
|
|
1244
|
+
// just remove uncovered range
|
|
1245
|
+
uncoveredList.forEach((currentBytes) => {
|
|
1246
|
+
currentBytes.forEach((range) => {
|
|
1247
|
+
for (const targetBytes of uncoveredList) {
|
|
1248
|
+
if (targetBytes === currentBytes) {
|
|
1249
|
+
continue;
|
|
1250
|
+
}
|
|
1251
|
+
if (isCoveredInRanges(range, targetBytes)) {
|
|
1252
|
+
return;
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
mergedBytes.push(range);
|
|
1256
|
+
});
|
|
1257
|
+
});
|
|
1258
|
+
|
|
1259
|
+
// will be dedupeCountRanges in collectFileCoverage
|
|
1260
|
+
state.bytes = mergedBytes;
|
|
1261
|
+
|
|
1262
|
+
// ===========================================================
|
|
1263
|
+
// functions
|
|
1264
|
+
const allFunctions = stateList.map((it) => it.functions).flat();
|
|
1265
|
+
const functionComparer = (lastRange, range) => {
|
|
1266
|
+
// if (lastRange.start === range.start && lastRange.end === range.end) {
|
|
1267
|
+
// return true;
|
|
1268
|
+
// }
|
|
1269
|
+
|
|
1270
|
+
// function range could be from sourcemap, not exact matched
|
|
1271
|
+
|
|
1272
|
+
// end is same
|
|
1273
|
+
// {start: 2017, end: 2315, count: 481}
|
|
1274
|
+
// {start: 2018, end: 2315, count: 14}
|
|
1275
|
+
|
|
1276
|
+
// start is same
|
|
1277
|
+
// {start: 10204, end: 10379, count: 0}
|
|
1278
|
+
// {start: 10204, end: 10393, count: 5}
|
|
1279
|
+
|
|
1280
|
+
// only one position matched could be same
|
|
1281
|
+
if (lastRange.start === range.start || lastRange.end === range.end) {
|
|
1282
|
+
// console.log(lastRange.start, range.start, lastRange.end, range.end);
|
|
1283
|
+
|
|
1284
|
+
// if (lastRange.start === range.start) {
|
|
1285
|
+
// console.log(range.end - lastRange.end, lastRange.start, lastRange.end, 'end', range.end, state.sourcePath);
|
|
1286
|
+
// } else {
|
|
1287
|
+
// console.log(range.start - lastRange.start, lastRange.start, lastRange.end, 'start', range.start, state.sourcePath);
|
|
1288
|
+
// }
|
|
1289
|
+
|
|
1290
|
+
return true;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
return false;
|
|
1294
|
+
};
|
|
1295
|
+
const functionHandler = (lastRange, range) => {
|
|
1296
|
+
lastRange.count += range.count;
|
|
1297
|
+
};
|
|
1298
|
+
const mergedFunctions = mergeRangesWith(allFunctions, functionComparer, functionHandler);
|
|
1299
|
+
state.functions = mergedFunctions;
|
|
1300
|
+
|
|
1301
|
+
// ===========================================================
|
|
1302
|
+
// branches
|
|
1303
|
+
const allBranches = stateList.map((it) => it.branches).flat();
|
|
1304
|
+
const branchComparer = (lastRange, range) => {
|
|
1305
|
+
// exact matched because the branch range is generated from ast
|
|
1306
|
+
return lastRange.start === range.start && lastRange.end === range.end;
|
|
1307
|
+
};
|
|
1308
|
+
const branchHandler = (lastRange, range) => {
|
|
1309
|
+
// merge locations count
|
|
1310
|
+
lastRange.locations.forEach((item, i) => {
|
|
1311
|
+
const loc = range.locations[i];
|
|
1312
|
+
if (loc) {
|
|
1313
|
+
item.count += loc.count;
|
|
1314
|
+
}
|
|
1315
|
+
});
|
|
1316
|
+
};
|
|
1317
|
+
const mergedBranches = mergeRangesWith(allBranches, branchComparer, branchHandler);
|
|
1318
|
+
state.branches = mergedBranches;
|
|
1319
|
+
|
|
1320
|
+
// if (sourcePath.endsWith('scroll_zoom.ts')) {
|
|
1321
|
+
// console.log(mergedBytes);
|
|
1322
|
+
// console.log(mergedFunctions);
|
|
1323
|
+
// console.log(mergedBranches.map((b) => [`${b.start}-${b.end}`, JSON.stringify(b.locations.map((l) => l.count))]));
|
|
1324
|
+
// }
|
|
1325
|
+
|
|
1326
|
+
|
|
1327
|
+
};
|
|
1328
|
+
|
|
1329
|
+
const generateV8DataList = (stateList, options) => {
|
|
1330
|
+
|
|
1331
|
+
const stateMap = new Map();
|
|
1332
|
+
|
|
1333
|
+
// all original files from dist
|
|
1334
|
+
const allOriginalList = [];
|
|
1335
|
+
stateList.forEach((state) => {
|
|
1336
|
+
const { v8Data, originalList } = state;
|
|
1337
|
+
// dedupe dist file if not debug
|
|
1338
|
+
if (!v8Data.dedupe) {
|
|
1339
|
+
stateMap.set(v8Data.id, state);
|
|
1340
|
+
}
|
|
1341
|
+
allOriginalList.push(originalList);
|
|
1342
|
+
});
|
|
1343
|
+
|
|
1344
|
+
// merge istanbul and v8(converted)
|
|
1345
|
+
const mergeMap = new Map();
|
|
1346
|
+
allOriginalList.flat().forEach((originalState) => {
|
|
1347
|
+
const { v8Data } = originalState;
|
|
1348
|
+
const id = v8Data.id;
|
|
1349
|
+
// exists item
|
|
1350
|
+
const prevState = stateMap.get(id);
|
|
1351
|
+
if (prevState) {
|
|
1352
|
+
// ignore empty item, just override it
|
|
1353
|
+
if (!prevState.v8Data.empty) {
|
|
1354
|
+
if (mergeMap.has(id)) {
|
|
1355
|
+
mergeMap.get(id).push(originalState);
|
|
1356
|
+
} else {
|
|
1357
|
+
mergeMap.set(id, [prevState, originalState]);
|
|
1358
|
+
}
|
|
1359
|
+
return;
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
stateMap.set(id, originalState);
|
|
1363
|
+
});
|
|
1364
|
+
|
|
1365
|
+
const mergeIds = mergeMap.keys();
|
|
1366
|
+
for (const id of mergeIds) {
|
|
1367
|
+
const state = stateMap.get(id);
|
|
1368
|
+
// for source the type could be ts, so just use js (boolean)
|
|
1369
|
+
if (state.js) {
|
|
1370
|
+
mergeV8Data(state, mergeMap.get(id));
|
|
1371
|
+
} else {
|
|
1372
|
+
// should no css here, css can not be in sources
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
// new v8 data list (includes sources)
|
|
1377
|
+
const v8DataList = [];
|
|
1378
|
+
// global file sources and istanbul coverage data
|
|
1379
|
+
const fileSources = {};
|
|
1380
|
+
const coverageData = {};
|
|
1381
|
+
stateMap.forEach((state) => {
|
|
1382
|
+
const { v8Data } = state;
|
|
1383
|
+
const istanbulData = collectFileCoverage(v8Data, state, options);
|
|
1384
|
+
const { sourcePath, source } = v8Data;
|
|
1385
|
+
v8DataList.push(v8Data);
|
|
1386
|
+
fileSources[sourcePath] = source;
|
|
1387
|
+
coverageData[sourcePath] = istanbulData;
|
|
1388
|
+
});
|
|
1389
|
+
|
|
1390
|
+
return {
|
|
1391
|
+
v8DataList,
|
|
1392
|
+
fileSources,
|
|
1393
|
+
coverageData
|
|
1394
|
+
};
|
|
1395
|
+
};
|
|
1396
|
+
|
|
1397
|
+
const convertV8List = (v8list, options) => {
|
|
1398
|
+
|
|
1399
|
+
const stateList = [];
|
|
1400
|
+
|
|
1401
|
+
for (const item of v8list) {
|
|
1402
|
+
// console.log([item.id]);
|
|
1403
|
+
|
|
1404
|
+
const {
|
|
1405
|
+
type, source, sourcePath
|
|
1406
|
+
} = item;
|
|
1407
|
+
|
|
1408
|
+
// for source file, type could be ts or vue as extname, but js = true
|
|
1409
|
+
const js = type === 'js';
|
|
1410
|
+
item.js = js;
|
|
1411
|
+
|
|
1412
|
+
// source mapping
|
|
1413
|
+
const locator = new Locator(source);
|
|
1414
|
+
|
|
1415
|
+
// ============================
|
|
1416
|
+
// move sourceMap
|
|
1417
|
+
const sourceMap = item.sourceMap;
|
|
1418
|
+
if (sourceMap) {
|
|
1419
|
+
delete item.sourceMap;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
// ============================
|
|
1423
|
+
const time_start_ast = Date.now();
|
|
1424
|
+
// move functions and ranges to coverageList
|
|
1425
|
+
let coverageList = [];
|
|
1426
|
+
let astInfo;
|
|
1427
|
+
if (js) {
|
|
1428
|
+
coverageList = filterCoverageList(item);
|
|
1429
|
+
// remove original functions
|
|
1430
|
+
if (!Util.isDebug()) {
|
|
1431
|
+
delete item.functions;
|
|
1432
|
+
}
|
|
1433
|
+
astInfo = getJsAstInfo(item, coverageList);
|
|
1434
|
+
} else {
|
|
1435
|
+
// convent css covered ranges to rules ranges and include uncovered ranges
|
|
1436
|
+
astInfo = getCssAstInfo(item, coverageList);
|
|
1437
|
+
// remove original ranges
|
|
1438
|
+
if (!Util.isDebug()) {
|
|
1439
|
+
delete item.ranges;
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
Util.logTime(`- parsed ast: ${sourcePath}`, time_start_ast);
|
|
1443
|
+
|
|
1444
|
+
// console.log(sourcePath, astInfo.statements.length);
|
|
1445
|
+
// ============================
|
|
1446
|
+
|
|
1447
|
+
// current file and it's sources from sourceMap
|
|
1448
|
+
// see const originalState
|
|
1449
|
+
const state = {
|
|
1450
|
+
js,
|
|
1451
|
+
type,
|
|
1452
|
+
source,
|
|
1453
|
+
sourcePath,
|
|
1454
|
+
sourceMap,
|
|
1455
|
+
locator,
|
|
1456
|
+
decodedMappings: [],
|
|
1457
|
+
// coverage info
|
|
1458
|
+
bytes: [],
|
|
1459
|
+
functions: [],
|
|
1460
|
+
branches: [],
|
|
1461
|
+
statements: [],
|
|
1462
|
+
astInfo,
|
|
1463
|
+
// for sub source files
|
|
1464
|
+
coverageList,
|
|
1465
|
+
originalList: [],
|
|
1466
|
+
// coverage data
|
|
1467
|
+
v8Data: item
|
|
1468
|
+
};
|
|
1469
|
+
|
|
1470
|
+
const time_start_unpack = Date.now();
|
|
1471
|
+
unpackDistFile(item, state, options);
|
|
1472
|
+
Util.logTime(`- unpacked dist: ${sourcePath}`, time_start_unpack);
|
|
1473
|
+
|
|
1474
|
+
stateList.push(state);
|
|
1475
|
+
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
const time_start_convert = Date.now();
|
|
1479
|
+
const dataList = generateV8DataList(stateList, options);
|
|
1480
|
+
Util.logTime('- generated v8 data list', time_start_convert);
|
|
1481
|
+
|
|
1482
|
+
return dataList;
|
|
1483
|
+
};
|
|
1484
|
+
|
|
1485
|
+
module.exports = {
|
|
1486
|
+
convertV8List
|
|
1487
|
+
};
|