monocart-coverage-reports 2.0.7 → 2.0.9

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.
@@ -1,3 +1,23 @@
1
+ // https://github.com/demurgos/v8-coverage
2
+ /**
3
+ * @ranges is always non-empty. The first range is called the "root range".
4
+ * @isBlockCoverage indicates if the function has block coverage information
5
+ * @false means that there is a single range and its count is the number of times the function was called.
6
+ * @true means that the ranges form a tree of blocks representing how many times each statement or expression inside was executed.
7
+ * It detects skipped or repeated statements. The root range counts the number of function calls.
8
+ * @functionName can be an empty string. This is common for the FunctionCov representing the whole module.
9
+ */
10
+ // https://github.com/bcoe/v8-coverage
11
+ /**
12
+ * @ranges is always non-empty. The first range is called the "root range".
13
+ * @isBlockCoverage indicates if the function has block coverage information.
14
+ If this is false, it usually means that the functions was never called.
15
+ It seems to be equivalent to ranges.length === 1 && ranges[0].count === 0.
16
+ * @functionName can be an empty string. This is common for the FunctionCov representing the whole module.
17
+ */
18
+
19
+ // if you have a line of code that says `var x= 10; console.log(x);` that's one line and 2 statements.
20
+
1
21
  const path = require('path');
2
22
 
3
23
  const Util = require('../utils/util.js');
@@ -7,6 +27,7 @@ const decodeMappings = require('../utils/decode-mappings.js');
7
27
  const { Locator } = require('monocart-formatter/node');
8
28
  const findOriginalRange = require('./find-original-range.js');
9
29
  const { getJsAstInfo, getCssAstInfo } = require('./ast.js');
30
+ const { getIgnoredRanges } = require('./ignore.js');
10
31
 
11
32
  const { dedupeCountRanges } = require('../utils/dedupe.js');
12
33
  const { getSourceType, initSourceMapSourcePath } = require('../utils/source-path.js');
@@ -14,6 +35,120 @@ const { getSourceType, initSourceMapSourcePath } = require('../utils/source-path
14
35
  const InfoLine = require('./info-line.js');
15
36
  const InfoBranch = require('./info-branch.js');
16
37
  const InfoFunction = require('./info-function.js');
38
+ const findInRanges = require('./find-in-ranges.js');
39
+
40
+ // ========================================================================================================
41
+
42
+ const handleIgnoredRanges = (list, ignoredRanges) => {
43
+ list.forEach((item) => {
44
+ if (item.count > 0) {
45
+ return;
46
+ }
47
+ const range = findInRanges(item.start, item.end, ignoredRanges);
48
+ if (range) {
49
+ // console.log(item, range);
50
+ item.ignored = true;
51
+ }
52
+ });
53
+ };
54
+
55
+ // ========================================================================================================
56
+
57
+ const updateLinesCount = (bytes, locator, lineMap) => {
58
+ bytes.forEach((range) => {
59
+
60
+ const {
61
+ start, end, count, ignored
62
+ } = range;
63
+
64
+ const sLoc = locator.offsetToLocation(start);
65
+ const eLoc = locator.offsetToLocation(end);
66
+
67
+ // update lines coverage
68
+ const lines = Util.getRangeLines(sLoc, eLoc);
69
+
70
+ lines.forEach((it) => {
71
+ const line = lineMap.get(it.line);
72
+ if (!line) {
73
+ return;
74
+ }
75
+
76
+ // from outside into inside, uncovered is certain
77
+ // default is covered
78
+ if (it.entire) {
79
+ line.covered = count > 0;
80
+ line.count = count;
81
+
82
+ if (ignored) {
83
+ if (!line.covered) {
84
+ line.ignored = true;
85
+ }
86
+ }
87
+
88
+ } else {
89
+
90
+ if (!ignored) {
91
+ if (count > 0) {
92
+ line.count = count;
93
+ } else {
94
+ // not covered if any count = 0
95
+ line.covered = false;
96
+ }
97
+ }
98
+
99
+ }
100
+
101
+ // if (!line.history) {
102
+ // line.history = [];
103
+ // }
104
+ // line.history.push(`${it.entire}-${count}`);
105
+
106
+ });
107
+
108
+ });
109
+
110
+ // if (state.sourcePath.endsWith('component.js')) {
111
+ // console.log('===========================================', state.sourcePath);
112
+ // }
113
+
114
+ };
115
+
116
+ const handleLinesCoverage = (bytes, locator) => {
117
+
118
+ const lines = [];
119
+ // line 1 based
120
+ const lineMap = new Map();
121
+
122
+ // init lines
123
+ let blankCount = 0;
124
+ let commentCount = 0;
125
+
126
+ locator.lines.forEach((it) => {
127
+ // exclude blank and comment
128
+ if (it.blank) {
129
+ blankCount += 1;
130
+ return;
131
+ }
132
+ if (it.comment) {
133
+ commentCount += 1;
134
+ return;
135
+ }
136
+ // line 1-base
137
+ const line = it.line + 1;
138
+ // default count to 1, both js and css
139
+ const lineInfo = new InfoLine(line, it.length, 1);
140
+ lineMap.set(line, lineInfo);
141
+ lines.push(lineInfo);
142
+ });
143
+
144
+ updateLinesCount(bytes, locator, lineMap);
145
+
146
+ return {
147
+ lines,
148
+ blankCount,
149
+ commentCount
150
+ };
151
+ };
17
152
 
18
153
  // ========================================================================================================
19
154
 
@@ -25,6 +160,10 @@ const calculateV8Functions = (functions) => {
25
160
  };
26
161
 
27
162
  functions.forEach((fn) => {
163
+ if (fn.ignored) {
164
+ return;
165
+ }
166
+
28
167
  v8Functions.total += 1;
29
168
  if (fn.count > 0) {
30
169
  v8Functions.covered += 1;
@@ -41,12 +180,13 @@ const calculateV8Branches = (branches) => {
41
180
  };
42
181
 
43
182
  branches.forEach((branch) => {
44
- branch.locations.forEach((location) => {
45
- v8Branches.total += 1;
46
- if (location.count > 0) {
47
- v8Branches.covered += 1;
48
- }
49
- });
183
+ if (branch.ignored) {
184
+ return;
185
+ }
186
+ v8Branches.total += 1;
187
+ if (branch.count > 0) {
188
+ v8Branches.covered += 1;
189
+ }
50
190
  });
51
191
 
52
192
  return v8Branches;
@@ -61,6 +201,10 @@ const calculateV8Lines = (lines, blankCount, commentCount) => {
61
201
  };
62
202
 
63
203
  lines.forEach((ln) => {
204
+ if (ln.ignored) {
205
+ // console.log(ln);
206
+ return;
207
+ }
64
208
  v8Lines.total += 1;
65
209
  // full line covered
66
210
  if (ln.covered) {
@@ -71,44 +215,7 @@ const calculateV8Lines = (lines, blankCount, commentCount) => {
71
215
  return v8Lines;
72
216
  };
73
217
 
74
- const createEmptyCoverageInfo = () => {
75
-
76
- // data for v8 UI
77
- const data = {
78
- bytes: [],
79
- functions: [],
80
- branches: []
81
- };
82
-
83
- const branches = [];
84
-
85
- const functions = [];
86
-
87
- const lines = [];
88
- // line 1 based
89
- const lineMap = new Map();
90
-
91
- const blankCount = 0;
92
- const commentCount = 0;
93
-
94
-
95
- return {
96
- // v8
97
- data,
98
-
99
- // istanbul
100
- branches,
101
-
102
- functions,
103
-
104
- lines,
105
- lineMap,
106
- blankCount,
107
- commentCount
108
-
109
- };
110
- };
111
-
218
+ // ========================================================================================================
112
219
  // istanbul coverage format
113
220
  /**
114
221
  * * `path` - the file path for which coverage is being tracked
@@ -119,32 +226,76 @@ const createEmptyCoverageInfo = () => {
119
226
  * * `f` - hit count for functions
120
227
  * * `b` - hit count for branches
121
228
  */
122
- const collectFileCoverage = (item, coverageInfo, state) => {
229
+ const collectFileCoverage = (item, state, coverageData, options) => {
123
230
 
124
231
  const { sourcePath } = item;
125
-
126
232
  const {
127
- // v8
128
- data,
129
-
130
- // istanbul
233
+ bytes,
234
+ functions,
131
235
  branches,
236
+ locator
237
+ } = state;
132
238
 
133
- functions,
239
+ // ==========================================
240
+ // v8 data
241
+ const data = {
242
+ bytes: dedupeCountRanges(bytes),
243
+ functions: [],
244
+ branches: []
245
+ };
134
246
 
135
- lines,
136
- blankCount,
137
- commentCount
247
+ // ==========================================
248
+ // ignore
249
+ const ignoredRanges = getIgnoredRanges(locator, options);
250
+ if (ignoredRanges) {
251
+
252
+ // data bytes is start/end/count object
253
+ handleIgnoredRanges(data.bytes, ignoredRanges);
254
+
255
+ // functions is InfoFunction start/end/count instance
256
+ handleIgnoredRanges(functions, ignoredRanges);
257
+
258
+ // branches is InfoBranch start/end/count instance
259
+ handleIgnoredRanges(branches, ignoredRanges);
260
+
261
+ // branch locations start/end/count object
262
+ branches.forEach((group) => {
263
+ if (group.ignored) {
264
+ // all branch group ignored
265
+ group.locations.forEach((it) => {
266
+ it.ignored = true;
267
+ });
268
+ } else {
269
+ handleIgnoredRanges(group.locations, ignoredRanges);
270
+ }
271
+ });
272
+
273
+ // console.log(ignoredRanges);
274
+
275
+ }
276
+
277
+ data.functions = functions.map((info) => {
278
+ return info.getRange();
279
+ });
280
+
281
+ // branch group with locations to flat branches
282
+ data.branches = branches.map((info) => {
283
+ return info.getRanges();
284
+ }).flat();
138
285
 
139
- } = coverageInfo;
286
+ // ==========================================
287
+ // lines
288
+ // after bytes with ignored, before calculateV8Lines
289
+ const {
290
+ lines, blankCount, commentCount
291
+ } = handleLinesCoverage(data.bytes, locator);
140
292
 
141
293
  // ==========================================
142
- // v8
143
- data.bytes = dedupeCountRanges(data.bytes);
294
+ // v8 data and summary
144
295
  item.data = data;
145
296
  item.summary = {
146
- functions: calculateV8Functions(functions),
147
- branches: calculateV8Branches(branches),
297
+ functions: calculateV8Functions(data.functions),
298
+ branches: calculateV8Branches(data.branches),
148
299
  lines: calculateV8Lines(lines, blankCount, commentCount)
149
300
  };
150
301
 
@@ -162,296 +313,288 @@ const collectFileCoverage = (item, coverageInfo, state) => {
162
313
  b: {}
163
314
  };
164
315
 
165
- lines.forEach((line, index) => {
316
+ lines.filter((it) => !it.ignored).forEach((line, index) => {
166
317
  istanbulCoverage.statementMap[`${index}`] = line.generate();
167
318
  istanbulCoverage.s[`${index}`] = line.count;
168
319
  });
169
320
 
170
- functions.forEach((fn, index) => {
171
- istanbulCoverage.fnMap[`${index}`] = fn.generate();
321
+ functions.filter((it) => !it.ignored).forEach((fn, index) => {
322
+ istanbulCoverage.fnMap[`${index}`] = fn.generate(locator);
172
323
  istanbulCoverage.f[`${index}`] = fn.count;
173
324
  });
174
325
 
175
- branches.forEach((branch, index) => {
176
- istanbulCoverage.branchMap[`${index}`] = branch.generate();
177
- istanbulCoverage.b[`${index}`] = branch.generateCounts();
326
+ branches.filter((it) => !it.ignored).forEach((branch, index) => {
327
+ const { map, counts } = branch.generate(locator);
328
+ istanbulCoverage.branchMap[`${index}`] = map;
329
+ istanbulCoverage.b[`${index}`] = counts;
178
330
  });
179
331
 
180
332
  // append to dist file state
181
- state.coverageData[sourcePath] = istanbulCoverage;
333
+ coverageData[sourcePath] = istanbulCoverage;
182
334
 
183
335
  };
184
336
 
185
337
  // ========================================================================================================
186
338
 
187
- const updateLineCoverage = (start, end, count, lineMap, locator) => {
188
- const sLoc = locator.offsetToLocation(start);
189
- const eLoc = locator.offsetToLocation(end);
190
-
191
- // update lines coverage
192
- const lines = Util.getRangeLines(sLoc, eLoc);
193
-
194
- lines.forEach((it) => {
195
- const line = lineMap.get(it.line);
196
- if (!line) {
197
- return;
198
- }
199
-
200
- // from outside into inside, uncovered is certain
201
- // default is covered
202
- if (it.entire) {
203
- line.covered = count > 0;
204
- line.count = count;
205
- } else {
206
- if (count > 0) {
207
- line.count = count;
208
- } else {
209
- // not covered if any count = 0
210
- line.covered = false;
211
- }
212
- }
213
-
214
- // if (!line.history) {
215
- // line.history = [];
216
- // }
217
- // line.history.push(`${it.entire}-${count}`);
218
-
219
- });
220
-
221
- // if (state.sourcePath.endsWith('component.js')) {
222
- // console.log('===========================================', state.sourcePath);
223
- // console.log(coverageInfo.lines);
224
- // }
225
- };
226
-
227
- // https://github.com/demurgos/v8-coverage
228
- /**
229
- * @ranges is always non-empty. The first range is called the "root range".
230
- * @isBlockCoverage indicates if the function has block coverage information
231
- * @false means that there is a single range and its count is the number of times the function was called.
232
- * @true means that the ranges form a tree of blocks representing how many times each statement or expression inside was executed.
233
- * It detects skipped or repeated statements. The root range counts the number of function calls.
234
- *
235
- * @functionName can be an empty string. This is common for the FunctionCov representing the whole module.
236
- */
237
- // if you have a line of code that says `var x= 10; console.log(x);` that's one line and 2 statements.
238
-
239
- const addJsLineCoverage = (state, range) => {
240
-
241
- const { locator, coverageInfo } = state;
242
-
243
- const { data, lineMap } = coverageInfo;
244
-
339
+ const addJsBytesCoverage = (state, range) => {
245
340
  const {
246
341
  startOffset, endOffset, count
247
342
  } = range;
248
-
249
343
  // add bytes range
250
- data.bytes.push({
251
- // index,
344
+ state.bytes.push({
252
345
  start: startOffset,
253
346
  end: endOffset,
254
347
  count
255
348
  });
349
+ };
256
350
 
257
- updateLineCoverage(startOffset, endOffset, count, lineMap, locator);
258
-
351
+ const addCssBytesCoverage = (state, range) => {
352
+ const {
353
+ start, end, count
354
+ } = range;
355
+ // add css bytes range, already start, end
356
+ state.bytes.push({
357
+ start,
358
+ end,
359
+ count
360
+ });
259
361
  };
260
362
 
261
- const addCssLineCoverage = (state, range) => {
363
+ // ========================================================================================================
262
364
 
263
- const { coverageInfo, locator } = state;
365
+ const handleFunctionsCoverage = (state) => {
264
366
 
265
- const { lineMap, data } = coverageInfo;
367
+ // functions only for js
368
+ if (!state.js) {
369
+ return;
370
+ }
266
371
 
267
- const {
268
- start, end, count
269
- } = range;
372
+ const { functions, astInfo } = state;
373
+ 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);
379
+ });
270
380
 
271
- // add bytes range
272
- data.bytes.push(range);
381
+ };
273
382
 
274
- updateLineCoverage(start, end, count, lineMap, locator);
383
+ const handleBranchesCoverage = (state) => {
384
+
385
+ // functions only for js
386
+ if (!state.js) {
387
+ return;
388
+ }
389
+
390
+ const { branches, astInfo } = state;
391
+ 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);
397
+ });
275
398
 
276
399
  };
277
400
 
278
- // ========================================================================================================
401
+ const handleBytesCoverage = (state) => {
402
+
403
+ const { js, coverageList } = state;
404
+
405
+ if (js) {
406
+ coverageList.forEach((block) => {
407
+ block.ranges.forEach((range) => {
408
+ addJsBytesCoverage(state, range);
409
+ });
410
+ });
411
+ } else {
412
+ coverageList.forEach((range) => {
413
+ addCssBytesCoverage(state, range);
414
+ });
415
+ }
279
416
 
280
- const updateOffsetToLocation = (locator, loc) => {
281
- const sLoc = locator.offsetToLocation(loc.start);
282
- loc.start = {
283
- line: sLoc.line,
284
- column: sLoc.column
285
- };
286
- const eLoc = locator.offsetToLocation(loc.end);
287
- loc.end = {
288
- line: eLoc.line,
289
- column: eLoc.column
290
- };
291
417
  };
292
418
 
293
- const handleFunctionsCoverage = (state) => {
419
+ // ========================================================================================================
420
+
421
+ const handleOriginalFunctionsCoverage = (state, originalMap) => {
294
422
 
295
423
  // functions only for js
296
424
  if (!state.js) {
297
- // use css rules data for functions
298
425
  return;
299
426
  }
300
427
 
301
- const {
302
- locator, coverageInfo, astInfo
303
- } = state;
304
-
305
- const v8Functions = coverageInfo.data.functions;
306
- const istanbulFunctions = coverageInfo.functions;
428
+ // console.log(state.astInfo.functions);
307
429
 
308
- astInfo.functions.forEach((it) => {
430
+ // function count
431
+ state.astInfo.functions.forEach((it) => {
309
432
  const {
310
- start, end, functionName, count
433
+ start, end, wrap
311
434
  } = it;
312
435
 
313
- v8Functions.push({
314
- start,
315
- end,
316
- count
317
- });
436
+ // remove webpack wrap functions for functions count, not for ranges here
437
+ if (wrap) {
438
+ return;
439
+ }
318
440
 
319
- const loc = {
320
- start,
321
- end
441
+ // rename to startOffset and endOffset
442
+ const range = {
443
+ startOffset: start,
444
+ endOffset: end
322
445
  };
323
- updateOffsetToLocation(locator, loc);
324
- const functionInfo = new InfoFunction(loc, count, functionName);
325
- istanbulFunctions.push(functionInfo);
326
- });
327
446
 
328
- // if (state.sourcePath.endsWith('store.js')) {
329
- // console.log('==========================================================');
330
- // console.log(astInfo.functions);
331
- // console.log(functions);
332
- // }
447
+ const result = findOriginalRange(range, state, originalMap);
448
+ if (result.error) {
449
+ return;
450
+ }
451
+ const { originalRange, originalState } = result;
452
+
453
+ // add back to original ast
454
+ originalState.astInfo.functions.push({
455
+ ... it,
456
+ generatedStart: start,
457
+ generatedEnd: end,
458
+ start: originalRange.startOffset,
459
+ end: originalRange.endOffset
460
+ });
461
+
462
+ // if (originalState.sourcePath.endsWith('store.js')) {
463
+ // console.log('==========================================================');
464
+ // console.log(it, result.startMapping, result.endMapping);
465
+ // }
466
+
467
+ });
333
468
 
334
469
  };
335
470
 
336
- const handleBranchesCoverage = (state) => {
471
+ const handleOriginalBranchesCoverage = (state, originalMap) => {
337
472
 
338
- // functions only for js
473
+ // branches only for js
339
474
  if (!state.js) {
340
475
  return;
341
476
  }
342
477
 
343
- const {
344
- locator, coverageInfo, astInfo
345
- } = state;
478
+ // console.log(state.astInfo.branches);
346
479
 
347
- const v8Branches = coverageInfo.data.branches;
348
- const isTanbulBranches = coverageInfo.branches;
349
- astInfo.branches.forEach((it) => {
480
+ // function count
481
+ state.astInfo.branches.forEach((it) => {
350
482
 
351
- const branchType = it.type;
352
- const branchLoc = {
353
- ... it.loc
483
+ const { type, locations } = it;
484
+
485
+ // rename to startOffset and endOffset
486
+ const bRange = {
487
+ startOffset: it.start,
488
+ endOffset: it.end
354
489
  };
355
- updateOffsetToLocation(locator, branchLoc);
356
490
 
357
- // locations
358
- // [ { start:{line,column}, end:{line,column}, count }, ...]
359
- const locations = it.locations.map((oLoc) => {
491
+ // start
492
+ const result = findOriginalRange(bRange, state, originalMap);
493
+ if (result.error) {
494
+ // not in the original files
495
+ return;
496
+ }
497
+ const { originalRange, originalState } = result;
498
+
499
+ const groupStart = originalRange.startOffset;
500
+ const groupEnd = originalRange.endOffset;
501
+
502
+ let hasError;
503
+ const newLocations = locations.map((oLoc) => {
504
+
360
505
  const newLoc = {
361
506
  ... oLoc
362
507
  };
508
+
363
509
  if (newLoc.none) {
510
+ newLoc.start = groupStart;
511
+ newLoc.end = groupEnd;
512
+ return newLoc;
513
+ }
364
514
 
365
- // the branch count is not very accurate
366
- v8Branches.push({
367
- start: it.loc.start,
368
- end: it.loc.end,
369
- count: oLoc.count,
370
- none: true
371
- });
515
+ const { start, end } = newLoc;
516
+
517
+ const lRange = {
518
+ startOffset: start,
519
+ endOffset: end
520
+ };
521
+ const res = findOriginalRange(lRange, state, originalMap);
522
+ if (res.error) {
523
+ // It should not happen unless it is minify files, the SourceMap has some order problems
524
+
525
+ 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}`);
372
530
 
373
531
  return newLoc;
374
532
  }
375
533
 
376
- // the branch count is not very accurate
377
- v8Branches.push({
378
- start: oLoc.start,
379
- end: oLoc.end,
380
- count: oLoc.count
381
- });
534
+ // mapping to new range
535
+ const oRage = res.originalRange;
536
+ newLoc.start = oRage.startOffset;
537
+ newLoc.end = oRage.endOffset;
382
538
 
383
- updateOffsetToLocation(locator, newLoc);
384
539
  return newLoc;
385
540
  });
386
541
 
387
- const branchInfo = new InfoBranch(branchLoc, locations, branchType);
388
- isTanbulBranches.push(branchInfo);
389
- });
390
-
391
-
392
- };
393
-
394
- const handleLinesCoverage = (state) => {
395
-
396
- const { locator, coverageInfo } = state;
397
-
398
- const lines = coverageInfo.lines;
399
- const lineMap = coverageInfo.lineMap;
400
-
401
- // init lines
402
- let blankCount = 0;
403
- let commentCount = 0;
404
-
405
- locator.lines.forEach((it) => {
406
- // exclude blank and comment
407
- if (it.blank) {
408
- blankCount += 1;
409
- return;
410
- }
411
- if (it.comment) {
412
- commentCount += 1;
542
+ // ignored group when found error
543
+ if (hasError) {
413
544
  return;
414
545
  }
415
- // line 1-base
416
- const line = it.line + 1;
417
- // default count to 1, both js and css
418
- const lineInfo = new InfoLine(line, it.length, 1);
419
- lineMap.set(line, lineInfo);
420
- lines.push(lineInfo);
546
+
547
+ // add back to original ast
548
+ originalState.astInfo.branches.push({
549
+ type,
550
+ start: groupStart,
551
+ end: groupEnd,
552
+ locations: newLocations
553
+ });
554
+
421
555
  });
422
556
 
423
- coverageInfo.blankCount = blankCount;
424
- coverageInfo.commentCount = commentCount;
425
557
  };
426
558
 
427
- const handleRangesCoverage = (state) => {
559
+ const handleOriginalBytesCoverage = (state, originalMap) => {
428
560
 
429
561
  const { js, coverageList } = state;
430
562
 
563
+ // const time_start_mapping = Date.now();
431
564
  if (js) {
565
+ // v8 coverage
432
566
  coverageList.forEach((block) => {
433
- block.ranges.forEach((range) => {
434
- addJsLineCoverage(state, range);
435
- });
436
- });
567
+ block.ranges.forEach((range, index) => {
437
568
 
438
- } else {
439
- coverageList.forEach((range) => {
440
- addCssLineCoverage(state, range);
441
- });
442
- }
569
+ // remove wrap functions for original files
570
+ if (range.wrap) {
571
+ // console.log(range);
572
+ return;
573
+ }
443
574
 
444
- };
575
+ const result = findOriginalRange(range, state, originalMap);
576
+ if (result.error) {
577
+ return;
578
+ }
445
579
 
446
- const generateCoverageForDist = (item, state) => {
580
+ const { originalRange, originalState } = result;
581
+ addJsBytesCoverage(originalState, originalRange);
447
582
 
448
- // handle coverage
449
- handleFunctionsCoverage(state);
450
- handleBranchesCoverage(state);
451
- handleLinesCoverage(state);
452
- handleRangesCoverage(state);
583
+ // if (originalRange.startOffset === 110 && originalRange.endOffset === 271) {
584
+ // console.log('===============================', originalState.sourcePath);
585
+ // console.log(result.startMapping, result.endMapping);
586
+ // }
587
+
588
+ });
589
+ });
590
+
591
+ } else {
592
+ // support css later
593
+ // current css no sourceMap, so never come in
594
+ // coverageList.forEach((range) => {
453
595
 
454
- collectFileCoverage(item, state.coverageInfo, state);
596
+ // });
597
+ }
455
598
 
456
599
  };
457
600
 
@@ -548,6 +691,8 @@ const getOriginalDecodedMappings = (originalDecodedMap, sourceIndex, locator) =>
548
691
  return decodedMappings;
549
692
  };
550
693
 
694
+ // ========================================================================================================
695
+
551
696
  const initOriginalList = (state, originalDecodedMap, options) => {
552
697
 
553
698
  // source filter
@@ -597,7 +742,10 @@ const initOriginalList = (state, originalDecodedMap, options) => {
597
742
  source: sourceContent,
598
743
  locator,
599
744
  decodedMappings,
600
- coverageInfo: createEmptyCoverageInfo(),
745
+ // coverage info
746
+ bytes: [],
747
+ functions: [],
748
+ branches: [],
601
749
  astInfo: {
602
750
  functions: [],
603
751
  branches: []
@@ -610,22 +758,24 @@ const initOriginalList = (state, originalDecodedMap, options) => {
610
758
  return originalMap;
611
759
  };
612
760
 
613
- const collectOriginalList = (item, state, originalMap) => {
761
+ const collectOriginalList = (item, state, originalMap, options) => {
614
762
 
615
763
  const { fileUrls, sourceMap } = state;
616
764
  const distFile = sourceMap.file || path.basename(item.sourcePath);
617
765
 
618
766
  // collect original files
619
767
  const sourceList = [];
768
+
620
769
  originalMap.forEach((originalState) => {
621
770
 
622
771
  const {
623
- js, type, sourcePath, source, coverageInfo
772
+ js, type, sourcePath, source
624
773
  } = originalState;
625
774
 
626
775
  // add file item
627
776
  const url = fileUrls[sourcePath] || sourcePath;
628
- const id = Util.calculateSha1(url + source);
777
+ // add dist for id
778
+ const id = Util.calculateSha1(distFile + url + source);
629
779
 
630
780
  const sourceItem = {
631
781
  url,
@@ -637,8 +787,8 @@ const collectOriginalList = (item, state, originalMap) => {
637
787
  source
638
788
  };
639
789
 
640
- // generate coverage, coverageInfo for current file, state for dist file
641
- collectFileCoverage(sourceItem, coverageInfo, state);
790
+ // generate coverage for current file, state for dist file
791
+ collectFileCoverage(sourceItem, originalState, state.coverageData, options);
642
792
 
643
793
  sourceList.push(sourceItem);
644
794
  });
@@ -646,184 +796,15 @@ const collectOriginalList = (item, state, originalMap) => {
646
796
  return sourceList;
647
797
  };
648
798
 
649
- // =======================================================================================
650
-
651
- const handleOriginalFunctionsCoverage = (state, originalMap) => {
652
-
653
- // functions only for js
654
- if (!state.js) {
655
- return;
656
- }
657
-
658
- // console.log(state.astInfo.functions);
659
-
660
- // function count
661
- state.astInfo.functions.forEach((it) => {
662
- const {
663
- start, end, wrap
664
- } = it;
665
-
666
- // remove webpack wrap functions for functions count, not for ranges here
667
- if (wrap) {
668
- return;
669
- }
670
-
671
- // rename to startOffset and endOffset
672
- const range = {
673
- startOffset: start,
674
- endOffset: end
675
- };
676
-
677
- const result = findOriginalRange(range, state, originalMap);
678
- if (result.error) {
679
- return;
680
- }
681
- const { originalRange, originalState } = result;
682
-
683
- // add back to original ast
684
- originalState.astInfo.functions.push({
685
- ... it,
686
- generatedStart: start,
687
- generatedEnd: end,
688
- start: originalRange.startOffset,
689
- end: originalRange.endOffset
690
- });
691
-
692
- // if (originalState.sourcePath.endsWith('store.js')) {
693
- // console.log('==========================================================');
694
- // console.log(it, result.startMapping, result.endMapping);
695
- // }
696
-
697
- });
698
-
699
- };
700
-
701
- const handleOriginalBranchesCoverage = (state, originalMap) => {
702
-
703
- // branches only for js
704
- if (!state.js) {
705
- return;
706
- }
707
-
708
- // console.log(state.astInfo.branches);
709
-
710
- // function count
711
- state.astInfo.branches.forEach((it) => {
712
-
713
- const {
714
- type, loc, locations
715
- } = it;
716
-
717
- // rename to startOffset and endOffset
718
- const bRange = {
719
- startOffset: loc.start,
720
- endOffset: loc.end
721
- };
722
-
723
- // start
724
- const result = findOriginalRange(bRange, state, originalMap);
725
- if (result.error) {
726
- // not in the original files
727
- return;
728
- }
729
- const { originalRange, originalState } = result;
730
-
731
- const newBranchLoc = {
732
- start: originalRange.startOffset,
733
- end: originalRange.endOffset
734
- };
735
-
736
- let hasError;
737
- const newLocations = locations.map((oLoc) => {
738
-
739
- const newLoc = {
740
- ... oLoc
741
- };
742
-
743
- if (newLoc.none) {
744
- return newLoc;
745
- }
746
-
747
- const { start, end } = newLoc;
748
-
749
- const lRange = {
750
- startOffset: start,
751
- endOffset: end
752
- };
753
- const res = findOriginalRange(lRange, state, originalMap);
754
- if (res.error) {
755
- // It should not happen unless it is minify files, the SourceMap has some order problems
756
-
757
- hasError = true;
758
-
759
- // console.log('====================================', state.sourcePath, loc);
760
- // console.log(res.errors);
761
- // Util.logError(`Not found original branch. start: ${start}, end: ${end}`);
762
-
763
- return newLoc;
764
- }
765
-
766
- const oRage = res.originalRange;
767
- newLoc.start = oRage.startOffset;
768
- newLoc.end = oRage.endOffset;
769
-
770
- return newLoc;
771
- });
772
-
773
- if (hasError) {
774
- return;
775
- }
776
-
777
- // add back to original ast
778
- originalState.astInfo.branches.push({
779
- type,
780
- loc: newBranchLoc,
781
- locations: newLocations
782
- });
783
-
784
- });
785
-
786
- };
787
-
788
- const handleOriginalRangesCoverage = (state, originalMap) => {
789
-
790
- const { js, coverageList } = state;
791
-
792
- // const time_start_mapping = Date.now();
793
- if (js) {
794
- // v8 coverage
795
- coverageList.forEach((block) => {
796
- block.ranges.forEach((range, index) => {
797
-
798
- // remove wrap functions for original files
799
- if (range.wrap) {
800
- // console.log(range);
801
- return;
802
- }
803
-
804
- const result = findOriginalRange(range, state, originalMap);
805
- if (result.error) {
806
- return;
807
- }
808
-
809
- const { originalRange, originalState } = result;
810
- addJsLineCoverage(originalState, originalRange);
811
-
812
- // if (originalRange.startOffset === 110 && originalRange.endOffset === 271) {
813
- // console.log('===============================', originalState.sourcePath);
814
- // console.log(result.startMapping, result.endMapping);
815
- // }
799
+ // ========================================================================================================
816
800
 
817
- });
818
- });
801
+ const generateCoverageForDist = (item, state, options) => {
819
802
 
820
- } else {
821
- // support css later
822
- // current css no sourceMap, so never come in
823
- // coverageList.forEach((range) => {
803
+ handleFunctionsCoverage(state);
804
+ handleBranchesCoverage(state);
805
+ handleBytesCoverage(state);
824
806
 
825
- // });
826
- }
807
+ collectFileCoverage(item, state, state.coverageData, options);
827
808
 
828
809
  };
829
810
 
@@ -860,38 +841,31 @@ const unpackSourceMap = async (item, state, options) => {
860
841
 
861
842
  // handle lines info before handle ranges to update line count
862
843
  originalMap.forEach((originalState) => {
844
+
863
845
  handleFunctionsCoverage(originalState);
864
846
  handleBranchesCoverage(originalState);
865
- handleLinesCoverage(originalState);
866
-
867
- // console.log(originalState.sourcePath, '================================');
868
- // console.log(originalState.astInfo.functions);
869
- // console.log(originalState.source.length);
870
- // console.log(originalState.coverageInfo.functions);
871
847
 
872
848
  // if (originalState.sourcePath.endsWith('demo.js')) {
873
849
  // console.log('=================================', originalState.sourcePath);
874
- // console.log(originalState.coverageInfo.lineMap);
875
850
  // }
876
851
 
877
852
  });
878
853
 
879
854
  // handle ranges after lines ready
880
- handleOriginalRangesCoverage(state, originalMap);
855
+ handleOriginalBytesCoverage(state, originalMap);
881
856
 
882
857
  // collect coverage for original list
883
- state.sourceList = collectOriginalList(item, state, originalMap);
858
+ state.sourceList = collectOriginalList(item, state, originalMap, options);
884
859
 
885
860
  };
886
861
 
887
- // ========================================================================================================
888
-
889
862
  const unpackDistFile = async (item, state, options) => {
890
863
 
891
864
  if (state.sourceMap) {
892
865
  if (Util.loggingType === 'debug') {
893
866
  // js self
894
- generateCoverageForDist(item, state);
867
+ item.debug = true;
868
+ generateCoverageForDist(item, state, options);
895
869
  } else {
896
870
  item.dedupe = true;
897
871
  }
@@ -902,7 +876,7 @@ const unpackDistFile = async (item, state, options) => {
902
876
  } else {
903
877
 
904
878
  // css/js self
905
- generateCoverageForDist(item, state);
879
+ generateCoverageForDist(item, state, options);
906
880
 
907
881
  }
908
882
 
@@ -927,7 +901,7 @@ const dedupeV8List = (v8list) => {
927
901
 
928
902
  const convertV8List = async (v8list, options) => {
929
903
 
930
- // global file sources and coverage data
904
+ // global file sources and coverage
931
905
  const fileSources = {};
932
906
  const coverageData = {};
933
907
  let sourceList = [];
@@ -956,9 +930,6 @@ const convertV8List = async (v8list, options) => {
956
930
  delete item.sourceMap;
957
931
  }
958
932
 
959
- // ============================
960
- const coverageInfo = createEmptyCoverageInfo();
961
-
962
933
  // ============================
963
934
  // move functions and ranges to coverageList
964
935
  let coverageList = [];
@@ -989,9 +960,12 @@ const convertV8List = async (v8list, options) => {
989
960
  sourceMap,
990
961
  coverageList,
991
962
  locator,
992
- coverageInfo,
963
+ // coverage info
964
+ bytes: [],
965
+ functions: [],
966
+ branches: [],
993
967
  astInfo,
994
- // for istanbul data
968
+ // for istanbul
995
969
  fileSources: {},
996
970
  coverageData: {}
997
971
  };