Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(654)

Unified Diff: third_party/WebKit/Source/devtools/front_end/coverage/CoverageModel.js

Issue 2865573003: DevTools: support live coverage (Closed)
Patch Set: minor polish on corner cases Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/devtools/front_end/coverage/CoverageModel.js
diff --git a/third_party/WebKit/Source/devtools/front_end/coverage/CoverageModel.js b/third_party/WebKit/Source/devtools/front_end/coverage/CoverageModel.js
index 8f339c9245527c394648340d5ea394704e677e3e..c322243d472cd73b3923800e79312cbd5ebfe1ee 100644
--- a/third_party/WebKit/Source/devtools/front_end/coverage/CoverageModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/coverage/CoverageModel.js
@@ -28,6 +28,8 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
/** @type {!Map<string, !Coverage.URLCoverageInfo>} */
this._coverageByURL = new Map();
+ /** @type {!Map<!Common.ContentProvider, !Coverage.CoverageInfo>} */
+ this._coverageByContentProvider = new Map();
}
/**
@@ -36,33 +38,66 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
start() {
this._coverageByURL.clear();
if (this._cssModel)
- this._cssModel.startRuleUsageTracking();
+ this._cssModel.startCoverage();
if (this._cpuProfilerModel)
this._cpuProfilerModel.startPreciseCoverage();
return !!(this._cssModel || this._cpuProfilerModel);
}
/**
- * @return {!Promise<!Array<!Coverage.URLCoverageInfo>>}
+ * @return {!Promise<!Array<!Coverage.CoverageInfo>>}
*/
- async stop() {
- await Promise.all([this._stopCSSCoverage(), this._stopJSCoverage()]);
+ stop() {
+ var pollPromise = this.poll();
+ if (this._cpuProfilerModel)
+ this._cpuProfilerModel.stopPreciseCoverage();
+ if (this._cssModel)
+ this._cssModel.stopCoverage();
+ return pollPromise;
+ }
+
+ /**
+ * @return {!Promise<!Array<!Coverage.CoverageInfo>>}
+ */
+ async poll() {
+ var updates = await Promise.all([this._takeCSSCoverage(), this._takeJSCoverage()]);
+ return updates[0].concat(updates[1]);
+ }
+
+ /**
+ * @return {!Array<!Coverage.URLCoverageInfo>}
+ */
+ entries() {
return Array.from(this._coverageByURL.values());
}
- async _stopJSCoverage() {
+ /**
+ * @param {!Common.ContentProvider} contentProvider
+ * @param {number} startOffset
+ * @param {number} endOffset
+ * @return {boolean|undefined}
+ */
+ usageForRange(contentProvider, startOffset, endOffset) {
+ var coverageInfo = this._coverageByContentProvider.get(contentProvider);
+ return coverageInfo && coverageInfo.usageForRange(startOffset, endOffset);
+ }
+
+ /**
+ * @return {!Promise<!Array<!Coverage.CoverageInfo>>}
+ */
+ async _takeJSCoverage() {
if (!this._cpuProfilerModel)
- return;
- var coveragePromise = this._cpuProfilerModel.takePreciseCoverage();
- this._cpuProfilerModel.stopPreciseCoverage();
- var rawCoverageData = await coveragePromise;
- this._processJSCoverage(rawCoverageData);
+ return [];
+ var rawCoverageData = await this._cpuProfilerModel.takePreciseCoverage();
+ return this._processJSCoverage(rawCoverageData);
}
/**
* @param {!Array<!Protocol.Profiler.ScriptCoverage>} scriptsCoverage
+ * @return {!Array<!Coverage.CoverageInfo>}
*/
_processJSCoverage(scriptsCoverage) {
+ var updatedEntries = [];
for (var entry of scriptsCoverage) {
var script = this._debuggerModel.scriptForId(entry.scriptId);
if (!script)
@@ -72,8 +107,52 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
for (var range of func.ranges)
ranges.push(range);
}
- this._addCoverage(script, script.contentLength, script.lineOffset, script.columnOffset, ranges);
+ var entry = this._addCoverage(script, script.contentLength, script.lineOffset, script.columnOffset, ranges);
+ if (entry)
+ updatedEntries.push(entry);
}
+ return updatedEntries;
+ }
+
+ /**
+ * @return {!Promise<!Array<!Coverage.CoverageInfo>>}
+ */
+ async _takeCSSCoverage() {
+ if (!this._cssModel)
+ return [];
+ var rawCoverageData = await this._cssModel.takeCoverageDelta();
+ return this._processCSSCoverage(rawCoverageData);
+ }
+
+ /**
+ * @param {!Array<!Protocol.CSS.RuleUsage>} ruleUsageList
+ * @return {!Array<!Coverage.CoverageInfo>}
+ */
+ _processCSSCoverage(ruleUsageList) {
+ var updatedEntries = [];
+ /** @type {!Map<!SDK.CSSStyleSheetHeader, !Array<!Coverage.RangeUseCount>>} */
+ var rulesByStyleSheet = new Map();
+ for (var rule of ruleUsageList) {
+ var styleSheetHeader = this._cssModel.styleSheetHeaderForId(rule.styleSheetId);
+ if (!styleSheetHeader)
+ continue;
+ var ranges = rulesByStyleSheet.get(styleSheetHeader);
+ if (!ranges) {
+ ranges = [];
+ rulesByStyleSheet.set(styleSheetHeader, ranges);
+ }
+ ranges.push({startOffset: rule.startOffset, endOffset: rule.endOffset, count: Number(rule.used)});
+ }
+ for (var entry of rulesByStyleSheet) {
+ var styleSheetHeader = /** @type {!SDK.CSSStyleSheetHeader} */ (entry[0]);
+ var ranges = /** @type {!Array<!Coverage.RangeUseCount>} */ (entry[1]);
+ var entry = this._addCoverage(
+ styleSheetHeader, styleSheetHeader.contentLength, styleSheetHeader.startLine, styleSheetHeader.startColumn,
+ ranges);
+ if (entry)
+ updatedEntries.push(entry);
+ }
+ return updatedEntries;
}
/**
@@ -121,60 +200,34 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
return result;
}
- async _stopCSSCoverage() {
- if (!this._cssModel)
- return [];
-
- var rawCoverageData = await this._cssModel.ruleListPromise();
- this._processCSSCoverage(rawCoverageData);
- }
-
- /**
- * @param {!Array<!Protocol.CSS.RuleUsage>} ruleUsageList
- */
- _processCSSCoverage(ruleUsageList) {
- /** @type {!Map<!SDK.CSSStyleSheetHeader, !Array<!Coverage.RangeUseCount>>} */
- var rulesByStyleSheet = new Map();
- for (var rule of ruleUsageList) {
- var styleSheetHeader = this._cssModel.styleSheetHeaderForId(rule.styleSheetId);
- if (!styleSheetHeader)
- continue;
- var ranges = rulesByStyleSheet.get(styleSheetHeader);
- if (!ranges) {
- ranges = [];
- rulesByStyleSheet.set(styleSheetHeader, ranges);
- }
- ranges.push({startOffset: rule.startOffset, endOffset: rule.endOffset, count: Number(rule.used)});
- }
- for (var entry of rulesByStyleSheet) {
- var styleSheetHeader = /** @type {!SDK.CSSStyleSheetHeader} */ (entry[0]);
- var ranges = /** @type {!Array<!Coverage.RangeUseCount>} */ (entry[1]);
- this._addCoverage(
- styleSheetHeader, styleSheetHeader.contentLength, styleSheetHeader.startLine, styleSheetHeader.startColumn,
- ranges);
- }
- }
-
/**
* @param {!Common.ContentProvider} contentProvider
* @param {number} contentLength
* @param {number} startLine
* @param {number} startColumn
* @param {!Array<!Coverage.RangeUseCount>} ranges
+ * @return {?Coverage.CoverageInfo}
*/
_addCoverage(contentProvider, contentLength, startLine, startColumn, ranges) {
var url = contentProvider.contentURL();
if (!url)
- return;
- var entry = this._coverageByURL.get(url);
- if (!entry) {
- entry = new Coverage.URLCoverageInfo(url);
- this._coverageByURL.set(url, entry);
+ return null;
+ var urlCoverage = this._coverageByURL.get(url);
+ if (!urlCoverage) {
+ urlCoverage = new Coverage.URLCoverageInfo(url);
+ this._coverageByURL.set(url, urlCoverage);
}
+ var coverageInfo = urlCoverage._ensureEntry(contentProvider, contentLength, startLine, startColumn);
+ this._coverageByContentProvider.set(contentProvider, coverageInfo);
var segments = Coverage.CoverageModel._convertToDisjointSegments(ranges);
if (segments.length && segments.peekLast().end < contentLength)
segments.push({end: contentLength});
- entry.update(contentProvider, contentLength, startLine, startColumn, segments);
+ var oldUsedSize = coverageInfo._usedSize;
+ coverageInfo.mergeCoverage(segments);
+ if (coverageInfo._usedSize === oldUsedSize)
+ return null;
+ urlCoverage._usedSize += coverageInfo._usedSize - oldUsedSize;
+ return coverageInfo;
}
};
@@ -193,28 +246,6 @@ Coverage.URLCoverageInfo = class {
}
/**
- * @param {!Common.ContentProvider} contentProvider
- * @param {number} contentLength
- * @param {number} lineOffset
- * @param {number} columnOffset
- * @param {!Array<!Coverage.CoverageSegment>} segments
- */
- update(contentProvider, contentLength, lineOffset, columnOffset, segments) {
- var key = `${lineOffset}:${columnOffset}`;
- var entry = this._coverageInfoByLocation.get(key);
-
- if (!entry) {
- entry = new Coverage.CoverageInfo(contentProvider, lineOffset, columnOffset);
- this._coverageInfoByLocation.set(key, entry);
- this._size += contentLength;
- this._type |= entry.type();
- }
- this._usedSize -= entry._usedSize;
- entry.mergeCoverage(segments);
- this._usedSize += entry._usedSize;
- }
-
- /**
* @return {string}
*/
url() {
@@ -250,14 +281,23 @@ Coverage.URLCoverageInfo = class {
}
/**
- * @return {!Promise<!Array<!{range: !TextUtils.TextRange, count: number}>>}
+ * @param {!Common.ContentProvider} contentProvider
+ * @param {number} contentLength
+ * @param {number} lineOffset
+ * @param {number} columnOffset
+ * @return {!Coverage.CoverageInfo}
*/
- async buildTextRanges() {
- var textRangePromises = [];
- for (var coverageInfo of this._coverageInfoByLocation.values())
- textRangePromises.push(coverageInfo.buildTextRanges());
- var allTextRanges = await Promise.all(textRangePromises);
- return [].concat(...allTextRanges);
+ _ensureEntry(contentProvider, contentLength, lineOffset, columnOffset) {
+ var key = `${lineOffset}:${columnOffset}`;
+ var entry = this._coverageInfoByLocation.get(key);
+
+ if (!entry) {
+ entry = new Coverage.CoverageInfo(contentProvider, lineOffset, columnOffset);
+ this._coverageInfoByLocation.set(key, entry);
+ this._size += contentLength;
+ this._type |= entry.type();
+ }
+ return entry;
}
};
@@ -286,6 +326,20 @@ Coverage.CoverageInfo = class {
}
/**
+ * @return {!Common.ContentProvider}
+ */
+ contentProvider() {
+ return this._contentProvider;
+ }
+
+ /**
+ * @return {string}
+ */
+ url() {
+ return this._contentProvider.contentURL();
+ }
+
+ /**
* @return {!Coverage.CoverageType}
*/
type() {
@@ -301,6 +355,20 @@ Coverage.CoverageInfo = class {
}
/**
+ * @param {number} start
+ * @param {number} end
+ * @return {boolean}
+ */
+ usageForRange(start, end) {
+ var index = this._segments.upperBound(start, (position, segment) => position - segment.end);
+ for (; index < this._segments.length && this._segments[index].end < end; ++index) {
+ if (this._segments[index].count)
+ return true;
+ }
+ return index < this._segments.length && this._segments[index].count;
+ }
+
+ /**
* @param {!Array<!Coverage.CoverageSegment>} segmentsA
* @param {!Array<!Coverage.CoverageSegment>} segmentsB
*/
@@ -333,35 +401,6 @@ Coverage.CoverageInfo = class {
return result;
}
- /**
- * @return {!Promise<!Array<!{range: !TextUtils.TextRange, count: number}>>}
- */
- async buildTextRanges() {
- var contents = await this._contentProvider.requestContent();
- if (!contents)
- return [];
- var text = new TextUtils.Text(contents);
- var lastOffset = 0;
- var result = [];
- for (var segment of this._segments) {
- if (!segment.end)
- continue;
- var startPosition = text.positionFromOffset(lastOffset);
- var endPosition = text.positionFromOffset(segment.end);
- if (!startPosition.lineNumber)
- startPosition.columnNumber += this._columnOffset;
- startPosition.lineNumber += this._lineOffset;
- if (!endPosition.lineNumber)
- endPosition.columnNumber += this._columnOffset;
- endPosition.lineNumber += this._lineOffset;
- var range = new TextUtils.TextRange(
- startPosition.lineNumber, startPosition.columnNumber, endPosition.lineNumber, endPosition.columnNumber);
- result.push({count: segment.count || 0, range: range});
- lastOffset = segment.end;
- }
- return result;
- }
-
_updateStats() {
this._usedSize = 0;

Powered by Google App Engine
This is Rietveld 408576698