mirror of
https://github.com/react/react-native-devtools-frontend.git
synced 2026-10-02 18:11:04 +08:00
Migrates coverage/ to esm
Bug: 1006759 Change-Id: I4bcbfad6d9512331df9394a0a182521cadb8e6dc Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/1928917 Reviewed-by: Tim van der Lippe <tvanderlippe@chromium.org> Commit-Queue: Paul Lewis <aerotwist@chromium.org>
This commit is contained in:
@@ -121,11 +121,7 @@ if (external_devtools_frontend) {
|
||||
"front_end/cookie_table/CookiesTable.js",
|
||||
"front_end/cookie_table/module.json",
|
||||
"front_end/coverage/coverageListView.css",
|
||||
"front_end/coverage/CoverageDecorationManager.js",
|
||||
"front_end/coverage/CoverageListView.js",
|
||||
"front_end/coverage/CoverageModel.js",
|
||||
"front_end/coverage/coverageView.css",
|
||||
"front_end/coverage/CoverageView.js",
|
||||
"front_end/coverage/module.json",
|
||||
"front_end/coverage_test_runner/CoverageTestRunner.js",
|
||||
"front_end/coverage_test_runner/module.json",
|
||||
@@ -711,6 +707,11 @@ if (external_devtools_frontend) {
|
||||
all_devtools_files += lighthouse_locale_files
|
||||
|
||||
all_devtools_modules = [
|
||||
"front_end/coverage/coverage.js",
|
||||
"front_end/coverage/CoverageView.js",
|
||||
"front_end/coverage/CoverageModel.js",
|
||||
"front_end/coverage/CoverageListView.js",
|
||||
"front_end/coverage/CoverageDecorationManager.js",
|
||||
"front_end/console/console.js",
|
||||
"front_end/console/ConsoleContextSelector.js",
|
||||
"front_end/console/ConsoleFilter.js",
|
||||
@@ -1218,6 +1219,11 @@ if (external_devtools_frontend) {
|
||||
]
|
||||
|
||||
copied_devtools_modules = [
|
||||
"$resources_out_dir/coverage/coverage.js",
|
||||
"$resources_out_dir/coverage/CoverageView.js",
|
||||
"$resources_out_dir/coverage/CoverageModel.js",
|
||||
"$resources_out_dir/coverage/CoverageListView.js",
|
||||
"$resources_out_dir/coverage/CoverageDecorationManager.js",
|
||||
"$resources_out_dir/console/console.js",
|
||||
"$resources_out_dir/console/ConsoleContextSelector.js",
|
||||
"$resources_out_dir/console/ConsoleFilter.js",
|
||||
@@ -1881,7 +1887,9 @@ if (external_devtools_frontend) {
|
||||
script = "scripts/build/build_debug_applications.py"
|
||||
inputs = all_devtools_files + application_templates
|
||||
stamp = "$resources_out_debug_dir/build.stamp"
|
||||
outputs = [ stamp ]
|
||||
outputs = [
|
||||
stamp,
|
||||
]
|
||||
|
||||
args = [
|
||||
"--input_path",
|
||||
@@ -1889,7 +1897,7 @@ if (external_devtools_frontend) {
|
||||
"--output_path",
|
||||
rebase_path(resources_out_debug_dir, root_build_dir),
|
||||
"--build_stamp",
|
||||
rebase_path(stamp, root_build_dir)
|
||||
rebase_path(stamp, root_build_dir),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -2,17 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @typedef {!{
|
||||
* id: string,
|
||||
* contentProvider: !Common.ContentProvider,
|
||||
* line: number,
|
||||
* column: number
|
||||
* }}
|
||||
*/
|
||||
Coverage.RawLocation;
|
||||
export const _decoratorType = 'coverage';
|
||||
|
||||
Coverage.CoverageDecorationManager = class {
|
||||
export default class CoverageDecorationManager {
|
||||
/**
|
||||
* @param {!Coverage.CoverageModel} coverageModel
|
||||
*/
|
||||
@@ -24,14 +16,14 @@ Coverage.CoverageDecorationManager = class {
|
||||
this._uiSourceCodeByContentProvider = new Platform.Multimap();
|
||||
|
||||
for (const uiSourceCode of Workspace.workspace.uiSourceCodes()) {
|
||||
uiSourceCode.addLineDecoration(0, Coverage.CoverageDecorationManager._decoratorType, this);
|
||||
uiSourceCode.addLineDecoration(0, _decoratorType, this);
|
||||
}
|
||||
Workspace.workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeAdded, this._onUISourceCodeAdded, this);
|
||||
}
|
||||
|
||||
reset() {
|
||||
for (const uiSourceCode of Workspace.workspace.uiSourceCodes()) {
|
||||
uiSourceCode.removeDecorationsForType(Coverage.CoverageDecorationManager._decoratorType);
|
||||
uiSourceCode.removeDecorationsForType(_decoratorType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,8 +39,8 @@ Coverage.CoverageDecorationManager = class {
|
||||
update(updatedEntries) {
|
||||
for (const entry of updatedEntries) {
|
||||
for (const uiSourceCode of this._uiSourceCodeByContentProvider.get(entry.contentProvider())) {
|
||||
uiSourceCode.removeDecorationsForType(Coverage.CoverageDecorationManager._decoratorType);
|
||||
uiSourceCode.addLineDecoration(0, Coverage.CoverageDecorationManager._decoratorType, this);
|
||||
uiSourceCode.removeDecorationsForType(_decoratorType);
|
||||
uiSourceCode.addLineDecoration(0, _decoratorType, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -205,106 +197,30 @@ Coverage.CoverageDecorationManager = class {
|
||||
*/
|
||||
_onUISourceCodeAdded(event) {
|
||||
const uiSourceCode = /** @type !Workspace.UISourceCode */ (event.data);
|
||||
uiSourceCode.addLineDecoration(0, Coverage.CoverageDecorationManager._decoratorType, this);
|
||||
uiSourceCode.addLineDecoration(0, _decoratorType, this);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Coverage.CoverageDecorationManager._decoratorType = 'coverage';
|
||||
/* Legacy exported object */
|
||||
self.Coverage = self.Coverage || {};
|
||||
|
||||
/* Legacy exported object */
|
||||
Coverage = Coverage || {};
|
||||
|
||||
/**
|
||||
* @implements {SourceFrame.LineDecorator}
|
||||
* @typedef {!{
|
||||
* id: string,
|
||||
* contentProvider: !Common.ContentProvider,
|
||||
* line: number,
|
||||
* column: number
|
||||
* }}
|
||||
*/
|
||||
Coverage.CoverageView.LineDecorator = class {
|
||||
constructor() {
|
||||
/** @type {!WeakMap<!TextEditor.CodeMirrorTextEditor, function(!Common.Event)>} */
|
||||
this._listeners = new WeakMap();
|
||||
}
|
||||
Coverage.RawLocation;
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @param {!Workspace.UISourceCode} uiSourceCode
|
||||
* @param {!TextEditor.CodeMirrorTextEditor} textEditor
|
||||
*/
|
||||
decorate(uiSourceCode, textEditor) {
|
||||
const decorations = uiSourceCode.decorationsForType(Coverage.CoverageDecorationManager._decoratorType);
|
||||
if (!decorations || !decorations.size) {
|
||||
this._uninstallGutter(textEditor);
|
||||
return;
|
||||
}
|
||||
const decorationManager =
|
||||
/** @type {!Coverage.CoverageDecorationManager} */ (decorations.values().next().value.data());
|
||||
decorationManager.usageByLine(uiSourceCode).then(lineUsage => {
|
||||
textEditor.operation(() => this._innerDecorate(uiSourceCode, textEditor, lineUsage));
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
Coverage.CoverageDecorationManager = CoverageDecorationManager;
|
||||
|
||||
/**
|
||||
* @param {!Workspace.UISourceCode} uiSourceCode
|
||||
* @param {!TextEditor.CodeMirrorTextEditor} textEditor
|
||||
* @param {!Array<boolean>} lineUsage
|
||||
*/
|
||||
_innerDecorate(uiSourceCode, textEditor, lineUsage) {
|
||||
const gutterType = Coverage.CoverageView.LineDecorator._gutterType;
|
||||
this._uninstallGutter(textEditor);
|
||||
if (lineUsage.length) {
|
||||
this._installGutter(textEditor, uiSourceCode.url());
|
||||
}
|
||||
for (let line = 0; line < lineUsage.length; ++line) {
|
||||
// Do not decorate the line if we don't have data.
|
||||
if (typeof lineUsage[line] !== 'boolean') {
|
||||
continue;
|
||||
}
|
||||
const className = lineUsage[line] ? 'text-editor-coverage-used-marker' : 'text-editor-coverage-unused-marker';
|
||||
const gutterElement = createElementWithClass('div', className);
|
||||
textEditor.setGutterDecoration(line, gutterType, gutterElement);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} url - the url of the file this click handler will select in the coverage drawer
|
||||
* @return {function(!Common.Event)}
|
||||
*/
|
||||
makeGutterClickHandler(url) {
|
||||
function handleGutterClick(event) {
|
||||
const eventData = /** @type {!SourceFrame.SourcesTextEditor.GutterClickEventData} */ (event.data);
|
||||
if (eventData.gutterType !== Coverage.CoverageView.LineDecorator._gutterType) {
|
||||
return;
|
||||
}
|
||||
const coverageViewId = 'coverage';
|
||||
UI.viewManager.showView(coverageViewId).then(() => UI.viewManager.view(coverageViewId).widget()).then(widget => {
|
||||
const matchFormattedSuffix = url.match(/(.*):formatted$/);
|
||||
const urlWithoutFormattedSuffix = (matchFormattedSuffix && matchFormattedSuffix[1]) || url;
|
||||
widget.selectCoverageItemByUrl(urlWithoutFormattedSuffix);
|
||||
});
|
||||
}
|
||||
return handleGutterClick;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!TextEditor.CodeMirrorTextEditor} textEditor - the text editor to install the gutter on
|
||||
* @param {string} url - the url of the file in the text editor
|
||||
*/
|
||||
_installGutter(textEditor, url) {
|
||||
let listener = this._listeners.get(textEditor);
|
||||
if (!listener) {
|
||||
listener = this.makeGutterClickHandler(url);
|
||||
this._listeners.set(textEditor, listener);
|
||||
}
|
||||
textEditor.installGutter(Coverage.CoverageView.LineDecorator._gutterType, false);
|
||||
textEditor.addEventListener(SourceFrame.SourcesTextEditor.Events.GutterClick, listener, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!TextEditor.CodeMirrorTextEditor} textEditor - the text editor to uninstall the gutter from
|
||||
*/
|
||||
_uninstallGutter(textEditor) {
|
||||
textEditor.uninstallGutter(Coverage.CoverageView.LineDecorator._gutterType);
|
||||
const listener = this._listeners.get(textEditor);
|
||||
if (listener) {
|
||||
textEditor.removeEventListener(SourceFrame.SourcesTextEditor.Events.GutterClick, listener, this);
|
||||
this._listeners.delete(textEditor);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Coverage.CoverageView.LineDecorator._gutterType = 'CodeMirror-gutter-coverage';
|
||||
/** @public */
|
||||
Coverage.CoverageDecorationManager.decoratorType = _decoratorType;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
Coverage.CoverageListView = class extends UI.VBox {
|
||||
export default class CoverageListView extends UI.VBox {
|
||||
/**
|
||||
* @param {function(!Coverage.URLCoverageInfo):boolean} filterCallback
|
||||
*/
|
||||
@@ -61,7 +61,7 @@ Coverage.CoverageListView = class extends UI.VBox {
|
||||
}
|
||||
continue;
|
||||
}
|
||||
node = new Coverage.CoverageListView.GridNode(entry, maxSize);
|
||||
node = new GridNode(entry, maxSize);
|
||||
this._nodeForCoverageInfo.set(entry, node);
|
||||
if (this._filterCallback(node._coverageInfo)) {
|
||||
rootNode.appendChild(node);
|
||||
@@ -231,9 +231,9 @@ Coverage.CoverageListView = class extends UI.VBox {
|
||||
}
|
||||
return types.join('+');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Coverage.CoverageListView.GridNode = class extends DataGrid.SortableDataGridNode {
|
||||
export class GridNode extends DataGrid.SortableDataGridNode {
|
||||
/**
|
||||
* @param {!Coverage.URLCoverageInfo} coverageInfo
|
||||
* @param {number} maxSize
|
||||
@@ -379,4 +379,20 @@ Coverage.CoverageListView.GridNode = class extends DataGrid.SortableDataGridNode
|
||||
const range = new TextUtils.SourceRange(matches.index, matches[0].length);
|
||||
UI.highlightRangesWithStyleClass(element, [range], 'filter-highlight');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/* Legacy exported object */
|
||||
self.Coverage = self.Coverage || {};
|
||||
|
||||
/* Legacy exported object */
|
||||
Coverage = Coverage || {};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
Coverage.CoverageListView = CoverageListView;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
Coverage.CoverageListView.GridNode = GridNode;
|
||||
|
||||
@@ -11,20 +11,28 @@ Coverage.CoverageSegment;
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
Coverage.CoverageType = {
|
||||
export const CoverageType = {
|
||||
CSS: (1 << 0),
|
||||
JavaScript: (1 << 1),
|
||||
JavaScriptPerFunction: (1 << 2),
|
||||
};
|
||||
|
||||
/** @enum {symbol} */
|
||||
Coverage.SuspensionState = {
|
||||
export const SuspensionState = {
|
||||
Active: Symbol('Active'),
|
||||
Suspending: Symbol('Suspending'),
|
||||
Suspended: Symbol('Suspended')
|
||||
};
|
||||
|
||||
Coverage.CoverageModel = class extends SDK.SDKModel {
|
||||
/** @enum {symbol} */
|
||||
export const Events = {
|
||||
CoverageUpdated: Symbol('CoverageUpdated')
|
||||
};
|
||||
|
||||
/** @type {number} */
|
||||
export const _coveragePollingPeriodMs = 200;
|
||||
|
||||
export default class CoverageModel extends SDK.SDKModel {
|
||||
/**
|
||||
* @param {!SDK.Target} target
|
||||
*/
|
||||
@@ -40,7 +48,7 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
|
||||
this._coverageByContentProvider = new Map();
|
||||
|
||||
/** @type {!Coverage.SuspensionState} */
|
||||
this._suspensionState = Coverage.SuspensionState.Active;
|
||||
this._suspensionState = SuspensionState.Active;
|
||||
/** @type {?number} */
|
||||
this._pollTimer = null;
|
||||
/** @type {?Promise} */
|
||||
@@ -60,7 +68,7 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
|
||||
* @return {!Promise<boolean>}
|
||||
*/
|
||||
async start(jsCoveragePerBlock) {
|
||||
if (this._suspensionState !== Coverage.SuspensionState.Active) {
|
||||
if (this._suspensionState !== SuspensionState.Active) {
|
||||
throw Error('Cannot start CoverageModel while it is not active.');
|
||||
}
|
||||
const promises = [];
|
||||
@@ -105,7 +113,7 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
|
||||
* @return {!Promise}
|
||||
*/
|
||||
async startPolling() {
|
||||
if (this._currentPollPromise || this._suspensionState !== Coverage.SuspensionState.Active) {
|
||||
if (this._currentPollPromise || this._suspensionState !== SuspensionState.Active) {
|
||||
return;
|
||||
}
|
||||
await this._pollLoop();
|
||||
@@ -118,8 +126,8 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
|
||||
this._clearTimer();
|
||||
this._currentPollPromise = this._pollAndCallback();
|
||||
await this._currentPollPromise;
|
||||
if (this._suspensionState === Coverage.SuspensionState.Active || this._performanceTraceRecording) {
|
||||
this._pollTimer = setTimeout(() => this._pollLoop(), Coverage.CoverageModel._coveragePollingPeriodMs);
|
||||
if (this._suspensionState === SuspensionState.Active || this._performanceTraceRecording) {
|
||||
this._pollTimer = setTimeout(() => this._pollLoop(), _coveragePollingPeriodMs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,17 +143,17 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
|
||||
* @return {!Promise<undefined>}
|
||||
*/
|
||||
async _pollAndCallback() {
|
||||
if (this._suspensionState === Coverage.SuspensionState.Suspended && !this._performanceTraceRecording) {
|
||||
if (this._suspensionState === SuspensionState.Suspended && !this._performanceTraceRecording) {
|
||||
return;
|
||||
}
|
||||
const updates = await this._takeAllCoverage();
|
||||
// This conditional should never trigger, as all intended ways to stop
|
||||
// polling are awaiting the `_currentPollPromise` before suspending.
|
||||
console.assert(
|
||||
this._suspensionState !== Coverage.SuspensionState.Suspended || this._performanceTraceRecording,
|
||||
this._suspensionState !== SuspensionState.Suspended || this._performanceTraceRecording,
|
||||
'CoverageModel was suspended while polling.');
|
||||
if (updates.length) {
|
||||
this.dispatchEventToListeners(Coverage.CoverageModel.Events.CoverageUpdated, updates);
|
||||
this.dispatchEventToListeners(Events.CoverageUpdated, updates);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,10 +172,10 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
|
||||
* @return {!Promise<undefined>}
|
||||
*/
|
||||
async preSuspendModel(reason) {
|
||||
if (this._suspensionState !== Coverage.SuspensionState.Active) {
|
||||
if (this._suspensionState !== SuspensionState.Active) {
|
||||
return;
|
||||
}
|
||||
this._suspensionState = Coverage.SuspensionState.Suspending;
|
||||
this._suspensionState = SuspensionState.Suspending;
|
||||
if (reason === 'performance-timeline') {
|
||||
this._performanceTraceRecording = true;
|
||||
// Keep polling to the backlog if a performance trace is recorded.
|
||||
@@ -185,7 +193,7 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
|
||||
* @return {!Promise<undefined>}
|
||||
*/
|
||||
async suspendModel(reason) {
|
||||
this._suspensionState = Coverage.SuspensionState.Suspended;
|
||||
this._suspensionState = SuspensionState.Suspended;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,7 +210,7 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
|
||||
* @return {!Promise<undefined>}
|
||||
*/
|
||||
async postResumeModel() {
|
||||
this._suspensionState = Coverage.SuspensionState.Active;
|
||||
this._suspensionState = SuspensionState.Active;
|
||||
this._performanceTraceRecording = false;
|
||||
if (this._shouldResumePollingOnResume) {
|
||||
this._shouldResumePollingOnResume = false;
|
||||
@@ -230,7 +238,7 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
|
||||
|
||||
_clearCSS() {
|
||||
for (const entry of this._coverageByContentProvider.values()) {
|
||||
if (entry.type() !== Coverage.CoverageType.CSS) {
|
||||
if (entry.type() !== CoverageType.CSS) {
|
||||
continue;
|
||||
}
|
||||
const contentProvider = /** @type {!SDK.CSSStyleSheetHeader} */ (entry.contentProvider());
|
||||
@@ -268,7 +276,7 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
|
||||
}
|
||||
const now = Date.now();
|
||||
const freshRawCoverageData = await this._cpuProfilerModel.takePreciseCoverage();
|
||||
if (this._suspensionState !== Coverage.SuspensionState.Active) {
|
||||
if (this._suspensionState !== SuspensionState.Active) {
|
||||
if (freshRawCoverageData.length > 0) {
|
||||
this._jsBacklog.push({rawCoverageData: freshRawCoverageData, stamp: now});
|
||||
}
|
||||
@@ -300,14 +308,14 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
|
||||
}
|
||||
|
||||
const ranges = [];
|
||||
let type = Coverage.CoverageType.JavaScript;
|
||||
let type = CoverageType.JavaScript;
|
||||
for (const func of entry.functions) {
|
||||
// Do not coerce undefined to false, i.e. only consider blockLevel to be false
|
||||
// if back-end explicitly provides blockLevel field, otherwise presume blockLevel
|
||||
// coverage is not available. Also, ignore non-block level functions that weren't
|
||||
// ever called.
|
||||
if (func.isBlockCoverage === false && !(func.ranges.length === 1 && !func.ranges[0].count)) {
|
||||
type |= Coverage.CoverageType.JavaScriptPerFunction;
|
||||
type |= CoverageType.JavaScriptPerFunction;
|
||||
}
|
||||
for (const range of func.ranges) {
|
||||
ranges.push(range);
|
||||
@@ -338,7 +346,7 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
|
||||
}
|
||||
const now = Date.now();
|
||||
const freshRawCoverageData = await this._cssModel.takeCoverageDelta();
|
||||
if (this._suspensionState !== Coverage.SuspensionState.Active) {
|
||||
if (this._suspensionState !== SuspensionState.Active) {
|
||||
if (freshRawCoverageData.length > 0) {
|
||||
this._cssBacklog.push({rawCoverageData: freshRawCoverageData, stamp: now});
|
||||
}
|
||||
@@ -382,7 +390,7 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
|
||||
const ranges = /** @type {!Array<!Coverage.RangeUseCount>} */ (entry[1]);
|
||||
const subentry = this._addCoverage(
|
||||
styleSheetHeader, styleSheetHeader.contentLength, styleSheetHeader.startLine, styleSheetHeader.startColumn,
|
||||
ranges, Coverage.CoverageType.CSS, stamp);
|
||||
ranges, CoverageType.CSS, stamp);
|
||||
if (subentry) {
|
||||
updatedEntries.push(subentry);
|
||||
}
|
||||
@@ -442,7 +450,7 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
|
||||
_addStyleSheetToCSSCoverage(styleSheetHeader) {
|
||||
this._addCoverage(
|
||||
styleSheetHeader, styleSheetHeader.contentLength, styleSheetHeader.startLine, styleSheetHeader.startColumn, [],
|
||||
Coverage.CoverageType.CSS, Date.now());
|
||||
CoverageType.CSS, Date.now());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -555,19 +563,14 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
|
||||
await fos.write(JSON.stringify(result, undefined, 2));
|
||||
fos.close();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** @enum {symbol} */
|
||||
Coverage.CoverageModel.Events = {
|
||||
CoverageUpdated: Symbol('CoverageUpdated')
|
||||
};
|
||||
SDK.SDKModel.register(CoverageModel, SDK.Target.Capability.None, false);
|
||||
|
||||
/** @type {number} */
|
||||
Coverage.CoverageModel._coveragePollingPeriodMs = 200;
|
||||
|
||||
SDK.SDKModel.register(Coverage.CoverageModel, SDK.Target.Capability.None, false);
|
||||
|
||||
Coverage.URLCoverageInfo = class {
|
||||
/**
|
||||
* @unrestricted
|
||||
*/
|
||||
export class URLCoverageInfo {
|
||||
/**
|
||||
* @param {string} url
|
||||
*/
|
||||
@@ -645,7 +648,7 @@ Coverage.URLCoverageInfo = class {
|
||||
const key = `${lineOffset}:${columnOffset}`;
|
||||
let entry = this._coverageInfoByLocation.get(key);
|
||||
|
||||
if ((type & Coverage.CoverageType.JavaScript) && !this._coverageInfoByLocation.size) {
|
||||
if ((type & CoverageType.JavaScript) && !this._coverageInfoByLocation.size) {
|
||||
this._isContentScript = /** @type {!SDK.Script} */ (contentProvider).isContentScript();
|
||||
}
|
||||
this._type |= type;
|
||||
@@ -655,7 +658,7 @@ Coverage.URLCoverageInfo = class {
|
||||
return entry;
|
||||
}
|
||||
|
||||
if ((type & Coverage.CoverageType.JavaScript) && !this._coverageInfoByLocation.size) {
|
||||
if ((type & CoverageType.JavaScript) && !this._coverageInfoByLocation.size) {
|
||||
this._isContentScript = /** @type {!SDK.Script} */ (contentProvider).isContentScript();
|
||||
}
|
||||
|
||||
@@ -665,9 +668,12 @@ Coverage.URLCoverageInfo = class {
|
||||
|
||||
return entry;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Coverage.CoverageInfo = class {
|
||||
/**
|
||||
* @unrestricted
|
||||
*/
|
||||
export class CoverageInfo {
|
||||
/**
|
||||
* @param {!Common.ContentProvider} contentProvider
|
||||
* @param {number} size
|
||||
@@ -797,4 +803,39 @@ Coverage.CoverageInfo = class {
|
||||
last = segment.end;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/* Legacy exported object */
|
||||
self.Coverage = self.Coverage || {};
|
||||
|
||||
/* Legacy exported object */
|
||||
Coverage = Coverage || {};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
Coverage.CoverageModel = CoverageModel;
|
||||
|
||||
/** @enum {symbol} */
|
||||
Coverage.CoverageModel.Events = Events;
|
||||
|
||||
/** @type {number} */
|
||||
Coverage.CoverageModel._coveragePollingPeriodMs = _coveragePollingPeriodMs;
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
Coverage.CoverageType = CoverageType;
|
||||
|
||||
/** @enum {symbol} */
|
||||
Coverage.SuspensionState = SuspensionState;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
Coverage.URLCoverageInfo = URLCoverageInfo;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
Coverage.CoverageInfo = CoverageInfo;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
Coverage.CoverageView = class extends UI.VBox {
|
||||
export class CoverageView extends UI.VBox {
|
||||
constructor() {
|
||||
super(true);
|
||||
|
||||
@@ -362,14 +362,14 @@ Coverage.CoverageView = class extends UI.VBox {
|
||||
selectCoverageItemByUrl(url) {
|
||||
this._listView.selectByUrl(url);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Coverage.CoverageView._extensionBindingsURLPrefix = 'extensions::';
|
||||
CoverageView._extensionBindingsURLPrefix = 'extensions::';
|
||||
|
||||
/**
|
||||
* @implements {UI.ActionDelegate}
|
||||
*/
|
||||
Coverage.CoverageView.ActionDelegate = class {
|
||||
export class ActionDelegate {
|
||||
/**
|
||||
* @override
|
||||
* @param {!UI.Context} context
|
||||
@@ -401,4 +401,123 @@ Coverage.CoverageView.ActionDelegate = class {
|
||||
console.assert(false, `Unknown action: ${actionId}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @implements {SourceFrame.LineDecorator}
|
||||
*/
|
||||
export class LineDecorator {
|
||||
constructor() {
|
||||
/** @type {!WeakMap<!TextEditor.CodeMirrorTextEditor, function(!Common.Event)>} */
|
||||
this._listeners = new WeakMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @param {!Workspace.UISourceCode} uiSourceCode
|
||||
* @param {!TextEditor.CodeMirrorTextEditor} textEditor
|
||||
*/
|
||||
decorate(uiSourceCode, textEditor) {
|
||||
const decorations = uiSourceCode.decorationsForType(Coverage.CoverageDecorationManager.decoratorType);
|
||||
if (!decorations || !decorations.size) {
|
||||
this._uninstallGutter(textEditor);
|
||||
return;
|
||||
}
|
||||
const decorationManager =
|
||||
/** @type {!Coverage.CoverageDecorationManager} */ (decorations.values().next().value.data());
|
||||
decorationManager.usageByLine(uiSourceCode).then(lineUsage => {
|
||||
textEditor.operation(() => this._innerDecorate(uiSourceCode, textEditor, lineUsage));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Workspace.UISourceCode} uiSourceCode
|
||||
* @param {!TextEditor.CodeMirrorTextEditor} textEditor
|
||||
* @param {!Array<boolean>} lineUsage
|
||||
*/
|
||||
_innerDecorate(uiSourceCode, textEditor, lineUsage) {
|
||||
const gutterType = Coverage.CoverageView.LineDecorator._gutterType;
|
||||
this._uninstallGutter(textEditor);
|
||||
if (lineUsage.length) {
|
||||
this._installGutter(textEditor, uiSourceCode.url());
|
||||
}
|
||||
for (let line = 0; line < lineUsage.length; ++line) {
|
||||
// Do not decorate the line if we don't have data.
|
||||
if (typeof lineUsage[line] !== 'boolean') {
|
||||
continue;
|
||||
}
|
||||
const className = lineUsage[line] ? 'text-editor-coverage-used-marker' : 'text-editor-coverage-unused-marker';
|
||||
const gutterElement = createElementWithClass('div', className);
|
||||
textEditor.setGutterDecoration(line, gutterType, gutterElement);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} url - the url of the file this click handler will select in the coverage drawer
|
||||
* @return {function(!Common.Event)}
|
||||
*/
|
||||
makeGutterClickHandler(url) {
|
||||
function handleGutterClick(event) {
|
||||
const eventData = /** @type {!SourceFrame.SourcesTextEditor.GutterClickEventData} */ (event.data);
|
||||
if (eventData.gutterType !== Coverage.CoverageView.LineDecorator._gutterType) {
|
||||
return;
|
||||
}
|
||||
const coverageViewId = 'coverage';
|
||||
UI.viewManager.showView(coverageViewId).then(() => UI.viewManager.view(coverageViewId).widget()).then(widget => {
|
||||
const matchFormattedSuffix = url.match(/(.*):formatted$/);
|
||||
const urlWithoutFormattedSuffix = (matchFormattedSuffix && matchFormattedSuffix[1]) || url;
|
||||
widget.selectCoverageItemByUrl(urlWithoutFormattedSuffix);
|
||||
});
|
||||
}
|
||||
return handleGutterClick;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!TextEditor.CodeMirrorTextEditor} textEditor - the text editor to install the gutter on
|
||||
* @param {string} url - the url of the file in the text editor
|
||||
*/
|
||||
_installGutter(textEditor, url) {
|
||||
let listener = this._listeners.get(textEditor);
|
||||
if (!listener) {
|
||||
listener = this.makeGutterClickHandler(url);
|
||||
this._listeners.set(textEditor, listener);
|
||||
}
|
||||
textEditor.installGutter(Coverage.CoverageView.LineDecorator._gutterType, false);
|
||||
textEditor.addEventListener(SourceFrame.SourcesTextEditor.Events.GutterClick, listener, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!TextEditor.CodeMirrorTextEditor} textEditor - the text editor to uninstall the gutter from
|
||||
*/
|
||||
_uninstallGutter(textEditor) {
|
||||
textEditor.uninstallGutter(Coverage.CoverageView.LineDecorator._gutterType);
|
||||
const listener = this._listeners.get(textEditor);
|
||||
if (listener) {
|
||||
textEditor.removeEventListener(SourceFrame.SourcesTextEditor.Events.GutterClick, listener, this);
|
||||
this._listeners.delete(textEditor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LineDecorator._gutterType = 'CodeMirror-gutter-coverage';
|
||||
|
||||
/* Legacy exported object */
|
||||
self.Coverage = self.Coverage || {};
|
||||
|
||||
/* Legacy exported object */
|
||||
Coverage = Coverage || {};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
Coverage.CoverageView = CoverageView;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
Coverage.CoverageView.LineDecorator = LineDecorator;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
Coverage.CoverageView.ActionDelegate = ActionDelegate;
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright 2019 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import './CoverageModel.js';
|
||||
import './CoverageListView.js';
|
||||
import './CoverageView.js';
|
||||
import './CoverageDecorationManager.js';
|
||||
|
||||
import * as CoverageDecorationManager from './CoverageDecorationManager.js';
|
||||
import * as CoverageListView from './CoverageListView.js';
|
||||
import * as CoverageModel from './CoverageModel.js';
|
||||
import * as CoverageView from './CoverageView.js';
|
||||
|
||||
export {
|
||||
CoverageDecorationManager,
|
||||
CoverageListView,
|
||||
CoverageModel,
|
||||
CoverageView,
|
||||
};
|
||||
@@ -50,7 +50,8 @@
|
||||
"sources",
|
||||
"data_grid"
|
||||
],
|
||||
"scripts": [
|
||||
"scripts": [],
|
||||
"modules": [
|
||||
"CoverageModel.js",
|
||||
"CoverageListView.js",
|
||||
"CoverageView.js",
|
||||
|
||||
Reference in New Issue
Block a user