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,201 +1,201 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const EC = require('eight-colors');
|
|
4
|
-
const { fileURLToPath, pathToFileURL } = require('url');
|
|
5
|
-
const Concurrency = require('../platform/concurrency.js');
|
|
6
|
-
const { convertSourceMap } = require('../packages/monocart-coverage-vendor.js');
|
|
7
|
-
|
|
8
|
-
const Util = require('../utils/util.js');
|
|
9
|
-
|
|
10
|
-
const loadSourceMap = async (url = '') => {
|
|
11
|
-
|
|
12
|
-
if (url.startsWith('file:')) {
|
|
13
|
-
const p = fileURLToPath(url);
|
|
14
|
-
const content = Util.readFileSync(p);
|
|
15
|
-
if (!content) {
|
|
16
|
-
Util.logDebug(EC.red(`failed to load sourcemap ${p}`));
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
return JSON.parse(content);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const [err, res] = await Util.request({
|
|
23
|
-
url
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
if (err) {
|
|
27
|
-
Util.logDebug(EC.red(`${err.message} ${url}`));
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return res.data;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const getSourceMapUrl = (content, url) => {
|
|
35
|
-
|
|
36
|
-
const m = content.match(convertSourceMap.mapFileCommentRegex);
|
|
37
|
-
if (!m) {
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const comment = m.pop();
|
|
42
|
-
const r = convertSourceMap.mapFileCommentRegex.exec(comment);
|
|
43
|
-
// for some odd reason //# .. captures in 1 and /* .. */ in 2
|
|
44
|
-
const filename = r[1] || r[2];
|
|
45
|
-
|
|
46
|
-
const urlObj = Util.resolveUrl(filename, url);
|
|
47
|
-
if (urlObj) {
|
|
48
|
-
return urlObj.toString();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const mapUrl = Util.resolveUrl(filename, pathToFileURL(url).toString());
|
|
52
|
-
if (mapUrl) {
|
|
53
|
-
return mapUrl.toString();
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const resolveSourcesContent = (sources, url) => {
|
|
58
|
-
const list = [];
|
|
59
|
-
for (const file of sources) {
|
|
60
|
-
const sourceUrl = Util.resolveUrl(file, url);
|
|
61
|
-
if (sourceUrl) {
|
|
62
|
-
const sourcePath = sourceUrl.toString();
|
|
63
|
-
if (sourcePath.startsWith('file:')) {
|
|
64
|
-
const content = Util.readFileSync(path.resolve(fileURLToPath(sourcePath)));
|
|
65
|
-
list.push(content);
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
Util.logDebug(EC.red(`failed to load source content ${file}`));
|
|
70
|
-
}
|
|
71
|
-
if (list.length === sources.length) {
|
|
72
|
-
return list;
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const resolveSourceMap = (data, url) => {
|
|
77
|
-
if (!data) {
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
const {
|
|
81
|
-
sources, sourcesContent, mappings
|
|
82
|
-
} = data;
|
|
83
|
-
|
|
84
|
-
if (!sources || !mappings) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// exists sources content
|
|
89
|
-
if (sourcesContent && sourcesContent.length === sources.length) {
|
|
90
|
-
return data;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// load sources content by sources
|
|
94
|
-
const contents = resolveSourcesContent(sources, url);
|
|
95
|
-
if (contents) {
|
|
96
|
-
data.sourcesContent = contents;
|
|
97
|
-
return data;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
const saveSourceFile = async (filePath, data) => {
|
|
103
|
-
await Util.writeFile(filePath, JSON.stringify(data));
|
|
104
|
-
|
|
105
|
-
// save source and sourcemap file for debug
|
|
106
|
-
// https://evanw.github.io/source-map-visualization
|
|
107
|
-
// if (data.sourceMap) {
|
|
108
|
-
// await Util.writeFile(`${filePath}.js`, data.source);
|
|
109
|
-
// await Util.writeFile(`${filePath}.js.map`, JSON.stringify(data.sourceMap));
|
|
110
|
-
// }
|
|
111
|
-
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
const collectSourceMaps = async (v8list, options) => {
|
|
115
|
-
|
|
116
|
-
const smList = [];
|
|
117
|
-
const concurrency = new Concurrency();
|
|
118
|
-
for (const item of v8list) {
|
|
119
|
-
|
|
120
|
-
const {
|
|
121
|
-
type, url, id, source, sourceMap
|
|
122
|
-
} = item;
|
|
123
|
-
|
|
124
|
-
// source and sourceMap will be saved as separated file (could be cached)
|
|
125
|
-
// just keep functions coverage ( could be multiple times, will be merged )
|
|
126
|
-
// so remove source and sourceMap
|
|
127
|
-
delete item.source;
|
|
128
|
-
delete item.sourceMap;
|
|
129
|
-
|
|
130
|
-
// source and sourceMap already saved
|
|
131
|
-
const sourcePath = Util.resolveCacheSourcePath(options.cacheDir, id);
|
|
132
|
-
if (fs.existsSync(sourcePath)) {
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// save source and sourceMap to separated json file
|
|
137
|
-
const sourceData = {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
source,
|
|
141
|
-
sourceMap
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
// remove comments if not debug
|
|
145
|
-
if (!Util.isDebug()) {
|
|
146
|
-
sourceData.source = convertSourceMap.removeComments(source);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// check sourceMap only for js
|
|
150
|
-
if (type === 'js' && !sourceData.sourceMap) {
|
|
151
|
-
// from inline sync
|
|
152
|
-
const smc = convertSourceMap.fromSource(source);
|
|
153
|
-
if (smc) {
|
|
154
|
-
sourceData.sourceMap = resolveSourceMap(smc.sourcemap, url);
|
|
155
|
-
smList.push({
|
|
156
|
-
url,
|
|
157
|
-
inline: true
|
|
158
|
-
});
|
|
159
|
-
await saveSourceFile(sourcePath, sourceData);
|
|
160
|
-
continue;
|
|
161
|
-
}
|
|
162
|
-
// from url async
|
|
163
|
-
const sourceMapUrl = getSourceMapUrl(source, item.url);
|
|
164
|
-
if (sourceMapUrl) {
|
|
165
|
-
concurrency.addItem({
|
|
166
|
-
sourceMapUrl,
|
|
167
|
-
sourcePath,
|
|
168
|
-
sourceData
|
|
169
|
-
});
|
|
170
|
-
continue;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// no need check sourceMap
|
|
175
|
-
await saveSourceFile(sourcePath, sourceData);
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// from url concurrency
|
|
180
|
-
await concurrency.start(async (item) => {
|
|
181
|
-
const { sourceMapUrl, sourceData } = item;
|
|
182
|
-
const { url } = sourceData;
|
|
183
|
-
const data = await loadSourceMap(sourceMapUrl);
|
|
184
|
-
if (data) {
|
|
185
|
-
sourceData.sourceMap = resolveSourceMap(data, url);
|
|
186
|
-
smList.push({
|
|
187
|
-
url,
|
|
188
|
-
sourceMapUrl
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
await saveSourceFile(item.sourcePath, sourceData);
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
return smList;
|
|
195
|
-
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
module.exports = {
|
|
199
|
-
collectSourceMaps,
|
|
200
|
-
resolveSourceMap
|
|
201
|
-
};
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const EC = require('eight-colors');
|
|
4
|
+
const { fileURLToPath, pathToFileURL } = require('url');
|
|
5
|
+
const Concurrency = require('../platform/concurrency.js');
|
|
6
|
+
const { convertSourceMap } = require('../packages/monocart-coverage-vendor.js');
|
|
7
|
+
|
|
8
|
+
const Util = require('../utils/util.js');
|
|
9
|
+
|
|
10
|
+
const loadSourceMap = async (url = '') => {
|
|
11
|
+
|
|
12
|
+
if (url.startsWith('file:')) {
|
|
13
|
+
const p = fileURLToPath(url);
|
|
14
|
+
const content = Util.readFileSync(p);
|
|
15
|
+
if (!content) {
|
|
16
|
+
Util.logDebug(EC.red(`failed to load sourcemap ${p}`));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
return JSON.parse(content);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const [err, res] = await Util.request({
|
|
23
|
+
url
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
if (err) {
|
|
27
|
+
Util.logDebug(EC.red(`${err.message} ${url}`));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return res.data;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const getSourceMapUrl = (content, url) => {
|
|
35
|
+
|
|
36
|
+
const m = content.match(convertSourceMap.mapFileCommentRegex);
|
|
37
|
+
if (!m) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const comment = m.pop();
|
|
42
|
+
const r = convertSourceMap.mapFileCommentRegex.exec(comment);
|
|
43
|
+
// for some odd reason //# .. captures in 1 and /* .. */ in 2
|
|
44
|
+
const filename = r[1] || r[2];
|
|
45
|
+
|
|
46
|
+
const urlObj = Util.resolveUrl(filename, url);
|
|
47
|
+
if (urlObj) {
|
|
48
|
+
return urlObj.toString();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const mapUrl = Util.resolveUrl(filename, pathToFileURL(url).toString());
|
|
52
|
+
if (mapUrl) {
|
|
53
|
+
return mapUrl.toString();
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const resolveSourcesContent = (sources, url) => {
|
|
58
|
+
const list = [];
|
|
59
|
+
for (const file of sources) {
|
|
60
|
+
const sourceUrl = Util.resolveUrl(file, url);
|
|
61
|
+
if (sourceUrl) {
|
|
62
|
+
const sourcePath = sourceUrl.toString();
|
|
63
|
+
if (sourcePath.startsWith('file:')) {
|
|
64
|
+
const content = Util.readFileSync(path.resolve(fileURLToPath(sourcePath)));
|
|
65
|
+
list.push(content);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
Util.logDebug(EC.red(`failed to load source content ${file}`));
|
|
70
|
+
}
|
|
71
|
+
if (list.length === sources.length) {
|
|
72
|
+
return list;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const resolveSourceMap = (data, url) => {
|
|
77
|
+
if (!data) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const {
|
|
81
|
+
sources, sourcesContent, mappings
|
|
82
|
+
} = data;
|
|
83
|
+
|
|
84
|
+
if (!sources || !mappings) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// exists sources content
|
|
89
|
+
if (sourcesContent && sourcesContent.length === sources.length) {
|
|
90
|
+
return data;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// load sources content by sources
|
|
94
|
+
const contents = resolveSourcesContent(sources, url);
|
|
95
|
+
if (contents) {
|
|
96
|
+
data.sourcesContent = contents;
|
|
97
|
+
return data;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const saveSourceFile = async (filePath, data) => {
|
|
103
|
+
await Util.writeFile(filePath, JSON.stringify(data));
|
|
104
|
+
|
|
105
|
+
// save source and sourcemap file for debug
|
|
106
|
+
// https://evanw.github.io/source-map-visualization
|
|
107
|
+
// if (data.sourceMap) {
|
|
108
|
+
// await Util.writeFile(`${filePath}.js`, data.source);
|
|
109
|
+
// await Util.writeFile(`${filePath}.js.map`, JSON.stringify(data.sourceMap));
|
|
110
|
+
// }
|
|
111
|
+
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const collectSourceMaps = async (v8list, options) => {
|
|
115
|
+
|
|
116
|
+
const smList = [];
|
|
117
|
+
const concurrency = new Concurrency();
|
|
118
|
+
for (const item of v8list) {
|
|
119
|
+
|
|
120
|
+
const {
|
|
121
|
+
type, url, id, source, sourceMap
|
|
122
|
+
} = item;
|
|
123
|
+
|
|
124
|
+
// source and sourceMap will be saved as separated file (could be cached)
|
|
125
|
+
// just keep functions coverage ( could be multiple times, will be merged )
|
|
126
|
+
// so remove source and sourceMap
|
|
127
|
+
delete item.source;
|
|
128
|
+
delete item.sourceMap;
|
|
129
|
+
|
|
130
|
+
// source and sourceMap already saved
|
|
131
|
+
const sourcePath = Util.resolveCacheSourcePath(options.cacheDir, id);
|
|
132
|
+
if (fs.existsSync(sourcePath)) {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// save source and sourceMap to separated json file
|
|
137
|
+
const sourceData = {
|
|
138
|
+
id,
|
|
139
|
+
url,
|
|
140
|
+
source,
|
|
141
|
+
sourceMap
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// remove comments if not debug
|
|
145
|
+
if (!Util.isDebug()) {
|
|
146
|
+
sourceData.source = convertSourceMap.removeComments(source);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// check sourceMap only for js
|
|
150
|
+
if (type === 'js' && !sourceData.sourceMap) {
|
|
151
|
+
// from inline sync
|
|
152
|
+
const smc = convertSourceMap.fromSource(source);
|
|
153
|
+
if (smc) {
|
|
154
|
+
sourceData.sourceMap = resolveSourceMap(smc.sourcemap, url);
|
|
155
|
+
smList.push({
|
|
156
|
+
url,
|
|
157
|
+
inline: true
|
|
158
|
+
});
|
|
159
|
+
await saveSourceFile(sourcePath, sourceData);
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
// from url async
|
|
163
|
+
const sourceMapUrl = getSourceMapUrl(source, item.url);
|
|
164
|
+
if (sourceMapUrl) {
|
|
165
|
+
concurrency.addItem({
|
|
166
|
+
sourceMapUrl,
|
|
167
|
+
sourcePath,
|
|
168
|
+
sourceData
|
|
169
|
+
});
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// no need check sourceMap
|
|
175
|
+
await saveSourceFile(sourcePath, sourceData);
|
|
176
|
+
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// from url concurrency
|
|
180
|
+
await concurrency.start(async (item) => {
|
|
181
|
+
const { sourceMapUrl, sourceData } = item;
|
|
182
|
+
const { url } = sourceData;
|
|
183
|
+
const data = await loadSourceMap(sourceMapUrl);
|
|
184
|
+
if (data) {
|
|
185
|
+
sourceData.sourceMap = resolveSourceMap(data, url);
|
|
186
|
+
smList.push({
|
|
187
|
+
url,
|
|
188
|
+
sourceMapUrl
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
await saveSourceFile(item.sourcePath, sourceData);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
return smList;
|
|
195
|
+
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
module.exports = {
|
|
199
|
+
collectSourceMaps,
|
|
200
|
+
resolveSourceMap
|
|
201
|
+
};
|