From 1b9d9e9cc0ea8026b057e1dc28eac625d6646057 Mon Sep 17 00:00:00 2001 From: Jack Franklin Date: Mon, 27 Apr 2020 11:38:17 +0100 Subject: [PATCH] chore: log useful error for Node v14 breakage (#5732) * chore: Useful error for Node v14 breakage There is currently a bug with extract-zip and Node v14.0.0 that causes extractZip to silently fail: https://github.com/puppeteer/puppeteer/issues/5719 Rather than silenty fail if the user is on Node 14 we instead detect that and throw an error directing the user to that bug. The rejection message below is surfaced to the user in the command line. The issue seems to be in streams never resolving so we wrap the call in a timeout and give it 100ms to resolve before deciding on an error. If the user is on Node < 14 we maintain the behaviour we had before this patch. Here's how this change impacts the output on Node 14 and Node 10: Node 10: ``` npm run tsc && rm -r .local-* && node install > puppeteer@3.0.1-post tsc /Users/jacktfranklin/src/puppeteer > tsc --version && tsc -p . && cp src/protocol.d.ts lib/ && cp src/externs.d.ts lib/ Version 3.8.3 Downloading Chromium r737027 - 118.4 Mb [====================] 100% 0.0s Chromium (737027) downloaded to /Users/jacktfranklin/src/puppeteer/.local-chromium/mac-737027 ``` --- Node 14 without this patch: ``` npm run tsc && rm -r .local-* && node install > puppeteer@3.0.1-post tsc /Users/jacktfranklin/src/puppeteer > tsc --version && tsc -p . && cp src/protocol.d.ts lib/ && cp src/externs.d.ts lib/ Version 3.8.3 Downloading Chromium r737027 - 118.4 Mb [====================] 100% 0.0s ``` Note that whilst it doesn't error, it doesn't complete the install. We don't get the success message that we saw above in the Node 10 install. --- Node 14 with this patch: ```npm run tsc && rm -r .local-* && node install > puppeteer@3.0.1-post tsc /Users/jacktfranklin/src/puppeteer > tsc --version && tsc -p . && cp src/protocol.d.ts lib/ && cp src/externs.d.ts lib/ Version 3.8.3 Downloading Chromium r737027 - 118.4 Mb [====================] 100% 0.0s ERROR: Failed to set up Chromium r737027! Set "PUPPETEER_SKIP_DOWNLOAD" env variable to skip download. Puppeteer currently does not work on Node v14 due to an upstream bug. Please see https://github.com/puppeteer/puppeteer/issues/5719 for details. ``` The explicit message should save users a good amount of debugging time. --- src/BrowserFetcher.ts | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/src/BrowserFetcher.ts b/src/BrowserFetcher.ts index cfcb8567e1eed..f2fb815ba4cf6 100644 --- a/src/BrowserFetcher.ts +++ b/src/BrowserFetcher.ts @@ -321,10 +321,45 @@ function install(archivePath: string, folderPath: string): Promise { } async function extractZip(zipPath: string, folderPath: string): Promise { - try { - await extract(zipPath, {dir: folderPath}); - } catch (error) { - return error; + const nodeVersion = process.version; + + /* There is currently a bug with extract-zip and Node v14.0.0 that + * causes extractZip to silently fail: + * https://github.com/puppeteer/puppeteer/issues/5719 + * + * Rather than silenty fail if the user is on Node 14 we instead + * detect that and throw an error directing the user to that bug. The + * rejection message below is surfaced to the user in the command + * line. + * + * The issue seems to be in streams never resolving so we wrap the + * call in a timeout and give it 10s to resolve before deciding on + * an error. + * + * If the user is on Node < 14 we maintain the behaviour we had before + * this patch. + */ + if (nodeVersion.startsWith('v14.')) { + let timeoutReject; + const timeoutPromise = new Promise((resolve, reject) => { timeoutReject = reject; }); + + const timeoutToken = setTimeout(() => { + const error = new Error(`Puppeteer currently does not work on Node v14 due to an upstream bug. Please see: https://github.com/puppeteer/puppeteer/issues/5719 for details.`); + timeoutReject(error); + }, 10 * 1000); + + await Promise.race([ + extract(zipPath, {dir: folderPath}), + timeoutPromise + ]); + + clearTimeout(timeoutToken); + } else { + try { + await extract(zipPath, {dir: folderPath}); + } catch (error) { + return error; + } } }