-
Notifications
You must be signed in to change notification settings - Fork 9.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cli: write report in runLighthouse before quitting Chrome #7339
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,53 +62,57 @@ function getDebuggableChrome(flags) { | |
}); | ||
} | ||
|
||
/** @return {never} */ | ||
function showConnectionError() { | ||
console.error('Unable to connect to Chrome'); | ||
process.exit(_RUNTIME_ERROR_CODE); | ||
return process.exit(_RUNTIME_ERROR_CODE); | ||
} | ||
|
||
/** @return {never} */ | ||
function showProtocolTimeoutError() { | ||
console.error('Debugger protocol timed out while connecting to Chrome.'); | ||
process.exit(_PROTOCOL_TIMEOUT_EXIT_CODE); | ||
return process.exit(_PROTOCOL_TIMEOUT_EXIT_CODE); | ||
} | ||
|
||
/** @param {LH.LighthouseError} err */ | ||
/** @param {LH.LighthouseError} err @return {never} */ | ||
function showPageHungError(err) { | ||
console.error('Page hung:', err.friendlyMessage); | ||
process.exit(_PAGE_HUNG_EXIT_CODE); | ||
return process.exit(_PAGE_HUNG_EXIT_CODE); | ||
} | ||
|
||
/** @param {LH.LighthouseError} err */ | ||
/** @param {LH.LighthouseError} err @return {never} */ | ||
function showInsecureDocumentRequestError(err) { | ||
console.error('Insecure document request:', err.friendlyMessage); | ||
process.exit(_INSECURE_DOCUMENT_REQUEST_EXIT_CODE); | ||
return process.exit(_INSECURE_DOCUMENT_REQUEST_EXIT_CODE); | ||
} | ||
|
||
/** | ||
* @param {LH.LighthouseError} err | ||
* @return {never} | ||
*/ | ||
function showRuntimeError(err) { | ||
console.error('Runtime error encountered:', err.friendlyMessage || err.message); | ||
if (err.stack) { | ||
console.error(err.stack); | ||
} | ||
process.exit(_RUNTIME_ERROR_CODE); | ||
return process.exit(_RUNTIME_ERROR_CODE); | ||
} | ||
|
||
/** | ||
* @param {LH.LighthouseError} err | ||
* @return {never} | ||
*/ | ||
function handleError(err) { | ||
if (err.code === 'ECONNREFUSED') { | ||
showConnectionError(); | ||
return showConnectionError(); | ||
} else if (err.code === 'CRI_TIMEOUT') { | ||
showProtocolTimeoutError(); | ||
return showProtocolTimeoutError(); | ||
} else if (err.code === 'PAGE_HUNG') { | ||
showPageHungError(err); | ||
return showPageHungError(err); | ||
} else if (err.code === 'INSECURE_DOCUMENT_REQUEST') { | ||
showInsecureDocumentRequestError(err); | ||
return showInsecureDocumentRequestError(err); | ||
} else { | ||
showRuntimeError(err); | ||
return showRuntimeError(err); | ||
} | ||
} | ||
|
||
|
@@ -159,66 +163,62 @@ async function saveResults(runnerResult, flags) { | |
} | ||
} | ||
|
||
/** | ||
* Attempt to kill the launched Chrome, if defined. | ||
* @param {ChromeLauncher.LaunchedChrome=} launchedChrome | ||
* @return {Promise<void>} | ||
*/ | ||
async function potentiallyKillChrome(launchedChrome) { | ||
if (!launchedChrome) return; | ||
|
||
try { | ||
await launchedChrome.kill(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we time this out? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
probably, but the Chrome child process still keeps the main process going, so it just prints a We could also |
||
} catch (err) { | ||
process.stderr.write(`Couldn't quit Chrome process. ${err.toString()}\n`); | ||
} | ||
} | ||
|
||
/** | ||
* @param {string} url | ||
* @param {LH.CliFlags} flags | ||
* @param {LH.Config.Json|undefined} config | ||
* @return {Promise<LH.RunnerResult|void>} | ||
* @return {Promise<LH.RunnerResult|undefined>} | ||
*/ | ||
function runLighthouse(url, flags, config) { | ||
/** @type {ChromeLauncher.LaunchedChrome|undefined} */ | ||
let launchedChrome; | ||
const shouldGather = flags.gatherMode || flags.gatherMode === flags.auditMode; | ||
let chromeP = Promise.resolve(); | ||
|
||
process.on('unhandledRejection', async (reason) => { | ||
async function runLighthouse(url, flags, config) { | ||
/** @param {any} reason */ | ||
async function handleTheUnhandled(reason) { | ||
process.stderr.write(`Unhandled Rejection. Reason: ${reason}\n`); | ||
try { | ||
await potentiallyKillChrome(); | ||
} catch (err) { | ||
process.stderr.write(`Couldn't quit Chrome process. ${err.toString()}\n`); | ||
} | ||
await potentiallyKillChrome(launchedChrome); | ||
setTimeout(_ => { | ||
process.exit(1); | ||
}, 100); | ||
}); | ||
|
||
if (shouldGather) { | ||
chromeP = chromeP.then(_ => | ||
getDebuggableChrome(flags).then(launchedChromeInstance => { | ||
launchedChrome = launchedChromeInstance; | ||
flags.port = launchedChrome.port; | ||
}) | ||
); | ||
} | ||
process.on('unhandledRejection', handleTheUnhandled); | ||
|
||
const resultsP = chromeP.then(_ => { | ||
return lighthouse(url, flags, config).then(runnerResult => { | ||
return potentiallyKillChrome().then(_ => runnerResult); | ||
}).then(async runnerResult => { | ||
// If in gatherMode only, there will be no runnerResult. | ||
if (runnerResult) { | ||
await saveResults(runnerResult, flags); | ||
} | ||
/** @type {ChromeLauncher.LaunchedChrome|undefined} */ | ||
let launchedChrome; | ||
|
||
return runnerResult; | ||
}); | ||
}); | ||
try { | ||
const shouldGather = flags.gatherMode || flags.gatherMode === flags.auditMode; | ||
if (shouldGather) { | ||
launchedChrome = await getDebuggableChrome(flags); | ||
flags.port = launchedChrome.port; | ||
} | ||
|
||
return resultsP.catch(err => { | ||
return Promise.resolve() | ||
.then(_ => potentiallyKillChrome()) | ||
.then(_ => handleError(err)); | ||
}); | ||
const runnerResult = await lighthouse(url, flags, config); | ||
|
||
/** | ||
* @return {Promise<{}>} | ||
*/ | ||
function potentiallyKillChrome() { | ||
if (launchedChrome !== undefined) { | ||
return launchedChrome.kill(); | ||
// If in gatherMode only, there will be no runnerResult. | ||
if (runnerResult) { | ||
await saveResults(runnerResult, flags); | ||
} | ||
return Promise.resolve({}); | ||
|
||
await potentiallyKillChrome(launchedChrome); | ||
process.removeListener('unhandledRejection', handleTheUnhandled); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this be removed in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh right 👍 |
||
|
||
return runnerResult; | ||
} catch (err) { | ||
await potentiallyKillChrome(launchedChrome); | ||
handleError(err); | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's the benefit of these
return process.exit
changes?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
purely tsc, you have to return it to take advantage of the
@return {never}
chain