Skip to content

Commit 5fc0fce

Browse files
authoredDec 12, 2020
core(artifacts): merge ConsoleMessages and RuntimeExceptions artifacts (#11663)
BREAKING CHANGE: RuntimeExceptions are now exposed in ConsoleMessages. BREAKING CHANGE: ConsoleMessages artifact has a new shape.
1 parent 70106be commit 5fc0fce

File tree

22 files changed

+1178
-949
lines changed

22 files changed

+1178
-949
lines changed
 

‎lighthouse-cli/test/cli/__snapshots__/index-test.js.snap

-3
Original file line numberDiff line numberDiff line change
@@ -1347,9 +1347,6 @@ Object {
13471347
Object {
13481348
"path": "viewport-dimensions",
13491349
},
1350-
Object {
1351-
"path": "runtime-exceptions",
1352-
},
13531350
Object {
13541351
"path": "console-messages",
13551352
},

‎lighthouse-cli/test/fixtures/dobetterweb/dbw_tester.html

+5
Original file line numberDiff line numberDiff line change
@@ -470,5 +470,10 @@ <h2>Do better web tester page</h2>
470470
window.webkitRequestFileSystem(window.TEMPORARY, 1024 * 1024, onInitFs, console.error);
471471
</script>
472472

473+
<script>
474+
// Log console.error calls in the console.
475+
console.error('Error! Error!');
476+
</script>
477+
473478
</body>
474479
</html>

‎lighthouse-cli/test/smokehouse/test-definitions/dobetterweb/dbw-expectations.js

+10-5
Original file line numberDiff line numberDiff line change
@@ -212,11 +212,11 @@ const expectations = [
212212
score: 0,
213213
details: {
214214
items: {
215-
length: '6 +/- 1',
215+
length: '7 +/- 1',
216216
// COMPAT: In 89.0.4351.0 we observed one additional runtime error and it's origin is currently unknown
217217
// TODO: Investigate and resolve it's presence. https://github.com/GoogleChrome/lighthouse/issues/11803
218218
// {
219-
// source: 'Runtime.exception',
219+
// source: 'exception',
220220
// description: 'TypeError: the given value is not a Promise',
221221
// url: 'http://localhost:10200/dobetterweb/third_party/aggressive-promise-polyfill.js',
222222
// },
@@ -228,7 +228,7 @@ const expectations = [
228228
// url: 'http://localhost:10200/dobetterweb/dbw_tester.html',
229229
// },
230230
// {
231-
// source: 'Runtime.exception',
231+
// source: 'exception',
232232
// description: /^Error: A distinctive error\s+at http:\/\/localhost:10200\/dobetterweb\/dbw_tester.html:\d+:\d+$/,
233233
// url: 'http://localhost:10200/dobetterweb/dbw_tester.html',
234234
// },
@@ -252,6 +252,11 @@ const expectations = [
252252
// description: 'Failed to load resource: the server responded with a status of 404 (Not Found)',
253253
// url: 'http://localhost:10200/dobetterweb/unknown404.css?delay=200',
254254
// },
255+
// {
256+
// source: 'console.error',
257+
// description: 'Error! Error!',
258+
// url: 'http://localhost:10200/dobetterweb/dbw_tester.html',
259+
// },
255260
// ],
256261
},
257262
},
@@ -408,10 +413,10 @@ const expectations = [
408413
},
409414
'dom-size': {
410415
score: 1,
411-
numericValue: 148,
416+
numericValue: 149,
412417
details: {
413418
items: [
414-
{statistic: 'Total DOM Elements', value: 148},
419+
{statistic: 'Total DOM Elements', value: 149},
415420
{statistic: 'Maximum DOM Depth', value: 4},
416421
{
417422
statistic: 'Maximum Child Elements',

‎lighthouse-core/audits/byte-efficiency/polyfill-graph-data.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,4 @@
5656
},
5757
"maxSize": 77759,
5858
"baseSize": 3708
59-
}
59+
}

‎lighthouse-core/audits/deprecations.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -56,26 +56,26 @@ class Deprecations extends Audit {
5656
static audit(artifacts) {
5757
const entries = artifacts.ConsoleMessages;
5858

59-
const deprecations = entries.filter(log => log.entry.source === 'deprecation').map(log => {
59+
const deprecations = entries.filter(log => log.source === 'deprecation').map(log => {
6060
// HTML deprecations will have no url and no way to attribute to a specific line.
6161
/** @type {LH.Audit.Details.SourceLocationValue=} */
6262
let source;
63-
if (log.entry.url) {
63+
if (log.url) {
6464
// JS deprecations will have a stack trace.
6565
// CSS deprecations only expose a line number.
66-
const topCallFrame = log.entry.stackTrace && log.entry.stackTrace.callFrames[0];
67-
const line = log.entry.lineNumber || 0;
66+
const topCallFrame = log.stackTrace && log.stackTrace.callFrames[0];
67+
const line = log.lineNumber || 0;
6868
const column = topCallFrame ? topCallFrame.columnNumber : 0;
6969
source = {
7070
type: 'source-location',
71-
url: log.entry.url,
71+
url: log.url,
7272
urlProvider: 'network',
7373
line,
7474
column,
7575
};
7676
}
7777
return {
78-
value: log.entry.text,
78+
value: log.text,
7979
source,
8080
};
8181
});

‎lighthouse-core/audits/errors-in-console.js

+8-25
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class ErrorLogs extends Audit {
3939
title: str_(UIStrings.title),
4040
failureTitle: str_(UIStrings.failureTitle),
4141
description: str_(UIStrings.description),
42-
requiredArtifacts: ['ConsoleMessages', 'RuntimeExceptions'],
42+
requiredArtifacts: ['ConsoleMessages'],
4343
};
4444
}
4545

@@ -81,36 +81,19 @@ class ErrorLogs extends Audit {
8181
/** @type {AuditOptions} */
8282
const auditOptions = context.options;
8383

84-
const consoleEntries = artifacts.ConsoleMessages;
85-
const runtimeExceptions = artifacts.RuntimeExceptions;
8684
/** @type {Array<{source: string, description: string|undefined, url: string|undefined}>} */
87-
const consoleRows =
88-
consoleEntries.filter(log => log.entry && log.entry.level === 'error')
85+
const consoleRows = artifacts.ConsoleMessages
86+
.filter(item => item.level === 'error')
8987
.map(item => {
9088
return {
91-
source: item.entry.source,
92-
description: item.entry.text,
93-
url: item.entry.url,
89+
source: item.source,
90+
description: item.text,
91+
url: item.url,
9492
};
9593
});
9694

97-
const runtimeExRows =
98-
runtimeExceptions.filter(entry => entry.exceptionDetails !== undefined)
99-
.map(entry => {
100-
const description = entry.exceptionDetails.exception ?
101-
entry.exceptionDetails.exception.description : entry.exceptionDetails.text;
102-
103-
return {
104-
source: 'Runtime.exception',
105-
description,
106-
url: entry.exceptionDetails.url,
107-
};
108-
});
109-
110-
const tableRows = ErrorLogs.filterAccordingToOptions(
111-
consoleRows.concat(runtimeExRows),
112-
auditOptions
113-
).sort((a, b) => (a.description || '').localeCompare(b.description || ''));
95+
const tableRows = ErrorLogs.filterAccordingToOptions(consoleRows, auditOptions)
96+
.sort((a, b) => (a.description || '').localeCompare(b.description || ''));
11497

11598
/** @type {LH.Audit.Details.Table['headings']} */
11699
const headings = [

‎lighthouse-core/audits/violation-audit.js

-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ class ViolationAudit extends Audit {
1616
static getViolationResults(artifacts, pattern) {
1717
const seen = new Set();
1818
return artifacts.ConsoleMessages
19-
.map(message => message.entry)
2019
.filter(entry => entry.url && entry.source === 'violation' && pattern.test(entry.text))
2120
.map(entry => ({label: `line: ${entry.lineNumber}`, url: entry.url}))
2221
.filter(entry => {

‎lighthouse-core/config/default-config.js

-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,6 @@ const defaultConfig = {
138138
'css-usage',
139139
'js-usage',
140140
'viewport-dimensions',
141-
'runtime-exceptions',
142141
'console-messages',
143142
'anchor-elements',
144143
'image-elements',

‎lighthouse-core/gather/gatherers/console-messages.js

+112-12
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,152 @@
11
/**
2-
* @license Copyright 2017 The Lighthouse Authors. All Rights Reserved.
2+
* @license Copyright 2020 The Lighthouse Authors. All Rights Reserved.
33
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
44
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
55
*/
66

77
/**
8-
* @fileoverview Gathers console deprecation and intervention warnings logged by Chrome.
8+
* @fileoverview Gathers all entries logged to the console, including console API calls,
9+
* exceptions, and browser reports (on violations, interventions, deprecations, etc.).
910
*/
1011

1112
'use strict';
1213

1314
const Gatherer = require('./gatherer.js');
1415

16+
/**
17+
* @param {LH.Crdp.Runtime.RemoteObject} obj
18+
* @return {string}
19+
*/
20+
function remoteObjectToString(obj) {
21+
if (typeof obj.value !== 'undefined' || obj.type === 'undefined') {
22+
return String(obj.value);
23+
}
24+
if (typeof obj.description === 'string' && obj.description !== obj.className) {
25+
return obj.description;
26+
}
27+
const type = obj.subtype || obj.type;
28+
const className = obj.className || 'Object';
29+
// Simulate calling String() on the object.
30+
return `[${type} ${className}]`;
31+
}
32+
1533
class ConsoleMessages extends Gatherer {
1634
constructor() {
1735
super();
18-
/** @type {Array<LH.Crdp.Log.EntryAddedEvent>} */
36+
/** @type {LH.Artifacts.ConsoleMessage[]} */
1937
this._logEntries = [];
20-
this._onConsoleEntryAdded = this.onConsoleEntry.bind(this);
38+
39+
this._onConsoleAPICalled = this.onConsoleAPICalled.bind(this);
40+
this._onExceptionThrown = this.onExceptionThrown.bind(this);
41+
this._onLogEntryAdded = this.onLogEntry.bind(this);
42+
}
43+
44+
/**
45+
* Handles events for when a script invokes a console API.
46+
* @param {LH.Crdp.Runtime.ConsoleAPICalledEvent} event
47+
*/
48+
onConsoleAPICalled(event) {
49+
const {type} = event;
50+
if (type !== 'warning' && type !== 'error') {
51+
// Only gather warnings and errors for brevity.
52+
return;
53+
}
54+
/** @type {LH.Crdp.Runtime.RemoteObject[]} */
55+
const args = event.args || [];
56+
const text = args.map(remoteObjectToString).join(' ');
57+
if (!text && !event.stackTrace) {
58+
// No useful information from Chrome. Skip.
59+
return;
60+
}
61+
const {url, lineNumber, columnNumber} =
62+
event.stackTrace && event.stackTrace.callFrames[0] || {};
63+
/** @type {LH.Artifacts.ConsoleMessage} */
64+
const consoleMessage = {
65+
eventType: 'consoleAPI',
66+
source: type === 'warning' ? 'console.warn' : 'console.error',
67+
level: type,
68+
text,
69+
stackTrace: event.stackTrace,
70+
timestamp: event.timestamp,
71+
url,
72+
lineNumber,
73+
columnNumber,
74+
};
75+
this._logEntries.push(consoleMessage);
2176
}
2277

2378
/**
24-
* @param {LH.Crdp.Log.EntryAddedEvent} entry
79+
* Handles exception thrown events.
80+
* @param {LH.Crdp.Runtime.ExceptionThrownEvent} event
2581
*/
26-
onConsoleEntry(entry) {
27-
this._logEntries.push(entry);
82+
onExceptionThrown(event) {
83+
const text = event.exceptionDetails.exception ?
84+
event.exceptionDetails.exception.description : event.exceptionDetails.text;
85+
if (!text) {
86+
return;
87+
}
88+
/** @type {LH.Artifacts.ConsoleMessage} */
89+
const consoleMessage = {
90+
eventType: 'exception',
91+
source: 'exception',
92+
level: 'error',
93+
text,
94+
stackTrace: event.exceptionDetails.stackTrace,
95+
timestamp: event.timestamp,
96+
url: event.exceptionDetails.url,
97+
lineNumber: event.exceptionDetails.lineNumber,
98+
columnNumber: event.exceptionDetails.columnNumber,
99+
};
100+
this._logEntries.push(consoleMessage);
101+
}
102+
103+
/**
104+
* Handles browser reports logged to the console, including interventions,
105+
* deprecations, violations, and more.
106+
* @param {LH.Crdp.Log.EntryAddedEvent} event
107+
*/
108+
onLogEntry(event) {
109+
const {source, level, text, stackTrace, timestamp, url, lineNumber} = event.entry;
110+
this._logEntries.push({
111+
eventType: 'protocolLog',
112+
source,
113+
level,
114+
text,
115+
stackTrace,
116+
timestamp,
117+
url,
118+
lineNumber,
119+
});
28120
}
29121

30122
/**
31123
* @param {LH.Gatherer.PassContext} passContext
32124
*/
33125
async beforePass(passContext) {
34126
const driver = passContext.driver;
35-
driver.on('Log.entryAdded', this._onConsoleEntryAdded);
127+
128+
driver.on('Log.entryAdded', this._onLogEntryAdded);
36129
await driver.sendCommand('Log.enable');
37130
await driver.sendCommand('Log.startViolationsReport', {
38131
config: [{name: 'discouragedAPIUse', threshold: -1}],
39132
});
133+
134+
driver.on('Runtime.consoleAPICalled', this._onConsoleAPICalled);
135+
driver.on('Runtime.exceptionThrown', this._onExceptionThrown);
136+
await driver.sendCommand('Runtime.enable');
40137
}
41138

42139
/**
43140
* @param {LH.Gatherer.PassContext} passContext
44141
* @return {Promise<LH.Artifacts['ConsoleMessages']>}
45142
*/
46-
async afterPass(passContext) {
47-
await passContext.driver.sendCommand('Log.stopViolationsReport');
48-
await passContext.driver.off('Log.entryAdded', this._onConsoleEntryAdded);
49-
await passContext.driver.sendCommand('Log.disable');
143+
async afterPass({driver}) {
144+
await driver.sendCommand('Log.stopViolationsReport');
145+
await driver.off('Log.entryAdded', this._onLogEntryAdded);
146+
await driver.sendCommand('Log.disable');
147+
await driver.off('Runtime.consoleAPICalled', this._onConsoleAPICalled);
148+
await driver.off('Runtime.exceptionThrown', this._onExceptionThrown);
149+
await driver.sendCommand('Runtime.disable');
50150
return this._logEntries;
51151
}
52152
}

‎lighthouse-core/gather/gatherers/runtime-exceptions.js

-48
This file was deleted.

0 commit comments

Comments
 (0)
Please sign in to comment.