monocart-coverage-reports 2.8.4 → 2.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![](https://badgen.net/npm/dw/monocart-coverage-reports)](https://www.npmjs.com/package/monocart-coverage-reports)
5
5
  ![](https://img.shields.io/librariesio/github/cenfun/monocart-coverage-reports)
6
6
  ![](https://img.shields.io/github/license/cenfun/monocart-coverage-reports)
7
- ![](https://img.shields.io/github/actions/workflow/status/cenfun/monocart-coverage-reports/static.yml)
7
+ ![](https://img.shields.io/github/actions/workflow/status/cenfun/monocart-coverage-reports/ci.yml)
8
8
 
9
9
  🌐 English | [įŽ€äŊ“中文](README.zh-Hans.md)
10
10
 
@@ -506,7 +506,7 @@ const coverageOptions = {
506
506
  sourceFilter: "**/src/**"
507
507
  };
508
508
  ```
509
- Supports multiple patterns:
509
+ Support multiple patterns:
510
510
  ```js
511
511
  const coverageOptions = {
512
512
  entryFilter: {
@@ -1062,8 +1062,8 @@ const coverageOptions = {
1062
1062
  - Node.js 20+
1063
1063
  - VSCode (extensions: eslint/stylelint/vue)
1064
1064
  ```sh
1065
- npm install starfall-cli -g
1066
1065
  npm install
1066
+ npx playwright install --with-deps
1067
1067
 
1068
1068
  npm run build
1069
1069
  npm run test
@@ -1082,4 +1082,5 @@ npm run eol
1082
1082
  - [Coverage Gutters](https://github.com/ryanluker/vscode-coverage-gutters) - Display test coverage generated by lcov or xml in VSCode editor.
1083
1083
 
1084
1084
  ## Thanks
1085
- - Special thanks to [@edumserrano](https://github.com/edumserrano)
1085
+ - [@bcoe](https://github.com/bcoe)
1086
+ - [@edumserrano](https://github.com/edumserrano)
package/README.zh-Hans.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![](https://badgen.net/npm/dw/monocart-coverage-reports)](https://www.npmjs.com/package/monocart-coverage-reports)
5
5
  ![](https://img.shields.io/librariesio/github/cenfun/monocart-coverage-reports)
6
6
  ![](https://img.shields.io/github/license/cenfun/monocart-coverage-reports)
7
- ![](https://img.shields.io/github/actions/workflow/status/cenfun/monocart-coverage-reports/static.yml)
7
+ ![](https://img.shields.io/github/actions/workflow/status/cenfun/monocart-coverage-reports/ci.yml)
8
8
 
9
9
  🌐 [English](README.md) | įŽ€äŊ“中文
10
10
 
@@ -1066,8 +1066,8 @@ const coverageOptions = {
1066
1066
  - Node.js 20+
1067
1067
  - VSCode (extensions: eslint/stylelint/vue)
1068
1068
  ```sh
1069
- npm install starfall-cli -g
1070
1069
  npm install
1070
+ npx playwright install --with-deps
1071
1071
 
1072
1072
  npm run build
1073
1073
  npm run test
@@ -1086,4 +1086,5 @@ npm run eol
1086
1086
  - [Coverage Gutters](https://github.com/ryanluker/vscode-coverage-gutters) - Display test coverage generated by lcov or xml in VSCode editor.
1087
1087
 
1088
1088
  ## Thanks
1089
- - Special thanks to [@edumserrano](https://github.com/edumserrano)
1089
+ - [@bcoe](https://github.com/bcoe)
1090
+ - [@edumserrano](https://github.com/edumserrano)
@@ -63,9 +63,14 @@ const resolveSourcesContent = (data, url) => {
63
63
 
64
64
  const { sources, sourcesContent } = data;
65
65
 
66
- let failed = false;
66
+ // sources [1,2,3]
67
+ // sourcesContent could be [null, null, "content"]
68
+ // some of contents could be missed
69
+
70
+ let hasSourceContent = false;
67
71
  sources.forEach((file, i) => {
68
72
  if (typeof sourcesContent[i] === 'string') {
73
+ hasSourceContent = true;
69
74
  return;
70
75
  }
71
76
 
@@ -79,16 +84,18 @@ const resolveSourcesContent = (data, url) => {
79
84
  const content = Util.readFileSync(path.resolve(sourcePath));
80
85
  if (typeof content === 'string') {
81
86
  sourcesContent[i] = content;
87
+ hasSourceContent = true;
82
88
  return;
83
89
  }
84
90
  }
85
91
 
86
- Util.logDebug(EC.red(`failed to load source content ${file}`));
87
- failed = true;
92
+ sourcesContent[i] = '';
93
+ Util.logDebug(EC.red(`failed to load source content: ${file}`));
94
+
88
95
  });
89
96
 
90
97
 
91
- if (!failed) {
98
+ if (hasSourceContent) {
92
99
  return data;
93
100
  }
94
101
  };
@@ -121,18 +128,6 @@ const resolveSourceMap = (data, url) => {
121
128
 
122
129
  };
123
130
 
124
- const saveSourceFile = async (filePath, data) => {
125
- await Util.writeFile(filePath, JSON.stringify(data));
126
-
127
- // save source and sourcemap file for debug
128
- // https://evanw.github.io/source-map-visualization
129
- // if (data.sourceMap) {
130
- // await Util.writeFile(`${filePath}.js`, data.source);
131
- // await Util.writeFile(`${filePath}.js.map`, JSON.stringify(data.sourceMap));
132
- // }
133
-
134
- };
135
-
136
131
  const getInlineSourceMap = (content) => {
137
132
  let smc;
138
133
  try {
@@ -146,7 +141,8 @@ const getInlineSourceMap = (content) => {
146
141
 
147
142
  const collectSourceMaps = async (v8list, options) => {
148
143
 
149
- const smList = [];
144
+ const sourceList = [];
145
+ const sourcemapList = [];
150
146
  const concurrency = new Concurrency();
151
147
  for (const item of v8list) {
152
148
 
@@ -161,8 +157,8 @@ const collectSourceMaps = async (v8list, options) => {
161
157
  delete item.sourceMap;
162
158
 
163
159
  // source and sourceMap already saved
164
- const sourcePath = Util.resolveCacheSourcePath(options.cacheDir, id);
165
- if (fs.existsSync(sourcePath)) {
160
+ const { cachePath } = Util.getCacheFileInfo('source', id, options.cacheDir);
161
+ if (fs.existsSync(cachePath)) {
166
162
  continue;
167
163
  }
168
164
 
@@ -185,11 +181,11 @@ const collectSourceMaps = async (v8list, options) => {
185
181
  const smc = getInlineSourceMap(source);
186
182
  if (smc) {
187
183
  sourceData.sourceMap = resolveSourceMap(smc.sourcemap, url);
188
- smList.push({
184
+ sourcemapList.push({
189
185
  url,
190
186
  inline: true
191
187
  });
192
- await saveSourceFile(sourcePath, sourceData);
188
+ sourceList.push(sourceData);
193
189
  continue;
194
190
  }
195
191
  // from url async
@@ -197,7 +193,6 @@ const collectSourceMaps = async (v8list, options) => {
197
193
  if (sourceMapUrl) {
198
194
  concurrency.addItem({
199
195
  sourceMapUrl,
200
- sourcePath,
201
196
  sourceData
202
197
  });
203
198
  continue;
@@ -205,7 +200,7 @@ const collectSourceMaps = async (v8list, options) => {
205
200
  }
206
201
 
207
202
  // no need check sourceMap
208
- await saveSourceFile(sourcePath, sourceData);
203
+ sourceList.push(sourceData);
209
204
 
210
205
  }
211
206
 
@@ -216,15 +211,20 @@ const collectSourceMaps = async (v8list, options) => {
216
211
  const data = await loadSourceMap(sourceMapUrl);
217
212
  if (data) {
218
213
  sourceData.sourceMap = resolveSourceMap(data, url);
219
- smList.push({
214
+ sourcemapList.push({
220
215
  url,
221
216
  sourceMapUrl
222
217
  });
223
218
  }
224
- await saveSourceFile(item.sourcePath, sourceData);
219
+
220
+ sourceList.push(sourceData);
221
+
225
222
  });
226
223
 
227
- return smList;
224
+ return {
225
+ sourceList,
226
+ sourcemapList
227
+ };
228
228
 
229
229
  };
230
230
 
@@ -389,6 +389,13 @@ const checkOriginalRangeCode = (range, state, startEndMap, type) => {
389
389
  return false;
390
390
  }
391
391
 
392
+ // do not check text for `bytes`
393
+ // it could be `} ` uncovered in `try { } catch`
394
+ // instead, use `dedupeCountRanges` to accumulate count
395
+ if (type === 'bytes') {
396
+ return true;
397
+ }
398
+
392
399
  // invalid original code
393
400
  // Matches any character that is not a word character from the basic Latin alphabet.
394
401
  // Equivalent to [^A-Za-z0-9_]
@@ -400,12 +407,6 @@ const checkOriginalRangeCode = (range, state, startEndMap, type) => {
400
407
 
401
408
  // type: bytes, functions, branches, statements
402
409
 
403
- // do not check repeated range for `bytes`
404
- // instead, use `dedupeCountRanges` to accumulate count
405
- if (type === 'bytes') {
406
- return true;
407
- }
408
-
409
410
  // check repeated range
410
411
  const key = `${start}_${end}`;
411
412
  if (startEndMap.has(key)) {
@@ -1238,15 +1239,17 @@ const initJsCoverageList = (item) => {
1238
1239
  inUncoveredRange.coveredList.push(range);
1239
1240
  }
1240
1241
  }
1241
- } else {
1242
- if (count === 0) {
1243
- uncoveredBlocks.push({
1244
- ... range,
1245
- index: i,
1246
- ranges: block.ranges
1247
- });
1248
- }
1242
+ return;
1243
+ }
1244
+
1245
+ if (count === 0) {
1246
+ uncoveredBlocks.push({
1247
+ ... range,
1248
+ index: i,
1249
+ ranges: block.ranges
1250
+ });
1249
1251
  }
1252
+
1250
1253
  });
1251
1254
  });
1252
1255
 
@@ -1282,7 +1285,7 @@ const initJsCoverageList = (item) => {
1282
1285
  });
1283
1286
  }
1284
1287
 
1285
- ranges.splice.apply(ranges, args);
1288
+ ranges.splice(... args);
1286
1289
 
1287
1290
  });
1288
1291
  }
@@ -1492,6 +1495,8 @@ const convertV8List = (v8list, options) => {
1492
1495
  for (const item of v8list) {
1493
1496
  // console.log([item.id]);
1494
1497
 
1498
+ const time_start_ast = Date.now();
1499
+
1495
1500
  const {
1496
1501
  type, source, fake, sourcePath
1497
1502
  } = item;
@@ -1512,7 +1517,6 @@ const convertV8List = (v8list, options) => {
1512
1517
  }
1513
1518
 
1514
1519
  // ============================
1515
- const time_start_ast = Date.now();
1516
1520
  // move functions and ranges to coverageList
1517
1521
  let coverageList = [];
1518
1522
  let astInfo;
@@ -1531,11 +1535,14 @@ const convertV8List = (v8list, options) => {
1531
1535
  delete item.ranges;
1532
1536
  }
1533
1537
  }
1534
- Util.logTime(`- parsed ast: ${sourcePath} (${EC.cyan(Util.BSF(maxContentLength))})`, time_start_ast);
1538
+
1539
+ Util.logTime(` ┌ [convert] parsed ast: ${sourcePath} (${EC.cyan(Util.BSF(maxContentLength))})`, time_start_ast);
1535
1540
 
1536
1541
  // console.log(sourcePath, astInfo.statements.length);
1537
1542
  // ============================
1538
1543
 
1544
+ const time_start_unpack = Date.now();
1545
+
1539
1546
  // current file and it's sources from sourceMap
1540
1547
  // see const originalState
1541
1548
  const state = {
@@ -1548,7 +1555,11 @@ const convertV8List = (v8list, options) => {
1548
1555
  locator,
1549
1556
  maxContentLength,
1550
1557
  decodedMappings: [],
1551
- cacheMap: new Map(),
1558
+ rangeCache: new Map(),
1559
+ diffCache: new Map(),
1560
+
1561
+ // alignTextList: [],
1562
+
1552
1563
  // coverage info
1553
1564
  bytes: [],
1554
1565
  functions: [],
@@ -1562,19 +1573,25 @@ const convertV8List = (v8list, options) => {
1562
1573
  v8Data: item
1563
1574
  };
1564
1575
 
1565
- const time_start_unpack = Date.now();
1566
1576
  unpackDistFile(item, state, options);
1567
1577
  const unpackedFiles = EC.cyan(`${state.originalList.length} files`);
1568
- Util.logTime(`- unpacked dist: ${sourcePath} (${unpackedFiles})`, time_start_unpack);
1569
1578
 
1570
1579
  stateList.push(state);
1571
1580
 
1581
+ Util.logTime(` ┌ [convert] unpacked sourcemap: ${sourcePath} (${unpackedFiles})`, time_start_unpack);
1582
+
1572
1583
  }
1573
1584
 
1574
1585
  const time_start_convert = Date.now();
1586
+
1575
1587
  const dataList = generateV8DataList(stateList, options);
1576
1588
  const dataFiles = EC.cyan(`${dataList.v8DataList.length} files`);
1577
- Util.logTime(`- generated data list (${dataFiles})`, time_start_convert);
1589
+
1590
+ // stateList.forEach((st, i) => {
1591
+ // Util.writeFileSync(`align-text-${i}.js`, `window.gridData = ${JSON.stringify(st.alignTextList, null, 4)}`);
1592
+ // });
1593
+
1594
+ Util.logTime(` ┌ [convert] converted data list (${dataFiles})`, time_start_convert);
1578
1595
 
1579
1596
  return dataList;
1580
1597
  };
@@ -39,7 +39,16 @@ const findMapping = (list, offset) => {
39
39
 
40
40
  // ========================================================================================================
41
41
 
42
- const alignText = (gt, ot) => {
42
+ const alignText = (gt, ot, info) => {
43
+
44
+ const { diffCache } = info.state;
45
+
46
+ if (diffCache.has(gt)) {
47
+ const subMap = diffCache.get(gt);
48
+ if (subMap.has(ot)) {
49
+ return subMap.get(ot);
50
+ }
51
+ }
43
52
 
44
53
  const toList = (s) => {
45
54
  return s.split('').map((v, i) => {
@@ -115,6 +124,15 @@ const alignText = (gt, ot) => {
115
124
  mergeList(gList, oList);
116
125
  }
117
126
 
127
+ if (diffCache.has(gt)) {
128
+ const subMap = diffCache.get(gt);
129
+ subMap.set(ot, gl);
130
+ } else {
131
+ const subMap = new Map();
132
+ diffCache.set(gt, subMap);
133
+ subMap.set(ot, gl);
134
+ }
135
+
118
136
  // console.log(gl);
119
137
  return gl;
120
138
  };
@@ -136,10 +154,19 @@ const getWordEndPosition = (list, gp, direction) => {
136
154
  }
137
155
  };
138
156
 
139
- const getAlignPosition = (gt, gp, ot, direction) => {
157
+ const getAlignPosition = (info, direction) => {
158
+
159
+ const gt = info.generatedText;
160
+ const gp = info.generatedPos;
161
+ const ot = info.originalText;
162
+
163
+ // const alignTextItem = {
164
+ // gt, ot, gp
165
+ // };
166
+ // info.state.alignTextList.push(it);
140
167
 
141
168
  // there is no need to align for long text
142
- const maxLength = 500;
169
+ const maxLength = 100;
143
170
  if (gt.length > maxLength || ot.length > maxLength) {
144
171
  // console.log(gt.length, ot.length, gp);
145
172
  return;
@@ -155,16 +182,16 @@ const getAlignPosition = (gt, gp, ot, direction) => {
155
182
  // generatedText: '1;else',
156
183
  // generatedLeft: '1;'
157
184
 
158
- // generatedText: ' var id = options.base ? item[0] + options.base : item[0];\r\n',
159
- // originalText: ' var id = options.base ? item[0] + options.base : item[0];\n',
160
-
161
185
  // right matched
162
186
  // only for original first line text
163
187
 
164
188
  // exclusive
165
- const list = alignText(gt, ot);
189
+ const list = alignText(gt, ot, info);
166
190
  const item = list[gp];
167
191
  if (item && item.original) {
192
+
193
+ // alignTextItem.op = item.original.index;
194
+
168
195
  return {
169
196
  pos: item.original.index
170
197
  };
@@ -280,10 +307,15 @@ const getComparedPosition = (info, direction) => {
280
307
  }
281
308
 
282
309
  // =============================
283
- // trim right
284
- const gtt = gt.trimEnd();
285
- const ott = ot.trimEnd();
310
+ // trim
311
+
312
+ const gtt = gt.trim();
313
+ // no generated content after trim
314
+ if (!gtt) {
315
+ return;
316
+ }
286
317
 
318
+ const ott = ot.trim();
287
319
  // no original content after trim
288
320
  if (!ott) {
289
321
  return {
@@ -291,21 +323,21 @@ const getComparedPosition = (info, direction) => {
291
323
  };
292
324
  }
293
325
 
294
- // no generated content after trim
295
- if (!gtt) {
296
- return;
297
- }
298
-
299
326
  // same content
300
327
  if (gtt === ott) {
328
+ // fix indent
329
+ const blankBlock = /\S/;
330
+ const gi = gt.search(blankBlock);
331
+ const oi = ot.search(blankBlock);
332
+
301
333
  return {
302
- pos: gp
334
+ pos: gp - gi + oi
303
335
  };
304
336
  }
305
337
 
306
338
  // =============================
307
339
 
308
- return getAlignPosition(gt, gp, ot, direction);
340
+ return getAlignPosition(info, direction);
309
341
 
310
342
  };
311
343
 
@@ -325,7 +357,7 @@ const getSimilarPosition = (info, direction) => {
325
357
  }
326
358
 
327
359
  // no need comparison for fake source
328
- if (info.fake) {
360
+ if (info.state.fake) {
329
361
  return;
330
362
  }
331
363
 
@@ -388,31 +420,48 @@ const getOriginalText = (m1, m2, cache) => {
388
420
 
389
421
  const o1 = m1.originalOffset;
390
422
  const o2 = m2.originalOffset;
423
+ const sameLine = m2.originalLine === m1.originalLine;
391
424
 
392
425
  // o1 < o2: most of time
393
426
  if (o1 < o2) {
427
+
428
+ // could be in comments
429
+ // it must be wrong sourcemap, do not fix it here
430
+ // if (originalLocator.lineParser.commentParser.isComment(o1, o2)) {
431
+ // console.log('in comments', originalLocator.getSlice(o1, o2), originalLocator.offsetToLocation(o1), originalLocator.offsetToLocation(o2), cache.originalState.sourcePath);
432
+ // return {
433
+ // originalOffset: o1,
434
+ // originalText: ''
435
+ // };
436
+ // }
437
+
438
+ if (sameLine) {
439
+ return {
440
+ originalOffset: o1,
441
+ originalText: originalLocator.getSlice(o1, o2)
442
+ };
443
+ }
444
+
394
445
  // could be multiple lines for original text
395
446
  return {
396
447
  originalOffset: o1,
397
- originalText: originalLocator.getSlice(o1, o2)
448
+ originalText: originalLocator.getSlice(o1, getOriginalEndOffset(m1, cache))
398
449
  };
399
450
  }
400
451
 
401
452
  // esbuild fixing two mapping have same original
402
453
  // m1 to end line
403
454
  if (o1 === o2) {
404
- const originalEndOffset = getOriginalEndOffset(m1, cache);
405
455
  return {
406
456
  originalOffset: o1,
407
- originalText: originalLocator.getSlice(o1, originalEndOffset)
457
+ originalText: originalLocator.getSlice(o1, getOriginalEndOffset(m1, cache))
408
458
  };
409
459
  }
410
460
 
411
461
  // o1 > o2: should be wrong sourcemap
412
462
 
413
- // just reverse offsets if few cross lines
414
- const crossLines = m1.originalLine - m2.originalLine;
415
- if (crossLines < 2) {
463
+ // just reverse offsets if same line
464
+ if (sameLine) {
416
465
  return {
417
466
  originalOffset: o2,
418
467
  originalText: originalLocator.getSlice(o2, o1)
@@ -426,10 +475,9 @@ const getOriginalText = (m1, m2, cache) => {
426
475
  // }
427
476
 
428
477
  // should be wrong, ignore m2
429
- const originalEndOffset = getOriginalEndOffset(m1, cache);
430
478
  return {
431
479
  originalOffset: o1,
432
- originalText: originalLocator.getSlice(o1, originalEndOffset)
480
+ originalText: originalLocator.getSlice(o1, getOriginalEndOffset(m1, cache))
433
481
  };
434
482
 
435
483
  };
@@ -505,7 +553,7 @@ const getFixedOriginalStart = (start, mappings, state, cache) => {
505
553
  const direction = 'start';
506
554
 
507
555
  const info = {
508
- fake: state.fake,
556
+ state,
509
557
  generatedText,
510
558
  generatedPos,
511
559
  originalText,
@@ -558,7 +606,7 @@ const getFixedOriginalEnd = (end, mappings, state, cache) => {
558
606
  const direction = 'end';
559
607
 
560
608
  const info = {
561
- fake: state.fake,
609
+ state,
562
610
  offset: end,
563
611
  generatedText,
564
612
  generatedPos,
@@ -826,11 +874,11 @@ const getMappingInfo = (start, end, state) => {
826
874
 
827
875
  const findOriginalRange = (start, end, state, originalMap) => {
828
876
 
829
- const { sourcePath, cacheMap } = state;
877
+ const { sourcePath, rangeCache } = state;
830
878
 
831
879
  const key = `${start}_${end}`;
832
- if (cacheMap.has(key)) {
833
- return cacheMap.get(key);
880
+ if (rangeCache.has(key)) {
881
+ return rangeCache.get(key);
834
882
  }
835
883
 
836
884
  const createMappingError = (errors) => {
@@ -843,7 +891,7 @@ const findOriginalRange = (start, end, state, originalMap) => {
843
891
  };
844
892
 
845
893
  // cache error response
846
- cacheMap.set(key, res);
894
+ rangeCache.set(key, res);
847
895
 
848
896
  return res;
849
897
  };
@@ -884,7 +932,7 @@ const findOriginalRange = (start, end, state, originalMap) => {
884
932
  };
885
933
 
886
934
  // cache response
887
- cacheMap.set(key, res);
935
+ rangeCache.set(key, res);
888
936
 
889
937
  return res;
890
938
 
@@ -1,5 +1,5 @@
1
1
  <!DOCTYPE html>
2
- <html>
2
+ <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">