lighthouse 12.0.0-dev.20240512 → 12.0.0-dev.20240514
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/cli/run.js +5 -38
- package/cli/test/smokehouse/lighthouse-runners/bundle.js +1 -1
- package/core/gather/driver/navigation.js +1 -1
- package/core/gather/driver.d.ts +0 -12
- package/core/gather/driver.js +1 -26
- package/core/gather/gatherers/inspector-issues.js +1 -0
- package/core/gather/session.d.ts +2 -0
- package/core/gather/session.js +22 -1
- package/package.json +4 -5
- package/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +1 -0
- package/types/artifacts.d.ts +1 -0
- package/types/gatherer.d.ts +1 -2
package/cli/run.js
CHANGED
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
import path from 'path';
|
|
10
10
|
import os from 'os';
|
|
11
11
|
|
|
12
|
-
import psList from 'ps-list';
|
|
13
12
|
import * as ChromeLauncher from 'chrome-launcher';
|
|
14
13
|
import yargsParser from 'yargs-parser';
|
|
15
14
|
import log from 'lighthouse-logger';
|
|
@@ -176,36 +175,6 @@ async function saveResults(runnerResult, flags) {
|
|
|
176
175
|
}
|
|
177
176
|
}
|
|
178
177
|
|
|
179
|
-
/**
|
|
180
|
-
* Attempt to kill the launched Chrome, if defined.
|
|
181
|
-
* @param {ChromeLauncher.LaunchedChrome=} launchedChrome
|
|
182
|
-
* @return {Promise<void>}
|
|
183
|
-
*/
|
|
184
|
-
async function potentiallyKillChrome(launchedChrome) {
|
|
185
|
-
if (!launchedChrome) return;
|
|
186
|
-
|
|
187
|
-
/** @type {NodeJS.Timeout} */
|
|
188
|
-
let timeout;
|
|
189
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
190
|
-
timeout = setTimeout(reject, 5000, new Error('Timed out waiting to kill Chrome'));
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
return Promise.race([
|
|
194
|
-
launchedChrome.kill(),
|
|
195
|
-
timeoutPromise,
|
|
196
|
-
]).catch(async err => {
|
|
197
|
-
const runningProcesses = await psList();
|
|
198
|
-
if (!runningProcesses.some(proc => proc.pid === launchedChrome.pid)) {
|
|
199
|
-
log.warn('CLI', 'Warning: Chrome process could not be killed because it already exited.');
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
throw new Error(`Couldn't quit Chrome process. ${err}`);
|
|
204
|
-
}).finally(() => {
|
|
205
|
-
clearTimeout(timeout);
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
|
|
209
178
|
/**
|
|
210
179
|
* @param {string} url
|
|
211
180
|
* @param {LH.CliFlags} flags
|
|
@@ -214,12 +183,10 @@ async function potentiallyKillChrome(launchedChrome) {
|
|
|
214
183
|
*/
|
|
215
184
|
async function runLighthouse(url, flags, config) {
|
|
216
185
|
/** @param {any} reason */
|
|
217
|
-
|
|
186
|
+
function handleTheUnhandled(reason) {
|
|
218
187
|
process.stderr.write(`Unhandled Rejection. Reason: ${reason}\n`);
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
process.exit(1);
|
|
222
|
-
}, 100);
|
|
188
|
+
launchedChrome?.kill();
|
|
189
|
+
process.exit(1);
|
|
223
190
|
}
|
|
224
191
|
process.on('unhandledRejection', handleTheUnhandled);
|
|
225
192
|
|
|
@@ -247,7 +214,7 @@ async function runLighthouse(url, flags, config) {
|
|
|
247
214
|
await saveResults(runnerResult, flags);
|
|
248
215
|
}
|
|
249
216
|
|
|
250
|
-
|
|
217
|
+
launchedChrome?.kill();
|
|
251
218
|
process.removeListener('unhandledRejection', handleTheUnhandled);
|
|
252
219
|
|
|
253
220
|
// Runtime errors indicate something was *very* wrong with the page result.
|
|
@@ -265,7 +232,7 @@ async function runLighthouse(url, flags, config) {
|
|
|
265
232
|
|
|
266
233
|
return runnerResult;
|
|
267
234
|
} catch (err) {
|
|
268
|
-
|
|
235
|
+
launchedChrome?.kill();
|
|
269
236
|
return printErrorAndExit(err);
|
|
270
237
|
}
|
|
271
238
|
}
|
|
@@ -123,7 +123,7 @@ async function gotoURL(driver, requestor, options) {
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
const waitConditions = await Promise.race([
|
|
126
|
-
|
|
126
|
+
session.onCrashPromise(),
|
|
127
127
|
Promise.all(waitConditionPromises),
|
|
128
128
|
]);
|
|
129
129
|
const timedOut = waitConditions.some(condition => condition.timedOut);
|
package/core/gather/driver.d.ts
CHANGED
|
@@ -14,10 +14,6 @@ export class Driver implements LH.Gatherer.Driver {
|
|
|
14
14
|
/** @type {Fetcher|undefined} */
|
|
15
15
|
_fetcher: Fetcher | undefined;
|
|
16
16
|
defaultSession: import("../../types/gatherer.js").default.ProtocolSession;
|
|
17
|
-
fatalRejection: {
|
|
18
|
-
promise: Promise<never>;
|
|
19
|
-
rej: (_: Error) => void;
|
|
20
|
-
};
|
|
21
17
|
/** @return {LH.Gatherer.Driver['executionContext']} */
|
|
22
18
|
get executionContext(): ExecutionContext;
|
|
23
19
|
get fetcher(): any;
|
|
@@ -27,14 +23,6 @@ export class Driver implements LH.Gatherer.Driver {
|
|
|
27
23
|
url(): Promise<string>;
|
|
28
24
|
/** @return {Promise<void>} */
|
|
29
25
|
connect(): Promise<void>;
|
|
30
|
-
/**
|
|
31
|
-
* If the target crashes, we can't continue gathering.
|
|
32
|
-
*
|
|
33
|
-
* FWIW, if the target unexpectedly detaches (eg the user closed the tab), pptr will
|
|
34
|
-
* catch that and reject into our this._cdpSession.send, which we'll alrady handle appropriately
|
|
35
|
-
* @return {void}
|
|
36
|
-
*/
|
|
37
|
-
listenForCrashes(): void;
|
|
38
26
|
/** @return {Promise<void>} */
|
|
39
27
|
disconnect(): Promise<void>;
|
|
40
28
|
}
|
package/core/gather/driver.js
CHANGED
|
@@ -8,7 +8,6 @@ import log from 'lighthouse-logger';
|
|
|
8
8
|
|
|
9
9
|
import {ExecutionContext} from './driver/execution-context.js';
|
|
10
10
|
import {TargetManager} from './driver/target-manager.js';
|
|
11
|
-
import {LighthouseError} from '../lib/lh-error.js';
|
|
12
11
|
import {Fetcher} from './fetcher.js';
|
|
13
12
|
import {NetworkMonitor} from './driver/network-monitor.js';
|
|
14
13
|
|
|
@@ -29,6 +28,7 @@ const throwingSession = {
|
|
|
29
28
|
sendCommand: throwNotConnectedFn,
|
|
30
29
|
sendCommandAndIgnore: throwNotConnectedFn,
|
|
31
30
|
dispose: throwNotConnectedFn,
|
|
31
|
+
onCrashPromise: throwNotConnectedFn,
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
/** @implements {LH.Gatherer.Driver} */
|
|
@@ -48,12 +48,6 @@ class Driver {
|
|
|
48
48
|
this._fetcher = undefined;
|
|
49
49
|
|
|
50
50
|
this.defaultSession = throwingSession;
|
|
51
|
-
|
|
52
|
-
// Poor man's Promise.withResolvers()
|
|
53
|
-
/** @param {Error} _ */
|
|
54
|
-
let rej = _ => {};
|
|
55
|
-
const promise = /** @type {Promise<never>} */ (new Promise((_, theRej) => rej = theRej));
|
|
56
|
-
this.fatalRejection = {promise, rej};
|
|
57
51
|
}
|
|
58
52
|
|
|
59
53
|
/** @return {LH.Gatherer.Driver['executionContext']} */
|
|
@@ -93,30 +87,11 @@ class Driver {
|
|
|
93
87
|
this._networkMonitor = new NetworkMonitor(this._targetManager);
|
|
94
88
|
await this._networkMonitor.enable();
|
|
95
89
|
this.defaultSession = this._targetManager.rootSession();
|
|
96
|
-
this.listenForCrashes();
|
|
97
90
|
this._executionContext = new ExecutionContext(this.defaultSession);
|
|
98
91
|
this._fetcher = new Fetcher(this.defaultSession);
|
|
99
92
|
log.timeEnd(status);
|
|
100
93
|
}
|
|
101
94
|
|
|
102
|
-
/**
|
|
103
|
-
* If the target crashes, we can't continue gathering.
|
|
104
|
-
*
|
|
105
|
-
* FWIW, if the target unexpectedly detaches (eg the user closed the tab), pptr will
|
|
106
|
-
* catch that and reject into our this._cdpSession.send, which we'll alrady handle appropriately
|
|
107
|
-
* @return {void}
|
|
108
|
-
*/
|
|
109
|
-
listenForCrashes() {
|
|
110
|
-
this.defaultSession.on('Inspector.targetCrashed', async _ => {
|
|
111
|
-
log.error('Driver', 'Inspector.targetCrashed');
|
|
112
|
-
// Manually detach so no more CDP traffic is attempted.
|
|
113
|
-
// Don't await, else our rejection will be a 'Target closed' protocol error on cross-talk CDP calls.
|
|
114
|
-
void this.defaultSession.dispose();
|
|
115
|
-
this.fatalRejection.rej(new LighthouseError(LighthouseError.errors.TARGET_CRASHED));
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
|
|
120
95
|
/** @return {Promise<void>} */
|
|
121
96
|
async disconnect() {
|
|
122
97
|
if (this.defaultSession === throwingSession) return;
|
package/core/gather/session.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export class ProtocolSession extends ProtocolSession_base implements LH.Gatherer
|
|
|
18
18
|
* @param {LH.CrdpEvents[E]} params
|
|
19
19
|
*/
|
|
20
20
|
_handleProtocolEvent<E extends keyof import("puppeteer-core").ProtocolMapping.Events>(method: E, ...params: import("puppeteer-core").ProtocolMapping.Events[E]): void;
|
|
21
|
+
_targetCrashedPromise: Promise<never>;
|
|
21
22
|
id(): string;
|
|
22
23
|
/** @param {LH.Crdp.Target.TargetInfo} targetInfo */
|
|
23
24
|
setTargetInfo(targetInfo: LH.Crdp.Target.TargetInfo): void;
|
|
@@ -53,6 +54,7 @@ export class ProtocolSession extends ProtocolSession_base implements LH.Gatherer
|
|
|
53
54
|
* @return {Promise<void>}
|
|
54
55
|
*/
|
|
55
56
|
dispose(): Promise<void>;
|
|
57
|
+
onCrashPromise(): Promise<never>;
|
|
56
58
|
}
|
|
57
59
|
export {};
|
|
58
60
|
//# sourceMappingURL=session.d.ts.map
|
package/core/gather/session.js
CHANGED
|
@@ -44,6 +44,22 @@ class ProtocolSession extends CrdpEventEmitter {
|
|
|
44
44
|
this._handleProtocolEvent = this._handleProtocolEvent.bind(this);
|
|
45
45
|
// @ts-expect-error Puppeteer expects the handler params to be type `unknown`
|
|
46
46
|
this._cdpSession.on('*', this._handleProtocolEvent);
|
|
47
|
+
|
|
48
|
+
// If the target crashes, we can't continue gathering.
|
|
49
|
+
// FWIW, if the target unexpectedly detaches (eg the user closed the tab), pptr will
|
|
50
|
+
// catch that and reject in this._cdpSession.send, which is caught by us.
|
|
51
|
+
/** @param {Error} _ */
|
|
52
|
+
let rej = _ => {}; // Poor man's Promise.withResolvers()
|
|
53
|
+
this._targetCrashedPromise = /** @type {Promise<never>} */ (
|
|
54
|
+
new Promise((_, theRej) => rej = theRej));
|
|
55
|
+
this.on('Inspector.targetCrashed', async () => {
|
|
56
|
+
log.error('TargetManager', 'Inspector.targetCrashed');
|
|
57
|
+
// Manually detach so no more CDP traffic is attempted.
|
|
58
|
+
// Don't await, else our rejection will be a 'Target closed' protocol error on cross-talk
|
|
59
|
+
// CDP calls.
|
|
60
|
+
void this.dispose();
|
|
61
|
+
rej(new LighthouseError(LighthouseError.errors.TARGET_CRASHED));
|
|
62
|
+
});
|
|
47
63
|
}
|
|
48
64
|
|
|
49
65
|
id() {
|
|
@@ -114,7 +130,8 @@ class ProtocolSession extends CrdpEventEmitter {
|
|
|
114
130
|
log.formatProtocol('method <= browser ERR', {method}, 'error');
|
|
115
131
|
throw LighthouseError.fromProtocolMessage(method, error);
|
|
116
132
|
});
|
|
117
|
-
const resultWithTimeoutPromise =
|
|
133
|
+
const resultWithTimeoutPromise =
|
|
134
|
+
Promise.race([resultPromise, timeoutPromise, this._targetCrashedPromise]);
|
|
118
135
|
|
|
119
136
|
return resultWithTimeoutPromise.finally(() => {
|
|
120
137
|
if (timeout) clearTimeout(timeout);
|
|
@@ -142,6 +159,10 @@ class ProtocolSession extends CrdpEventEmitter {
|
|
|
142
159
|
this._cdpSession.off('*', this._handleProtocolEvent);
|
|
143
160
|
await this._cdpSession.detach().catch(e => log.verbose('session', 'detach failed', e.message));
|
|
144
161
|
}
|
|
162
|
+
|
|
163
|
+
onCrashPromise() {
|
|
164
|
+
return this._targetCrashedPromise;
|
|
165
|
+
}
|
|
145
166
|
}
|
|
146
167
|
|
|
147
168
|
export {ProtocolSession};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lighthouse",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "12.0.0-dev.
|
|
4
|
+
"version": "12.0.0-dev.20240514",
|
|
5
5
|
"description": "Automated auditing, performance metrics, and best practices for the web.",
|
|
6
6
|
"main": "./core/index.js",
|
|
7
7
|
"bin": {
|
|
@@ -185,7 +185,7 @@
|
|
|
185
185
|
"chrome-launcher": "^1.1.1",
|
|
186
186
|
"configstore": "^5.0.1",
|
|
187
187
|
"csp_evaluator": "1.1.1",
|
|
188
|
-
"devtools-protocol": "0.0.
|
|
188
|
+
"devtools-protocol": "0.0.1299070",
|
|
189
189
|
"enquirer": "^2.3.6",
|
|
190
190
|
"http-link-header": "^1.1.1",
|
|
191
191
|
"intl-messageformat": "^10.5.3",
|
|
@@ -198,7 +198,6 @@
|
|
|
198
198
|
"metaviewport-parser": "0.3.0",
|
|
199
199
|
"open": "^8.4.0",
|
|
200
200
|
"parse-cache-control": "1.0.1",
|
|
201
|
-
"ps-list": "^8.0.0",
|
|
202
201
|
"puppeteer-core": "^22.6.5",
|
|
203
202
|
"robots-parser": "^3.0.1",
|
|
204
203
|
"semver": "^5.3.0",
|
|
@@ -210,8 +209,8 @@
|
|
|
210
209
|
"yargs-parser": "^21.0.0"
|
|
211
210
|
},
|
|
212
211
|
"resolutions": {
|
|
213
|
-
"puppeteer/**/devtools-protocol": "0.0.
|
|
214
|
-
"puppeteer-core/**/devtools-protocol": "0.0.
|
|
212
|
+
"puppeteer/**/devtools-protocol": "0.0.1299070",
|
|
213
|
+
"puppeteer-core/**/devtools-protocol": "0.0.1299070"
|
|
215
214
|
},
|
|
216
215
|
"repository": "GoogleChrome/lighthouse",
|
|
217
216
|
"keywords": [
|
package/types/artifacts.d.ts
CHANGED
|
@@ -545,6 +545,7 @@ declare module Artifacts {
|
|
|
545
545
|
quirksModeIssue: Crdp.Audits.QuirksModeIssueDetails[];
|
|
546
546
|
cookieIssue: Crdp.Audits.CookieIssueDetails[];
|
|
547
547
|
sharedArrayBufferIssue: Crdp.Audits.SharedArrayBufferIssueDetails[];
|
|
548
|
+
sharedDictionaryIssue: Crdp.Audits.SharedDictionaryIssueDetails[];
|
|
548
549
|
stylesheetLoadingIssue: Crdp.Audits.StylesheetLoadingIssueDetails[];
|
|
549
550
|
federatedAuthUserInfoRequestIssue: Crdp.Audits.FederatedAuthUserInfoRequestIssueDetails[];
|
|
550
551
|
}
|
package/types/gatherer.d.ts
CHANGED
|
@@ -35,6 +35,7 @@ declare module Gatherer {
|
|
|
35
35
|
sendCommand<TMethod extends keyof CrdpCommands>(method: TMethod, ...params: CrdpCommands[TMethod]['paramsType']): Promise<CrdpCommands[TMethod]['returnType']>;
|
|
36
36
|
sendCommandAndIgnore<TMethod extends keyof CrdpCommands>(method: TMethod, ...params: CrdpCommands[TMethod]['paramsType']): Promise<void>;
|
|
37
37
|
dispose(): Promise<void>;
|
|
38
|
+
onCrashPromise(): Promise<never>;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
interface Driver {
|
|
@@ -49,8 +50,6 @@ declare module Gatherer {
|
|
|
49
50
|
off(event: 'protocolevent', callback: (payload: Protocol.RawEventMessage) => void): void
|
|
50
51
|
};
|
|
51
52
|
networkMonitor: NetworkMonitor;
|
|
52
|
-
listenForCrashes: (() => void);
|
|
53
|
-
fatalRejection: {promise: Promise<never>, rej: (reason: Error) => void}
|
|
54
53
|
}
|
|
55
54
|
|
|
56
55
|
interface Context<TDependencies extends DependencyKey = DefaultDependenciesKey> {
|