monocart-coverage-reports 2.3.3 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,19 +17,37 @@ const {
17
17
  const { getSourceType, initSourceMapSourcePath } = require('../utils/source-path.js');
18
18
  const { decode } = require('../packages/monocart-coverage-vendor.js');
19
19
 
20
- const InfoLine = require('./info-line.js');
21
20
  const InfoBranch = require('./info-branch.js');
22
21
  const InfoFunction = require('./info-function.js');
23
- const findInRanges = require('./find-in-ranges.js');
22
+ const InfoStatement = require('./info-statement.js');
23
+
24
+ // ========================================================================================================
25
+
26
+ // debug info
27
+ const logMappingErrors = (type, result) => {
28
+
29
+ // const {
30
+ // errors, start, end, sourcePath
31
+ // } = result;
32
+ // // if (!sourcePath.endsWith('monocart-v8.js') || type !== 'byte') {
33
+ // // return;
34
+ // // }
35
+ // const list = [
36
+ // Util.EC.red('[Mapping]'),
37
+ // Util.EC.magenta(type),
38
+ // errors.join(' -> '),
39
+ // Util.EC.blue(`${start} ~ ${end}`),
40
+ // sourcePath
41
+ // ];
42
+ // console.log(list.join(' '));
43
+
44
+ };
24
45
 
25
46
  // ========================================================================================================
26
47
 
27
48
  const handleIgnoredRanges = (list, ignoredRanges) => {
28
49
  list.forEach((item) => {
29
- if (item.count > 0) {
30
- return;
31
- }
32
- const range = findInRanges(item.start, item.end, ignoredRanges);
50
+ const range = Util.findInRanges(item.start, item.end, ignoredRanges, 'start', 'end');
33
51
  if (range) {
34
52
  // console.log(item, range);
35
53
  item.ignored = true;
@@ -37,15 +55,18 @@ const handleIgnoredRanges = (list, ignoredRanges) => {
37
55
  });
38
56
  };
39
57
 
40
- // ========================================================================================================
41
58
 
42
- const updateLinesCount = (bytes, locator, lineMap) => {
59
+ const applyBytesToLines = (bytes, locator, lineMap) => {
43
60
  bytes.forEach((range) => {
44
-
45
61
  const {
46
62
  start, end, count, ignored
47
63
  } = range;
48
64
 
65
+ // no need handle ignored and uncovered byte
66
+ if (count === 0 && ignored) {
67
+ return;
68
+ }
69
+
49
70
  const sLoc = locator.offsetToLocation(start);
50
71
  const eLoc = locator.offsetToLocation(end);
51
72
 
@@ -53,155 +74,150 @@ const updateLinesCount = (bytes, locator, lineMap) => {
53
74
  const lines = Util.getRangeLines(sLoc, eLoc);
54
75
 
55
76
  lines.forEach((it) => {
56
- const line = lineMap.get(it.line);
57
- if (!line) {
77
+ const lineItem = lineMap.get(it.line);
78
+ if (!lineItem) {
79
+ // not found line, could be comment or blank line
80
+ return;
81
+ }
82
+ if (lineItem.ignored) {
58
83
  return;
59
84
  }
60
85
 
61
- // from outside into inside, uncovered is certain
62
- // default is covered
63
- if (it.entire) {
64
- line.covered = count > 0;
65
- line.count = count;
86
+ it.count = count;
66
87
 
67
- if (ignored) {
68
- if (!line.covered) {
69
- line.ignored = true;
70
- }
88
+ // default is covered, so only focus on
89
+ // 1, biggest covered count
90
+ // 2, uncovered entire and pieces
91
+ if (count > 0) {
92
+ lineItem.coveredCount = Math.max(lineItem.coveredCount, count);
93
+ } else {
94
+ if (it.entire) {
95
+ lineItem.uncoveredEntire = it;
96
+ } else {
97
+ lineItem.uncoveredPieces.push(it);
71
98
  }
99
+ }
100
+ });
72
101
 
73
- } else {
102
+ });
74
103
 
75
- if (!ignored) {
76
- if (count > 0) {
77
- line.count = count;
78
- } else {
79
- // not covered if any count = 0
80
- line.covered = false;
81
- }
82
- }
104
+ // no ignore items
105
+ lineMap.forEach((lineItem, line) => {
83
106
 
84
- }
107
+ const {
108
+ uncoveredEntire, uncoveredPieces, coveredCount
109
+ } = lineItem;
85
110
 
86
- // if (!line.history) {
87
- // line.history = [];
88
- // }
89
- // line.history.push(`${it.entire}-${count}`);
111
+ // default count to 1, both js and css
112
+ let count = 1;
113
+ // full covered true/false for entire line
114
+ let covered = true;
90
115
 
91
- });
116
+ if (uncoveredEntire) {
117
+ count = 0;
118
+ covered = false;
119
+ } else {
120
+ count = coveredCount;
121
+ const uncoveredLen = uncoveredPieces.length;
122
+ if (uncoveredLen > 0) {
123
+ covered = false;
124
+ // uncovered
125
+ count = `1/${uncoveredLen + 1}`;
126
+ }
127
+ }
92
128
 
93
- });
129
+ lineItem.covered = covered;
130
+ lineItem.count = count;
94
131
 
95
- // if (state.sourcePath.endsWith('component.js')) {
96
- // console.log('===========================================', state.sourcePath);
97
- // }
132
+ });
98
133
 
99
134
  };
100
135
 
101
- const handleLinesCoverage = (bytes, locator) => {
102
-
103
- const lines = [];
104
- // line 1 based
105
- const lineMap = new Map();
136
+ const handleLinesCoverage = (bytes, locator, ignoredRanges) => {
106
137
 
107
138
  // init lines
108
139
  let blankCount = 0;
109
140
  let commentCount = 0;
110
-
111
- locator.lines.forEach((it) => {
141
+ // line 1 based
142
+ const lineMap = new Map();
143
+ locator.lines.forEach((lineItem) => {
112
144
  // exclude blank and comment
113
- if (it.blank) {
145
+ if (lineItem.blank) {
114
146
  blankCount += 1;
115
147
  return;
116
148
  }
117
- if (it.comment) {
149
+ if (lineItem.comment) {
118
150
  commentCount += 1;
119
151
  return;
120
152
  }
153
+ const ignored = Util.findInRanges(lineItem.start, lineItem.end, ignoredRanges);
154
+ if (ignored) {
155
+ return;
156
+ }
121
157
  // line 1-base
122
- const line = it.line + 1;
123
- // default count to 1, both js and css
124
- const lineInfo = new InfoLine(line, it.length, 1);
125
- lineMap.set(line, lineInfo);
126
- lines.push(lineInfo);
158
+ const line = lineItem.line + 1;
159
+ lineItem.coveredCount = 1;
160
+ lineItem.uncoveredEntire = null;
161
+ lineItem.uncoveredPieces = [];
162
+ lineMap.set(line, lineItem);
127
163
  });
128
164
 
129
- updateLinesCount(bytes, locator, lineMap);
130
-
131
- return {
132
- lines,
133
- blankCount,
134
- commentCount
135
- };
136
- };
137
-
138
- // ========================================================================================================
139
-
140
- const calculateV8Functions = (functions) => {
165
+ applyBytesToLines(bytes, locator, lineMap);
141
166
 
142
- const v8Functions = {
167
+ const summaryLines = {
143
168
  total: 0,
144
- covered: 0
169
+ covered: 0,
170
+ blank: blankCount,
171
+ comment: commentCount
145
172
  };
146
-
147
- functions.forEach((fn) => {
148
- if (fn.ignored) {
149
- return;
150
- }
151
-
152
- v8Functions.total += 1;
153
- if (fn.count > 0) {
154
- v8Functions.covered += 1;
173
+ // data lines for codecov
174
+ // https://docs.codecov.com/docs/codecov-custom-coverage-format
175
+ const dataLines = {};
176
+
177
+ // no ignore items
178
+ lineMap.forEach((lineItem, line) => {
179
+ const { count, covered } = lineItem;
180
+ // data lines
181
+ dataLines[line] = count;
182
+
183
+ summaryLines.total += 1;
184
+ if (covered) {
185
+ summaryLines.covered += 1;
155
186
  }
156
187
  });
157
188
 
158
- return v8Functions;
159
- };
160
-
161
- const calculateV8Branches = (branches) => {
162
- const v8Branches = {
163
- total: 0,
164
- covered: 0
189
+ return {
190
+ dataLines,
191
+ summaryLines
165
192
  };
193
+ };
166
194
 
167
- branches.forEach((branch) => {
168
- if (branch.ignored) {
169
- return;
170
- }
171
- v8Branches.total += 1;
172
- if (branch.count > 0) {
173
- v8Branches.covered += 1;
174
- }
175
- });
195
+ // ========================================================================================================
176
196
 
177
- return v8Branches;
178
- };
197
+ const calculateV8Summary = (list) => {
179
198
 
180
- const calculateV8Lines = (lines, blankCount, commentCount) => {
181
- const v8Lines = {
199
+ const summary = {
182
200
  total: 0,
183
- covered: 0,
184
- blank: blankCount,
185
- comment: commentCount
201
+ covered: 0
186
202
  };
187
203
 
188
- lines.forEach((ln) => {
189
- if (ln.ignored) {
190
- // console.log(ln);
204
+ list.forEach((item) => {
205
+ if (item.ignored) {
191
206
  return;
192
207
  }
193
- v8Lines.total += 1;
194
- // full line covered
195
- if (ln.covered) {
196
- v8Lines.covered += 1;
208
+
209
+ summary.total += 1;
210
+ if (item.count > 0) {
211
+ summary.covered += 1;
197
212
  }
198
213
  });
199
214
 
200
- return v8Lines;
215
+ return summary;
201
216
  };
202
217
 
203
218
  // ========================================================================================================
204
219
  // istanbul coverage format
220
+ // https://github.com/istanbuljs/istanbuljs/blob/master/docs/raw-output.md
205
221
  /**
206
222
  * * `path` - the file path for which coverage is being tracked
207
223
  * * `statementMap` - map of statement locations keyed by statement index
@@ -217,6 +233,7 @@ const collectFileCoverage = (v8Data, state, options) => {
217
233
  bytes,
218
234
  functions,
219
235
  branches,
236
+ statements,
220
237
 
221
238
  sourcePath,
222
239
  locator
@@ -227,7 +244,8 @@ const collectFileCoverage = (v8Data, state, options) => {
227
244
  const data = {
228
245
  bytes: dedupeCountRanges(bytes),
229
246
  functions: [],
230
- branches: []
247
+ branches: [],
248
+ statements: []
231
249
  };
232
250
 
233
251
  // ==========================================
@@ -235,13 +253,15 @@ const collectFileCoverage = (v8Data, state, options) => {
235
253
  const ignoredRanges = getIgnoredRanges(locator, options);
236
254
  if (ignoredRanges) {
237
255
 
256
+ data.ignores = ignoredRanges;
257
+
238
258
  // data bytes is start/end/count object
239
259
  handleIgnoredRanges(data.bytes, ignoredRanges);
240
260
 
241
- // functions is InfoFunction start/end/count instance
261
+ // functions start/end/count instance
242
262
  handleIgnoredRanges(functions, ignoredRanges);
243
263
 
244
- // branches is InfoBranch start/end/count instance
264
+ // branches start/end/count instance
245
265
  handleIgnoredRanges(branches, ignoredRanges);
246
266
 
247
267
  // branch locations start/end/count object
@@ -256,10 +276,24 @@ const collectFileCoverage = (v8Data, state, options) => {
256
276
  }
257
277
  });
258
278
 
279
+ // statements start/end/count instance
280
+ handleIgnoredRanges(statements, ignoredRanges);
281
+
259
282
  // console.log(ignoredRanges);
260
283
 
261
284
  }
262
285
 
286
+ // ==========================================
287
+ // lines
288
+ // after bytes with ignored, before calculateV8Lines
289
+ const { dataLines, summaryLines } = handleLinesCoverage(data.bytes, locator, ignoredRanges);
290
+
291
+ data.lines = dataLines;
292
+
293
+ // console.log('statements', state.sourcePath, statements.length);
294
+
295
+ // ==========================================
296
+
263
297
  data.functions = functions.map((info) => {
264
298
  return info.getRange();
265
299
  });
@@ -271,21 +305,24 @@ const collectFileCoverage = (v8Data, state, options) => {
271
305
  }).flat();
272
306
  sortRanges(data.branches);
273
307
 
308
+ data.statements = statements.map((info) => {
309
+ return info.getRange();
310
+ });
311
+ sortRanges(data.statements);
312
+
274
313
  // ==========================================
275
- // lines
276
- // after bytes with ignored, before calculateV8Lines
277
- const {
278
- lines, blankCount, commentCount
279
- } = handleLinesCoverage(data.bytes, locator);
314
+
315
+ const summary = {
316
+ functions: calculateV8Summary(data.functions),
317
+ branches: calculateV8Summary(data.branches),
318
+ statements: calculateV8Summary(data.statements),
319
+ lines: summaryLines
320
+ };
280
321
 
281
322
  // ==========================================
282
323
  // v8 data and summary
283
324
  v8Data.data = data;
284
- v8Data.summary = {
285
- functions: calculateV8Functions(data.functions),
286
- branches: calculateV8Branches(data.branches),
287
- lines: calculateV8Lines(lines, blankCount, commentCount)
288
- };
325
+ v8Data.summary = summary;
289
326
 
290
327
  // ==========================================
291
328
  // istanbul
@@ -301,25 +338,13 @@ const collectFileCoverage = (v8Data, state, options) => {
301
338
  b: {}
302
339
  };
303
340
 
304
- // for codecov https://docs.codecov.com/docs/codecov-custom-coverage-format
305
- data.lines = {};
306
-
307
- lines.filter((it) => !it.ignored).forEach((line, index) => {
308
- istanbulData.statementMap[`${index}`] = line.generate();
309
- istanbulData.s[`${index}`] = line.count;
310
-
311
- let count = 0;
312
- if (line.covered) {
313
- count = line.count;
314
- } else if (!line.covered && line.count > 0) {
315
- count = '1/2';
316
- }
317
- // 1-base
318
- data.lines[`${line.line}`] = count;
341
+ statements.filter((it) => !it.ignored).forEach((statement, index) => {
342
+ istanbulData.statementMap[`${index}`] = statement.generate(locator);
343
+ istanbulData.s[`${index}`] = statement.count;
319
344
  });
320
345
 
321
346
  functions.filter((it) => !it.ignored).forEach((fn, index) => {
322
- istanbulData.fnMap[`${index}`] = fn.generate(locator);
347
+ istanbulData.fnMap[`${index}`] = fn.generate(locator, index);
323
348
  istanbulData.f[`${index}`] = fn.count;
324
349
  });
325
350
 
@@ -329,7 +354,6 @@ const collectFileCoverage = (v8Data, state, options) => {
329
354
  istanbulData.b[`${index}`] = counts;
330
355
  });
331
356
 
332
- // istanbul data
333
357
  return istanbulData;
334
358
 
335
359
  };
@@ -341,11 +365,17 @@ const addJsBytesCoverage = (state, range) => {
341
365
  startOffset, endOffset, count
342
366
  } = range;
343
367
  // add bytes range
344
- state.bytes.push({
368
+ const byte = {
345
369
  start: startOffset,
346
370
  end: endOffset,
347
371
  count
348
- });
372
+ };
373
+ // for debug
374
+ if (Util.isDebug() && state.original) {
375
+ byte.generatedStart = range.generatedStart;
376
+ byte.generatedEnd = range.generatedEnd;
377
+ }
378
+ state.bytes.push(byte);
349
379
  };
350
380
 
351
381
  const addCssBytesCoverage = (state, range) => {
@@ -371,11 +401,14 @@ const handleFunctionsCoverage = (state) => {
371
401
 
372
402
  const { functions, astInfo } = state;
373
403
  astInfo.functions.forEach((it) => {
374
- const {
375
- start, end, functionName, count
376
- } = it;
377
- const functionInfo = new InfoFunction(start, end, count, functionName);
378
- functions.push(functionInfo);
404
+
405
+ const { start, end } = it;
406
+ if (start >= end) {
407
+ // console.log('invalid function', start, end);
408
+ return;
409
+ }
410
+
411
+ functions.push(new InfoFunction(it, state.original));
379
412
  });
380
413
 
381
414
  };
@@ -389,11 +422,35 @@ const handleBranchesCoverage = (state) => {
389
422
 
390
423
  const { branches, astInfo } = state;
391
424
  astInfo.branches.forEach((it) => {
392
- const {
393
- start, end, locations, type
394
- } = it;
395
- const branchInfo = new InfoBranch(start, end, locations, type);
396
- branches.push(branchInfo);
425
+
426
+ const { start, end } = it;
427
+ if (start >= end) {
428
+ // console.log('invalid branch', state.sourcePath, it);
429
+ return;
430
+ }
431
+
432
+ branches.push(new InfoBranch(it, state.original));
433
+ });
434
+
435
+ };
436
+
437
+ const handleStatementsCoverage = (state) => {
438
+
439
+ // statement only for js
440
+ if (!state.js) {
441
+ return;
442
+ }
443
+
444
+ const { statements, astInfo } = state;
445
+ astInfo.statements.forEach((it) => {
446
+
447
+ const { start, end } = it;
448
+ if (start >= end) {
449
+ // console.log('invalid statement', start, end);
450
+ return;
451
+ }
452
+
453
+ statements.push(new InfoStatement(it, state.original));
397
454
  });
398
455
 
399
456
  };
@@ -427,10 +484,22 @@ const handleOriginalFunctionsCoverage = (state, originalStateMap) => {
427
484
 
428
485
  // console.log(state.astInfo.functions);
429
486
 
487
+ const updateFunctionBodyRange = (start, end, bodyStart, bodyEnd, originalFunction) => {
488
+ if (bodyStart !== start || bodyEnd !== end) {
489
+ const result = findOriginalRange(bodyStart, bodyEnd, state, originalStateMap);
490
+ if (result.error) {
491
+ logMappingErrors('function body', result);
492
+ } else {
493
+ originalFunction.bodyStart = result.start;
494
+ originalFunction.bodyEnd = result.end;
495
+ }
496
+ }
497
+ };
498
+
430
499
  // function count
431
500
  state.astInfo.functions.forEach((it) => {
432
501
  const {
433
- start, end, wrap
502
+ start, end, bodyStart, bodyEnd, wrap
434
503
  } = it;
435
504
 
436
505
  // remove webpack wrap functions for functions count, not for ranges here
@@ -438,31 +507,27 @@ const handleOriginalFunctionsCoverage = (state, originalStateMap) => {
438
507
  return;
439
508
  }
440
509
 
441
- // rename to startOffset and endOffset
442
- const range = {
443
- startOffset: start,
444
- endOffset: end
445
- };
446
-
447
- const result = findOriginalRange(range, state, originalStateMap);
510
+ const result = findOriginalRange(start, end, state, originalStateMap);
448
511
  if (result.error) {
512
+ logMappingErrors('function', result);
449
513
  return;
450
514
  }
451
- const { originalRange, originalState } = result;
452
515
 
453
- // add back to original ast
454
- originalState.astInfo.functions.push({
516
+ const originalFunction = {
455
517
  ... it,
456
518
  generatedStart: start,
457
519
  generatedEnd: end,
458
- start: originalRange.startOffset,
459
- end: originalRange.endOffset
460
- });
520
+ start: result.start,
521
+ end: result.end,
522
+ bodyStart: result.start,
523
+ bodyEnd: result.end
524
+ };
461
525
 
462
- // if (originalState.sourcePath.endsWith('store.js')) {
463
- // console.log('==========================================================');
464
- // console.log(it, result.startMapping, result.endMapping);
465
- // }
526
+ // body start and end
527
+ updateFunctionBodyRange(start, end, bodyStart, bodyEnd, originalFunction);
528
+
529
+ // add back to original ast
530
+ result.originalState.astInfo.functions.push(originalFunction);
466
531
 
467
532
  });
468
533
 
@@ -478,26 +543,20 @@ const handleOriginalBranchesCoverage = (state, originalStateMap) => {
478
543
  // console.log(state.astInfo.branches);
479
544
 
480
545
  // function count
481
- state.astInfo.branches.forEach((it) => {
546
+ state.astInfo.branches.forEach((group) => {
482
547
 
483
- const { type, locations } = it;
484
-
485
- // rename to startOffset and endOffset
486
- const bRange = {
487
- startOffset: it.start,
488
- endOffset: it.end
489
- };
548
+ const { type, locations } = group;
490
549
 
491
550
  // start
492
- const result = findOriginalRange(bRange, state, originalStateMap);
551
+ const result = findOriginalRange(group.start, group.end, state, originalStateMap);
493
552
  if (result.error) {
494
- // not in the original files
553
+ logMappingErrors('branch group', result);
495
554
  return;
496
555
  }
497
- const { originalRange, originalState } = result;
498
556
 
499
- const groupStart = originalRange.startOffset;
500
- const groupEnd = originalRange.endOffset;
557
+ // new group start and end
558
+ const groupStart = result.start;
559
+ const groupEnd = result.end;
501
560
 
502
561
  let hasError;
503
562
  const newLocations = locations.map((oLoc) => {
@@ -512,29 +571,19 @@ const handleOriginalBranchesCoverage = (state, originalStateMap) => {
512
571
  return newLoc;
513
572
  }
514
573
 
515
- const { start, end } = newLoc;
516
-
517
- const lRange = {
518
- startOffset: start,
519
- endOffset: end
520
- };
521
- const res = findOriginalRange(lRange, state, originalStateMap);
522
- if (res.error) {
574
+ const locResult = findOriginalRange(newLoc.start, newLoc.end, state, originalStateMap);
575
+ if (locResult.error) {
523
576
  // It should not happen unless it is minify files, the SourceMap has some order problems
524
-
577
+ logMappingErrors('branch', locResult);
525
578
  hasError = true;
526
-
527
- // console.log('====================================', state.sourcePath, loc);
528
- // console.log(res.errors);
529
- // Util.logError(`Not found original branch. start: ${start}, end: ${end}`);
530
-
531
579
  return newLoc;
532
580
  }
533
581
 
534
582
  // mapping to new range
535
- const oRage = res.originalRange;
536
- newLoc.start = oRage.startOffset;
537
- newLoc.end = oRage.endOffset;
583
+ newLoc.start = locResult.start;
584
+ newLoc.end = locResult.end;
585
+ newLoc.generatedStart = newLoc.start;
586
+ newLoc.generatedEnd = newLoc.end;
538
587
 
539
588
  return newLoc;
540
589
  });
@@ -545,7 +594,7 @@ const handleOriginalBranchesCoverage = (state, originalStateMap) => {
545
594
  }
546
595
 
547
596
  // add back to original ast
548
- originalState.astInfo.branches.push({
597
+ result.originalState.astInfo.branches.push({
549
598
  type,
550
599
  start: groupStart,
551
600
  end: groupEnd,
@@ -556,6 +605,50 @@ const handleOriginalBranchesCoverage = (state, originalStateMap) => {
556
605
 
557
606
  };
558
607
 
608
+ const handleOriginalStatementsCoverage = (state, originalStateMap) => {
609
+
610
+ // statements only for js
611
+ if (!state.js) {
612
+ return;
613
+ }
614
+
615
+ // statement count
616
+ state.astInfo.statements.forEach((it) => {
617
+ const { start, end } = it;
618
+
619
+ const result = findOriginalRange(start, end, state, originalStateMap);
620
+ if (result.error) {
621
+ logMappingErrors('statement', result);
622
+ return;
623
+ }
624
+
625
+ // add back to original ast
626
+ result.originalState.astInfo.statements.push({
627
+ ... it,
628
+ generatedStart: start,
629
+ generatedEnd: end,
630
+ start: result.start,
631
+ end: result.end
632
+ });
633
+
634
+ });
635
+
636
+ originalStateMap.forEach((originalState) => {
637
+ const statements = originalState.astInfo.statements;
638
+ if (Util.isList(statements)) {
639
+ return;
640
+ }
641
+ // fake source nothing matched
642
+ statements.push({
643
+ start: 0,
644
+ end: originalState.source.length,
645
+ count: 1
646
+ });
647
+
648
+ });
649
+
650
+ };
651
+
559
652
  const handleOriginalBytesCoverage = (state, originalStateMap) => {
560
653
 
561
654
  const { js, coverageList } = state;
@@ -572,18 +665,23 @@ const handleOriginalBytesCoverage = (state, originalStateMap) => {
572
665
  return;
573
666
  }
574
667
 
575
- const result = findOriginalRange(range, state, originalStateMap);
668
+ const {
669
+ startOffset, endOffset, count
670
+ } = range;
671
+
672
+ const result = findOriginalRange(startOffset, endOffset, state, originalStateMap);
576
673
  if (result.error) {
674
+ logMappingErrors('byte', result);
577
675
  return;
578
676
  }
579
677
 
580
- const { originalRange, originalState } = result;
581
- addJsBytesCoverage(originalState, originalRange);
582
-
583
- // if (originalRange.startOffset === 110 && originalRange.endOffset === 271) {
584
- // console.log('===============================', originalState.sourcePath);
585
- // console.log(result.startMapping, result.endMapping);
586
- // }
678
+ addJsBytesCoverage(result.originalState, {
679
+ generatedStart: startOffset,
680
+ generatedEnd: endOffset,
681
+ startOffset: result.start,
682
+ endOffset: result.end,
683
+ count
684
+ });
587
685
 
588
686
  });
589
687
  });
@@ -613,7 +711,15 @@ const handleOriginalBytesCoverage = (state, originalStateMap) => {
613
711
  const endMapping = decodedMappings[len - 1];
614
712
  // console.log(startMapping, endMapping);
615
713
  const startOffset = startMapping.generatedOffset;
616
- const endOffset = endMapping.generatedEndOffset || endMapping.generatedOffset;
714
+
715
+ if (!endMapping.generatedEndOffset) {
716
+ // line last one
717
+ const line = state.locator.getLine(endMapping.generatedLine + 1);
718
+ // last column
719
+ const toEndLength = line.length - endMapping.generatedColumn;
720
+ endMapping.generatedEndOffset = endMapping.generatedOffset + toEndLength;
721
+ }
722
+ const endOffset = endMapping.generatedEndOffset;
617
723
 
618
724
  // console.log('===========================================================', originalState.sourcePath);
619
725
  // console.log(originalState.source.length, endMapping);
@@ -654,11 +760,22 @@ const decodeSourceMappings = (state, originalDecodedMap) => {
654
760
  });
655
761
 
656
762
  const allDecodedMappings = [];
657
- let generatedIndex = 0;
658
763
  decodedList.forEach((segments, generatedLine) => {
659
764
  let info = null;
660
765
  segments.forEach((segment) => {
766
+
767
+ // const COLUMN = 0;
768
+ // const SOURCES_INDEX = 1;
769
+ // const SOURCE_LINE = 2;
770
+ // const SOURCE_COLUMN = 3;
771
+ // const NAMES_INDEX = 4;
661
772
  const [generatedColumn, sourceIndex, originalLine, originalColumn] = segment;
773
+ // the segment length could be 1, 4 or 5
774
+
775
+ if (typeof sourceIndex === 'undefined') {
776
+ return;
777
+ }
778
+
662
779
  const generatedOffset = generatedLocator.locationToOffset({
663
780
  // 1-base
664
781
  line: generatedLine + 1,
@@ -669,7 +786,6 @@ const decodeSourceMappings = (state, originalDecodedMap) => {
669
786
  generatedOffset,
670
787
  generatedLine,
671
788
  generatedColumn,
672
- generatedIndex,
673
789
 
674
790
  sourceIndex,
675
791
  originalLine,
@@ -677,23 +793,11 @@ const decodeSourceMappings = (state, originalDecodedMap) => {
677
793
  };
678
794
 
679
795
  allDecodedMappings.push(info);
680
- generatedIndex += 1;
681
-
682
- if (typeof sourceIndex === 'undefined') {
683
- return;
684
- }
685
796
 
686
797
  originalDecodedMap.get(sourceIndex).push(info);
687
798
 
688
799
  });
689
800
 
690
- // line last one
691
- if (info) {
692
- const line = generatedLocator.getLine(info.generatedLine + 1);
693
- // last column
694
- info.generatedEndOffset = info.generatedOffset + (line.length - info.generatedColumn);
695
- }
696
-
697
801
  });
698
802
 
699
803
  // defaults to sort by generated offset, not need sort
@@ -782,9 +886,11 @@ const initOriginalList = (state, originalDecodedMap, options) => {
782
886
  bytes: [],
783
887
  functions: [],
784
888
  branches: [],
889
+ statements: [],
785
890
  astInfo: {
786
891
  functions: [],
787
- branches: []
892
+ branches: [],
893
+ statements: []
788
894
  },
789
895
  // coverage data
790
896
  v8Data: {}
@@ -837,6 +943,7 @@ const generateCoverageForDist = (state) => {
837
943
 
838
944
  handleFunctionsCoverage(state);
839
945
  handleBranchesCoverage(state);
946
+ handleStatementsCoverage(state);
840
947
  handleBytesCoverage(state);
841
948
 
842
949
  };
@@ -868,12 +975,14 @@ const unpackSourceMap = (state, options) => {
868
975
  // handle functions before handle original state functions
869
976
  handleOriginalFunctionsCoverage(state, originalStateMap);
870
977
  handleOriginalBranchesCoverage(state, originalStateMap);
978
+ handleOriginalStatementsCoverage(state, originalStateMap);
871
979
 
872
980
  // handle lines info before handle ranges to update line count
873
981
  originalStateMap.forEach((originalState) => {
874
982
 
875
983
  handleFunctionsCoverage(originalState);
876
984
  handleBranchesCoverage(originalState);
985
+ handleStatementsCoverage(originalState);
877
986
 
878
987
  // if (originalState.sourcePath.endsWith('demo.js')) {
879
988
  // console.log('=================================', originalState.sourcePath);
@@ -881,7 +990,7 @@ const unpackSourceMap = (state, options) => {
881
990
 
882
991
  });
883
992
 
884
- // handle ranges after lines ready
993
+ // handle bytes ranges
885
994
  handleOriginalBytesCoverage(state, originalStateMap);
886
995
 
887
996
  // collect coverage for original list
@@ -892,7 +1001,7 @@ const unpackSourceMap = (state, options) => {
892
1001
  const unpackDistFile = (item, state, options) => {
893
1002
 
894
1003
  if (state.sourceMap) {
895
- if (Util.loggingType === 'debug') {
1004
+ if (Util.isDebug()) {
896
1005
  // js self
897
1006
  item.debug = true;
898
1007
  generateCoverageForDist(state);
@@ -1197,7 +1306,7 @@ const convertV8List = (v8list, options) => {
1197
1306
  if (js) {
1198
1307
  coverageList = filterCoverageList(item);
1199
1308
  // remove original functions
1200
- if (Util.loggingType !== 'debug') {
1309
+ if (!Util.isDebug()) {
1201
1310
  delete item.functions;
1202
1311
  }
1203
1312
  astInfo = getJsAstInfo(item, coverageList);
@@ -1205,11 +1314,12 @@ const convertV8List = (v8list, options) => {
1205
1314
  // convent css covered ranges to rules ranges and include uncovered ranges
1206
1315
  astInfo = getCssAstInfo(item, coverageList);
1207
1316
  // remove original ranges
1208
- if (Util.loggingType !== 'debug') {
1317
+ if (!Util.isDebug()) {
1209
1318
  delete item.ranges;
1210
1319
  }
1211
1320
  }
1212
1321
 
1322
+ // console.log(sourcePath, astInfo.statements.length);
1213
1323
  // ============================
1214
1324
 
1215
1325
  // current file and it's sources from sourceMap
@@ -1226,6 +1336,7 @@ const convertV8List = (v8list, options) => {
1226
1336
  bytes: [],
1227
1337
  functions: [],
1228
1338
  branches: [],
1339
+ statements: [],
1229
1340
  astInfo,
1230
1341
  // for sub source files
1231
1342
  coverageList,