OLD | NEW |
1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** @typedef {{startOffset: number, endOffset: number, count: number}} */ | 5 /** @typedef {{startOffset: number, endOffset: number, count: number}} */ |
6 Coverage.RangeUseCount; | 6 Coverage.RangeUseCount; |
7 | 7 |
| 8 /** @typedef {{end: number, count: (number|undefined), depth: number}} */ |
| 9 Coverage.CoverageSegment; |
| 10 |
8 /** @typedef {{ | 11 /** @typedef {{ |
9 * contentProvider: !Common.ContentProvider, | 12 * contentProvider: !Common.ContentProvider, |
10 * size: number, | 13 * size: number, |
11 * unusedSize: number, | 14 * unusedSize: number, |
12 * usedSize: number, | 15 * usedSize: number, |
13 * type: !Coverage.CoverageType, | 16 * type: !Coverage.CoverageType, |
14 * lineOffset: number, | 17 * lineOffset: number, |
15 * columnOffset: number, | 18 * columnOffset: number, |
16 * ranges: !Array<!Coverage.RangeUseCount> | 19 * segments: !Array<!Coverage.CoverageSegment> |
17 * }} | 20 * }} |
18 */ | 21 */ |
19 Coverage.CoverageInfo; | 22 Coverage.CoverageInfo; |
20 | 23 |
21 /** | 24 /** |
22 * @enum {number} | 25 * @enum {number} |
23 */ | 26 */ |
24 Coverage.CoverageType = { | 27 Coverage.CoverageType = { |
25 CSS: (1 << 0), | 28 CSS: (1 << 0), |
26 JavaScript: (1 << 1), | 29 JavaScript: (1 << 1), |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 */ | 106 */ |
104 static _processJSCoverage(debuggerModel, scriptsCoverage) { | 107 static _processJSCoverage(debuggerModel, scriptsCoverage) { |
105 var result = []; | 108 var result = []; |
106 for (var entry of scriptsCoverage) { | 109 for (var entry of scriptsCoverage) { |
107 var script = debuggerModel.scriptForId(entry.scriptId); | 110 var script = debuggerModel.scriptForId(entry.scriptId); |
108 if (!script) | 111 if (!script) |
109 continue; | 112 continue; |
110 var ranges = []; | 113 var ranges = []; |
111 for (var func of entry.functions) { | 114 for (var func of entry.functions) { |
112 for (var range of func.ranges) | 115 for (var range of func.ranges) |
113 ranges.push({startOffset: range.startOffset, endOffset: range.endOffse
t, count: range.count}); | 116 ranges.push(range); |
114 } | 117 } |
| 118 ranges.sort((a, b) => a.startOffset - b.startOffset); |
115 result.push(Coverage.CoverageModel._buildCoverageInfo( | 119 result.push(Coverage.CoverageModel._buildCoverageInfo( |
116 script, script.contentLength, script.lineOffset, script.columnOffset,
ranges)); | 120 script, script.contentLength, script.lineOffset, script.columnOffset,
ranges)); |
117 } | 121 } |
118 return result; | 122 return result; |
119 } | 123 } |
120 | 124 |
121 /** | 125 /** |
| 126 * @param {!Array<!Coverage.RangeUseCount>} ranges |
| 127 * @return {!Array<!Coverage.CoverageSegment>} |
| 128 */ |
| 129 static _convertToDisjointSegments(ranges) { |
| 130 var result = []; |
| 131 |
| 132 var stack = []; |
| 133 for (var entry of ranges) { |
| 134 var top = stack.peekLast(); |
| 135 while (top && top.endOffset <= entry.startOffset) { |
| 136 append(top.endOffset, top.count, stack.length); |
| 137 stack.pop(); |
| 138 top = stack.peekLast(); |
| 139 } |
| 140 append(entry.startOffset, top ? top.count : undefined, stack.length); |
| 141 stack.push(entry); |
| 142 } |
| 143 |
| 144 while (stack.length) { |
| 145 var depth = stack.length; |
| 146 var top = stack.pop(); |
| 147 append(top.endOffset, top.count, depth); |
| 148 } |
| 149 |
| 150 /** |
| 151 * @param {number} end |
| 152 * @param {number} count |
| 153 * @param {number} depth |
| 154 */ |
| 155 function append(end, count, depth) { |
| 156 var last = result.peekLast(); |
| 157 if (last) { |
| 158 if (last.end === end) |
| 159 return; |
| 160 if (last.count === count && last.depth === depth) { |
| 161 last.end = end; |
| 162 return; |
| 163 } |
| 164 } |
| 165 result.push({end: end, count: count, depth: depth}); |
| 166 } |
| 167 |
| 168 return result; |
| 169 } |
| 170 |
| 171 /** |
122 * @return {!Promise<!Array<!Coverage.CoverageInfo>>} | 172 * @return {!Promise<!Array<!Coverage.CoverageInfo>>} |
123 */ | 173 */ |
124 async _stopCSSCoverage() { | 174 async _stopCSSCoverage() { |
125 if (!this._cssModel) | 175 if (!this._cssModel) |
126 return []; | 176 return []; |
127 | 177 |
128 var rawCoverageData = await this._cssModel.ruleListPromise(); | 178 var rawCoverageData = await this._cssModel.ruleListPromise(); |
129 return Coverage.CoverageModel._processCSSCoverage( | 179 return Coverage.CoverageModel._processCSSCoverage( |
130 /** @type !SDK.CSSModel */ (this._cssModel), rawCoverageData); | 180 /** @type !SDK.CSSModel */ (this._cssModel), rawCoverageData); |
131 } | 181 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 /** @type Coverage.CoverageType */ | 215 /** @type Coverage.CoverageType */ |
166 var coverageType; | 216 var coverageType; |
167 var url = contentProvider.contentURL(); | 217 var url = contentProvider.contentURL(); |
168 if (contentProvider.contentType().isScript()) | 218 if (contentProvider.contentType().isScript()) |
169 coverageType = Coverage.CoverageType.JavaScript; | 219 coverageType = Coverage.CoverageType.JavaScript; |
170 else if (contentProvider.contentType().isStyleSheet()) | 220 else if (contentProvider.contentType().isStyleSheet()) |
171 coverageType = Coverage.CoverageType.CSS; | 221 coverageType = Coverage.CoverageType.CSS; |
172 else | 222 else |
173 console.assert(false, `Unexpected resource type ${contentProvider.contentT
ype().name} for ${url}`); | 223 console.assert(false, `Unexpected resource type ${contentProvider.contentT
ype().name} for ${url}`); |
174 | 224 |
175 var stack = []; | 225 var segments = Coverage.CoverageModel._convertToDisjointSegments(ranges); |
176 ranges.sort((a, b) => a.startOffset - b.startOffset); | |
177 for (var entry of ranges) { | |
178 while (stack.length && stack.peekLast().endOffset <= entry.startOffset) | |
179 stack.pop(); | |
180 | |
181 entry.ownSize = entry.endOffset - entry.startOffset; | |
182 var top = stack.peekLast(); | |
183 if (top) { | |
184 if (top.endOffset < entry.endOffset) { | |
185 console.assert( | |
186 false, `Overlapping coverage entries in ${url}: ${top.start}-${top
.end} vs. ${entry.start}-${entry.end}`); | |
187 } | |
188 top.ownSize -= entry.ownSize; | |
189 } | |
190 stack.push(entry); | |
191 } | |
192 | |
193 var usedSize = 0; | 226 var usedSize = 0; |
194 var unusedSize = 0; | 227 var unusedSize = 0; |
195 for (var entry of ranges) { | 228 var last = 0; |
196 if (entry.count) | 229 for (var segment of segments) { |
197 usedSize += entry.ownSize; | 230 if (typeof segment.count === 'number') { |
198 else | 231 if (segment.count) |
199 unusedSize += entry.ownSize; | 232 usedSize += segment.end - last; |
| 233 else |
| 234 unusedSize += segment.end - last; |
| 235 } |
| 236 last = segment.end; |
200 } | 237 } |
201 | |
202 var coverageInfo = { | 238 var coverageInfo = { |
203 contentProvider: contentProvider, | 239 contentProvider: contentProvider, |
204 ranges: ranges, | 240 segments: segments, |
205 type: coverageType, | 241 type: coverageType, |
206 size: contentLength, | 242 size: contentLength, |
207 usedSize: usedSize, | 243 usedSize: usedSize, |
208 unusedSize: unusedSize, | 244 unusedSize: unusedSize, |
209 lineOffset: startLine, | 245 lineOffset: startLine, |
210 columnOffset: startColumn | 246 columnOffset: startColumn |
211 }; | 247 }; |
212 return coverageInfo; | 248 return coverageInfo; |
213 } | 249 } |
214 }; | 250 }; |
OLD | NEW |