From 064150f8dd56dfb7b342bee4540cc0cab4fdab8b Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Thu, 3 Jun 2021 09:55:33 -0700 Subject: [PATCH] chore: use fs.promises API instead of promisify (#6871) --- src/cli/fixtures.ts | 3 +-- src/client/android.ts | 5 ++-- src/client/browserContext.ts | 8 ++----- src/client/clientHelper.ts | 3 +-- src/client/elementHandle.ts | 7 ++---- src/client/frame.ts | 7 ++---- src/client/network.ts | 3 +-- src/client/page.ts | 10 +++----- src/dispatchers/artifactDispatcher.ts | 3 +-- src/install/browserFetcher.ts | 7 ++---- src/install/installer.ts | 24 +++++++------------ src/server/android/android.ts | 5 +--- src/server/artifact.ts | 5 ++-- src/server/browserType.ts | 11 ++++----- src/server/chromium/chromium.ts | 4 +--- src/server/chromium/crDevTools.ts | 5 ++-- src/server/chromium/crProtocolHelper.ts | 13 +++++----- src/server/electron/electron.ts | 4 +--- src/server/supplements/har/harTracer.ts | 5 +--- .../supplements/recorder/recorderApp.ts | 6 ++--- src/server/trace/recorder/traceSnapshotter.ts | 5 +--- src/server/trace/recorder/tracing.ts | 11 +++------ src/server/trace/viewer/traceViewer.ts | 5 +--- src/server/validateDependencies.ts | 10 +++----- src/utils/ubuntuVersion.ts | 7 ++---- src/utils/utils.ts | 5 +--- tests/config/browserTest.ts | 5 +--- tests/download.spec.ts | 5 ++-- utils/testserver/index.js | 7 +++--- 29 files changed, 63 insertions(+), 135 deletions(-) diff --git a/src/cli/fixtures.ts b/src/cli/fixtures.ts index fa1d8f5a07..dd89584a2b 100644 --- a/src/cli/fixtures.ts +++ b/src/cli/fixtures.ts @@ -15,7 +15,6 @@ */ import * as fs from 'fs'; -import * as util from 'util'; import * as folio from 'folio'; import type { LaunchOptions, BrowserContextOptions, Page } from '../../types/types'; import type { PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWorkerArgs, PlaywrightWorkerOptions } from '../../types/test'; @@ -139,7 +138,7 @@ export const test = folio.test.extend {}); + await fs.promises.unlink(videoPath).catch(e => {}); })); } }, diff --git a/src/client/android.ts b/src/client/android.ts index cda58c9a7a..c5cc68d55a 100644 --- a/src/client/android.ts +++ b/src/client/android.ts @@ -15,7 +15,6 @@ */ import fs from 'fs'; -import * as util from 'util'; import { isString } from '../utils/utils'; import * as channels from '../protocol/channels'; import { Events } from './events'; @@ -190,7 +189,7 @@ export class AndroidDevice extends ChannelOwner { if (isString(file)) - return (await util.promisify(fs.readFile)(file)).toString('base64'); + return fs.promises.readFile(file, { encoding: 'base64' }).toString(); return file.toString('base64'); } diff --git a/src/client/browserContext.ts b/src/client/browserContext.ts index f3ac2d227e..0ea9f29a54 100644 --- a/src/client/browserContext.ts +++ b/src/client/browserContext.ts @@ -18,7 +18,6 @@ import { Page, BindingCall } from './page'; import * as network from './network'; import * as channels from '../protocol/channels'; -import * as util from 'util'; import fs from 'fs'; import { ChannelOwner } from './channelOwner'; import { deprecate, evaluationScript, urlMatches } from './clientHelper'; @@ -35,9 +34,6 @@ import * as structs from '../../types/structs'; import { CDPSession } from './cdpSession'; import { Tracing } from './tracing'; -const fsWriteFileAsync = util.promisify(fs.writeFile.bind(fs)); -const fsReadFileAsync = util.promisify(fs.readFile.bind(fs)); - export class BrowserContext extends ChannelOwner implements api.BrowserContext { _pages = new Set(); private _routes: { url: URLMatch, handler: network.RouteHandler }[] = []; @@ -289,7 +285,7 @@ export class BrowserContext extends ChannelOwner extends JSHandle implements api.ElementHandle { readonly _elementChannel: channels.ElementHandleChannel; @@ -230,7 +227,7 @@ export class ElementHandle extends JSHandle implements const buffer = Buffer.from(result.binary, 'base64'); if (options.path) { await mkdirIfNeeded(options.path); - await fsWriteFileAsync(options.path, buffer); + await fs.promises.writeFile(options.path, buffer); } return buffer; }); @@ -302,7 +299,7 @@ export async function convertInputFiles(files: string | FilePayload | string[] | if (typeof item === 'string') { return { name: path.basename(item), - buffer: (await util.promisify(fs.readFile)(item)).toString('base64') + buffer: (await fs.promises.readFile(item)).toString('base64') }; } else { return { diff --git a/src/client/frame.ts b/src/client/frame.ts index bb6f1697d4..005c23daed 100644 --- a/src/client/frame.ts +++ b/src/client/frame.ts @@ -22,7 +22,6 @@ import { ElementHandle, convertSelectOptionValues, convertInputFiles } from './e import { assertMaxArguments, JSHandle, serializeArgument, parseResult } from './jsHandle'; import fs from 'fs'; import * as network from './network'; -import * as util from 'util'; import { Page } from './page'; import { EventEmitter } from 'events'; import { Waiter } from './waiter'; @@ -32,8 +31,6 @@ import { urlMatches } from './clientHelper'; import * as api from '../../types/types'; import * as structs from '../../types/structs'; -const fsReadFileAsync = util.promisify(fs.readFile.bind(fs)); - export type WaitForNavigationOptions = { timeout?: number, waitUntil?: LifecycleEvent, @@ -275,7 +272,7 @@ export class Frame extends ChannelOwner { const copy = { ...options }; if (copy.path) { - copy.content = (await fsReadFileAsync(copy.path)).toString(); + copy.content = (await fs.promises.readFile(copy.path)).toString(); copy.content += '//# sourceURL=' + copy.path.replace(/\n/g, ''); } return ElementHandle.from((await channel.addScriptTag({ ...copy })).element); @@ -286,7 +283,7 @@ export class Frame extends ChannelOwner { const copy = { ...options }; if (copy.path) { - copy.content = (await fsReadFileAsync(copy.path)).toString(); + copy.content = (await fs.promises.readFile(copy.path)).toString(); copy.content += '/*# sourceURL=' + copy.path.replace(/\n/g, '') + '*/'; } return ElementHandle.from((await channel.addStyleTag({ ...copy })).element); diff --git a/src/client/network.ts b/src/client/network.ts index 35b61a1e80..2dad65d4bb 100644 --- a/src/client/network.ts +++ b/src/client/network.ts @@ -21,7 +21,6 @@ import { Frame } from './frame'; import { Headers, WaitForEventOptions } from './types'; import fs from 'fs'; import * as mime from 'mime'; -import * as util from 'util'; import { isString, headersObjectToArray, headersArrayToObject } from '../utils/utils'; import { Events } from './events'; import { Page } from './page'; @@ -196,7 +195,7 @@ export class Route extends ChannelOwner & { width?: string | number, height?: string | number, @@ -481,7 +477,7 @@ export class Page extends ChannelOwner => new Promise(resolve => fs.stat(path, err => resolve(!err))); export type OnProgressCallback = (downloadedBytes: number, totalBytes: number) => void; @@ -96,14 +93,14 @@ export async function downloadBrowserWithProgressBar(registry: Registry, browser await extract(zipPath, { dir: browserDirectory}); const executablePath = registry.executablePath(browserName)!; debugLogger.log('install', `fixing permissions at ${executablePath}`); - await chmodAsync(executablePath, 0o755); + await fs.promises.chmod(executablePath, 0o755); } catch (e) { debugLogger.log('install', `FAILED installation ${progressBarName} with error: ${e}`); process.exitCode = 1; throw e; } finally { if (await existsAsync(zipPath)) - await unlinkAsync(zipPath); + await fs.promises.unlink(zipPath); } logPolitely(`${progressBarName} downloaded to ${browserDirectory}`); return true; diff --git a/src/install/installer.ts b/src/install/installer.ts index 620c131837..23b4f6bba4 100644 --- a/src/install/installer.ts +++ b/src/install/installer.ts @@ -16,18 +16,12 @@ import fs from 'fs'; import path from 'path'; -import util from 'util'; import lockfile from 'proper-lockfile'; import {Registry, allBrowserNames, isBrowserDirectory, BrowserName, registryDirectory} from '../utils/registry'; import * as browserFetcher from './browserFetcher'; import { getAsBooleanFromENV, calculateSha1, removeFolders } from '../utils/utils'; -const fsMkdirAsync = util.promisify(fs.mkdir.bind(fs)); -const fsReaddirAsync = util.promisify(fs.readdir.bind(fs)); -const fsReadFileAsync = util.promisify(fs.readFile.bind(fs)); -const fsExistsAsync = (filePath: string) => fsReadFileAsync(filePath).then(() => true).catch(e => false); -const fsUnlinkAsync = util.promisify(fs.unlink.bind(fs)); -const fsWriteFileAsync = util.promisify(fs.writeFile.bind(fs)); +const fsExistsAsync = (filePath: string) => fs.promises.readFile(filePath).then(() => true).catch(e => false); const PACKAGE_PATH = path.join(__dirname, '..', '..'); @@ -38,7 +32,7 @@ export async function installBrowsersWithProgressBar(browserNames: BrowserName[] return false; } - await fsMkdirAsync(registryDirectory, { recursive: true }); + await fs.promises.mkdir(registryDirectory, { recursive: true }); const lockfilePath = path.join(registryDirectory, '__dirlock'); const releaseLock = await lockfile.lock(registryDirectory, { retries: { @@ -56,8 +50,8 @@ export async function installBrowsersWithProgressBar(browserNames: BrowserName[] const linksDir = path.join(registryDirectory, '.links'); try { - await fsMkdirAsync(linksDir, { recursive: true }); - await fsWriteFileAsync(path.join(linksDir, calculateSha1(PACKAGE_PATH)), PACKAGE_PATH); + await fs.promises.mkdir(linksDir, { recursive: true }); + await fs.promises.writeFile(path.join(linksDir, calculateSha1(PACKAGE_PATH)), PACKAGE_PATH); await validateCache(linksDir, browserNames); } finally { await releaseLock(); @@ -67,11 +61,11 @@ export async function installBrowsersWithProgressBar(browserNames: BrowserName[] async function validateCache(linksDir: string, browserNames: BrowserName[]) { // 1. Collect used downloads and package descriptors. const usedBrowserPaths: Set = new Set(); - for (const fileName of await fsReaddirAsync(linksDir)) { + for (const fileName of await fs.promises.readdir(linksDir)) { const linkPath = path.join(linksDir, fileName); let linkTarget = ''; try { - linkTarget = (await fsReadFileAsync(linkPath)).toString(); + linkTarget = (await fs.promises.readFile(linkPath)).toString(); const linkRegistry = new Registry(linkTarget); for (const browserName of allBrowserNames) { if (!linkRegistry.isSupportedBrowser(browserName)) @@ -88,13 +82,13 @@ async function validateCache(linksDir: string, browserNames: BrowserName[]) { usedBrowserPaths.add(usedBrowserPath); } } catch (e) { - await fsUnlinkAsync(linkPath).catch(e => {}); + await fs.promises.unlink(linkPath).catch(e => {}); } } // 2. Delete all unused browsers. if (!getAsBooleanFromENV('PLAYWRIGHT_SKIP_BROWSER_GC')) { - let downloadedBrowsers = (await fsReaddirAsync(registryDirectory)).map(file => path.join(registryDirectory, file)); + let downloadedBrowsers = (await fs.promises.readdir(registryDirectory)).map(file => path.join(registryDirectory, file)); downloadedBrowsers = downloadedBrowsers.filter(file => isBrowserDirectory(file)); const directories = new Set(downloadedBrowsers); for (const browserDirectory of usedBrowserPaths) @@ -110,7 +104,7 @@ async function validateCache(linksDir: string, browserNames: BrowserName[]) { await browserFetcher.downloadBrowserWithProgressBar(myRegistry, browserName).catch(e => { throw new Error(`Failed to download ${browserName}, caused by\n${e.stack}`); }); - await fsWriteFileAsync(markerFilePath(myRegistry.browserDirectory(browserName)), ''); + await fs.promises.writeFile(markerFilePath(myRegistry.browserDirectory(browserName)), ''); } } diff --git a/src/server/android/android.ts b/src/server/android/android.ts index 908bd1c6d3..61fc4106c3 100644 --- a/src/server/android/android.ts +++ b/src/server/android/android.ts @@ -19,7 +19,6 @@ import * as types from '../types'; import { EventEmitter } from 'events'; import fs from 'fs'; import * as stream from 'stream'; -import * as util from 'util'; import * as ws from 'ws'; import { createGuid, makeWaitForNextTask } from '../../utils/utils'; import { BrowserOptions, BrowserProcess, PlaywrightOptions } from '../browser'; @@ -34,8 +33,6 @@ import { AndroidWebView } from '../../protocol/channels'; import { CRPage } from '../chromium/crPage'; import { SdkObject, internalCallMetadata } from '../instrumentation'; -const readFileAsync = util.promisify(fs.readFile); - export interface Backend { devices(): Promise; } @@ -174,7 +171,7 @@ export class AndroidDevice extends SdkObject { debug('pw:android')('Installing the new driver'); for (const file of ['android-driver.apk', 'android-driver-target.apk']) - await this.installApk(await readFileAsync(require.resolve(`../../../bin/${file}`))); + await this.installApk(await fs.promises.readFile(require.resolve(`../../../bin/${file}`))); debug('pw:android')('Starting the new driver'); this.shell('am instrument -w com.microsoft.playwright.androiddriver.test/androidx.test.runner.AndroidJUnitRunner').catch(e => debug('pw:android')(e)); diff --git a/src/server/artifact.ts b/src/server/artifact.ts index d5fe84bbc0..adf8f1b81c 100644 --- a/src/server/artifact.ts +++ b/src/server/artifact.ts @@ -15,7 +15,6 @@ */ import fs from 'fs'; -import * as util from 'util'; import { SdkObject } from './instrumentation'; type SaveCallback = (localPath: string, error?: string) => Promise; @@ -85,7 +84,7 @@ export class Artifact extends SdkObject { return; this._deleted = true; if (fileName) - await util.promisify(fs.unlink)(fileName).catch(e => {}); + await fs.promises.unlink(fileName).catch(e => {}); } async deleteOnContextClose(): Promise { @@ -95,7 +94,7 @@ export class Artifact extends SdkObject { return; this._deleted = true; if (!this._unaccessibleErrorMessage) - await util.promisify(fs.unlink)(this._localPath).catch(e => {}); + await fs.promises.unlink(this._localPath).catch(e => {}); await this.reportFinished('File deleted upon browser context closure.'); } diff --git a/src/server/browserType.ts b/src/server/browserType.ts index d7bea10229..d876f1a1a2 100644 --- a/src/server/browserType.ts +++ b/src/server/browserType.ts @@ -17,7 +17,6 @@ import fs from 'fs'; import * as os from 'os'; import path from 'path'; -import * as util from 'util'; import { BrowserContext, normalizeProxySettings, validateBrowserContextOptions } from './browserContext'; import * as registry from '../utils/registry'; import { ConnectionTransport, WebSocketTransport } from './transport'; @@ -33,8 +32,6 @@ import { helper } from './helper'; import { RecentLogsCollector } from '../utils/debugLogger'; import { CallMetadata, SdkObject } from './instrumentation'; -const mkdirAsync = util.promisify(fs.mkdir); -const mkdtempAsync = util.promisify(fs.mkdtemp); const existsAsync = (path: string): Promise => new Promise(resolve => fs.stat(path, err => resolve(!err))); const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-'); @@ -143,15 +140,15 @@ export abstract class BrowserType extends SdkObject { const tempDirectories = []; if (options.downloadsPath) - await mkdirAsync(options.downloadsPath, { recursive: true }); + await fs.promises.mkdir(options.downloadsPath, { recursive: true }); if (options.tracesDir) - await mkdirAsync(options.tracesDir, { recursive: true }); + await fs.promises.mkdir(options.tracesDir, { recursive: true }); - const artifactsDir = await mkdtempAsync(ARTIFACTS_FOLDER); + const artifactsDir = await fs.promises.mkdtemp(ARTIFACTS_FOLDER); tempDirectories.push(artifactsDir); if (!userDataDir) { - userDataDir = await mkdtempAsync(path.join(os.tmpdir(), `playwright_${this._name}dev_profile-`)); + userDataDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), `playwright_${this._name}dev_profile-`)); tempDirectories.push(userDataDir); } diff --git a/src/server/chromium/chromium.ts b/src/server/chromium/chromium.ts index 815c6c1c8e..4c162b07fc 100644 --- a/src/server/chromium/chromium.ts +++ b/src/server/chromium/chromium.ts @@ -18,7 +18,6 @@ import fs from 'fs'; import os from 'os'; import path from 'path'; -import util from 'util'; import { CRBrowser } from './crBrowser'; import { Env } from '../processLauncher'; import { kBrowserCloseMessageId } from './crConnection'; @@ -37,7 +36,6 @@ import { CallMetadata } from '../instrumentation'; import { findChromiumChannel } from './findChromiumChannel'; import http from 'http'; -const mkdtempAsync = util.promisify(fs.mkdtemp); const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-'); export class Chromium extends BrowserType { @@ -65,7 +63,7 @@ export class Chromium extends BrowserType { if (options.headers) headersMap = headersArrayToObject(options.headers, false); - const artifactsDir = await mkdtempAsync(ARTIFACTS_FOLDER); + const artifactsDir = await fs.promises.mkdtemp(ARTIFACTS_FOLDER); const chromeTransport = await WebSocketTransport.connect(progress, await urlToWSEndpoint(endpointURL), headersMap); const browserProcess: BrowserProcess = { diff --git a/src/server/chromium/crDevTools.ts b/src/server/chromium/crDevTools.ts index 6dae9754f2..47f44d0ad0 100644 --- a/src/server/chromium/crDevTools.ts +++ b/src/server/chromium/crDevTools.ts @@ -15,7 +15,6 @@ */ import fs from 'fs'; -import * as util from 'util'; import { CRSession } from './crConnection'; const kBindingName = '__pw_devtools__'; @@ -44,7 +43,7 @@ export class CRDevTools { if (parsed.method === 'getPreferences') { if (this._prefs === undefined) { try { - const json = await util.promisify(fs.readFile)(this._preferencesPath, 'utf8'); + const json = await fs.promises.readFile(this._preferencesPath, 'utf8'); this._prefs = JSON.parse(json); } catch (e) { this._prefs = {}; @@ -100,7 +99,7 @@ export class CRDevTools { _save() { // Serialize saves to avoid corruption. this._savePromise = this._savePromise.then(async () => { - await util.promisify(fs.writeFile)(this._preferencesPath, JSON.stringify(this._prefs)).catch(e => null); + await fs.promises.writeFile(this._preferencesPath, JSON.stringify(this._prefs)).catch(e => null); }); } } diff --git a/src/server/chromium/crProtocolHelper.ts b/src/server/chromium/crProtocolHelper.ts index 8794f51c4f..4c76569a85 100644 --- a/src/server/chromium/crProtocolHelper.ts +++ b/src/server/chromium/crProtocolHelper.ts @@ -18,7 +18,6 @@ import { CRSession } from './crConnection'; import { Protocol } from './protocol'; import fs from 'fs'; -import * as util from 'util'; import * as types from '../types'; import { mkdirIfNeeded } from '../../utils/utils'; import { splitErrorMessage } from '../../utils/stackTrace'; @@ -43,10 +42,10 @@ export async function releaseObject(client: CRSession, objectId: string) { export async function readProtocolStream(client: CRSession, handle: string, path: string | null): Promise { let eof = false; - let fd: number | undefined; + let fd: fs.promises.FileHandle | undefined; if (path) { await mkdirIfNeeded(path); - fd = await util.promisify(fs.open)(path, 'w'); + fd = await fs.promises.open(path, 'w'); } const bufs = []; while (!eof) { @@ -54,11 +53,11 @@ export async function readProtocolStream(client: CRSession, handle: string, path eof = response.eof; const buf = Buffer.from(response.data, response.base64Encoded ? 'base64' : undefined); bufs.push(buf); - if (path) - await util.promisify(fs.write)(fd!, buf); + if (fd) + await fd.write(buf); } - if (path) - await util.promisify(fs.close)(fd!); + if (fd) + await fd.close(); await client.send('IO.close', {handle}); return Buffer.concat(bufs); } diff --git a/src/server/electron/electron.ts b/src/server/electron/electron.ts index 547104516c..825d8fb2f7 100644 --- a/src/server/electron/electron.ts +++ b/src/server/electron/electron.ts @@ -17,7 +17,6 @@ import fs from 'fs'; import os from 'os'; import path from 'path'; -import util from 'util'; import { CRBrowser, CRBrowserContext } from '../chromium/crBrowser'; import { CRConnection, CRSession } from '../chromium/crConnection'; import { CRExecutionContext } from '../chromium/crExecutionContext'; @@ -37,7 +36,6 @@ import { RecentLogsCollector } from '../../utils/debugLogger'; import { internalCallMetadata, SdkObject } from '../instrumentation'; import * as channels from '../../protocol/channels'; -const mkdtempAsync = util.promisify(fs.mkdtemp); const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-'); export class ElectronApplication extends SdkObject { @@ -125,7 +123,7 @@ export class Electron extends SdkObject { electronArguments.push('--no-sandbox'); } - const artifactsDir = await mkdtempAsync(ARTIFACTS_FOLDER); + const artifactsDir = await fs.promises.mkdtemp(ARTIFACTS_FOLDER); const browserLogsCollector = new RecentLogsCollector(); const { launchedProcess, gracefullyClose, kill } = await launchProcess({ diff --git a/src/server/supplements/har/harTracer.ts b/src/server/supplements/har/harTracer.ts index 81d042aa89..cad34a866a 100644 --- a/src/server/supplements/har/harTracer.ts +++ b/src/server/supplements/har/harTracer.ts @@ -15,15 +15,12 @@ */ import fs from 'fs'; -import * as util from 'util'; import { BrowserContext } from '../../browserContext'; import { helper } from '../../helper'; import * as network from '../../network'; import { Page } from '../../page'; import * as har from './har'; -const fsWriteFileAsync = util.promisify(fs.writeFile.bind(fs)); - type HarOptions = { path: string; omitContent?: boolean; @@ -233,7 +230,7 @@ export class HarTracer { else pageEntry.pageTimings.onLoad = -1; } - await fsWriteFileAsync(this._options.path, JSON.stringify({ log: this._log }, undefined, 2)); + await fs.promises.writeFile(this._options.path, JSON.stringify({ log: this._log }, undefined, 2)); } } diff --git a/src/server/supplements/recorder/recorderApp.ts b/src/server/supplements/recorder/recorderApp.ts index 82172d61aa..14b559c8dd 100644 --- a/src/server/supplements/recorder/recorderApp.ts +++ b/src/server/supplements/recorder/recorderApp.ts @@ -16,7 +16,6 @@ import fs from 'fs'; import path from 'path'; -import * as util from 'util'; import { CRPage } from '../../chromium/crPage'; import { Page } from '../../page'; import { ProgressController } from '../../progress'; @@ -26,7 +25,6 @@ import type { CallLog, EventData, Mode, Source } from './recorderTypes'; import { BrowserContext } from '../../browserContext'; import { isUnderTest } from '../../../utils/utils'; -const readFileAsync = util.promisify(fs.readFile); const existsAsync = (path: string): Promise => new Promise(resolve => fs.stat(path, err => resolve(!err))); declare global { @@ -57,7 +55,7 @@ export class RecorderApp extends EventEmitter { } private async _init() { - const icon = await readFileAsync(require.resolve('../../../web/recorder/app_icon.png')); + const icon = await fs.promises.readFile(require.resolve('../../../web/recorder/app_icon.png')); const crPopup = this._page._delegate as CRPage; await crPopup._mainFrameSession._client.send('Browser.setDockTile', { image: icon.toString('base64') @@ -67,7 +65,7 @@ export class RecorderApp extends EventEmitter { if (route.request().url().startsWith('https://playwright/')) { const uri = route.request().url().substring('https://playwright/'.length); const file = require.resolve('../../../web/recorder/' + uri); - const buffer = await readFileAsync(file); + const buffer = await fs.promises.readFile(file); await route.fulfill({ status: 200, headers: [ diff --git a/src/server/trace/recorder/traceSnapshotter.ts b/src/server/trace/recorder/traceSnapshotter.ts index 1f232f3b1d..5c1b3ab540 100644 --- a/src/server/trace/recorder/traceSnapshotter.ts +++ b/src/server/trace/recorder/traceSnapshotter.ts @@ -17,7 +17,6 @@ import { EventEmitter } from 'events'; import fs from 'fs'; import path from 'path'; -import util from 'util'; import { BrowserContext } from '../../browserContext'; import { Page } from '../../page'; import { FrameSnapshot, ResourceSnapshot } from '../../snapshot/snapshotTypes'; @@ -25,8 +24,6 @@ import { Snapshotter, SnapshotterBlob, SnapshotterDelegate } from '../../snapsho import { ElementHandle } from '../../dom'; import { TraceEvent } from '../common/traceEvents'; -const fsWriteFileAsync = util.promisify(fs.writeFile.bind(fs)); - export class TraceSnapshotter extends EventEmitter implements SnapshotterDelegate { private _snapshotter: Snapshotter; private _resourcesDir: string; @@ -64,7 +61,7 @@ export class TraceSnapshotter extends EventEmitter implements SnapshotterDelegat onBlob(blob: SnapshotterBlob): void { this._writeArtifactChain = this._writeArtifactChain.then(async () => { - await fsWriteFileAsync(path.join(this._resourcesDir, blob.sha1), blob.buffer).catch(() => {}); + await fs.promises.writeFile(path.join(this._resourcesDir, blob.sha1), blob.buffer).catch(() => {}); }); } diff --git a/src/server/trace/recorder/tracing.ts b/src/server/trace/recorder/tracing.ts index b896ca9a96..59884449f7 100644 --- a/src/server/trace/recorder/tracing.ts +++ b/src/server/trace/recorder/tracing.ts @@ -16,7 +16,6 @@ import fs from 'fs'; import path from 'path'; -import util from 'util'; import yazl from 'yazl'; import { calculateSha1, createGuid, mkdirIfNeeded, monotonicTime } from '../../../utils/utils'; import { Artifact } from '../../artifact'; @@ -28,10 +27,6 @@ import { Page } from '../../page'; import * as trace from '../common/traceEvents'; import { TraceSnapshotter } from './traceSnapshotter'; -const fsAppendFileAsync = util.promisify(fs.appendFile.bind(fs)); -const fsWriteFileAsync = util.promisify(fs.writeFile.bind(fs)); -const fsMkdirAsync = util.promisify(fs.mkdir.bind(fs)); - export type TracerOptions = { name?: string; snapshots?: boolean; @@ -80,7 +75,7 @@ export class Tracing implements InstrumentationListener { ); // context + page must be the first events added, no awaits above this line. - await fsMkdirAsync(this._resourcesDir, { recursive: true }); + await fs.promises.mkdir(this._resourcesDir, { recursive: true }); this._context.instrumentation.addListener(this); if (options.snapshots) @@ -179,7 +174,7 @@ export class Tracing implements InstrumentationListener { }; this._appendTraceEvent(event); this._appendEventChain = this._appendEventChain.then(async () => { - await fsWriteFileAsync(path.join(this._resourcesDir!, sha1), params.buffer).catch(() => {}); + await fs.promises.writeFile(path.join(this._resourcesDir!, sha1), params.buffer).catch(() => {}); }); }), ); @@ -207,7 +202,7 @@ export class Tracing implements InstrumentationListener { // Serialize all writes to the trace file. this._appendEventChain = this._appendEventChain.then(async () => { - await fsAppendFileAsync(this._traceFile!, JSON.stringify(event) + '\n'); + await fs.promises.appendFile(this._traceFile!, JSON.stringify(event) + '\n'); }); } } diff --git a/src/server/trace/viewer/traceViewer.ts b/src/server/trace/viewer/traceViewer.ts index 8445f8182d..68d465add2 100644 --- a/src/server/trace/viewer/traceViewer.ts +++ b/src/server/trace/viewer/traceViewer.ts @@ -17,7 +17,6 @@ import fs from 'fs'; import path from 'path'; import { createPlaywright } from '../../playwright'; -import * as util from 'util'; import { PersistentSnapshotStorage, TraceModel } from './traceModel'; import { TraceEvent } from '../common/traceEvents'; import { ServerRouteHandler, HttpServer } from '../../../utils/httpServer'; @@ -27,8 +26,6 @@ import { isUnderTest } from '../../../utils/utils'; import { internalCallMetadata } from '../../instrumentation'; import { ProgressController } from '../../progress'; -const fsReadFileAsync = util.promisify(fs.readFile.bind(fs)); - export class TraceViewer { private _server: HttpServer; private _browserName: string; @@ -76,7 +73,7 @@ export class TraceViewer { response.statusCode = 200; response.setHeader('Content-Type', 'application/json'); (async () => { - const traceContent = await fsReadFileAsync(tracePrefix + '.trace', 'utf8'); + const traceContent = await fs.promises.readFile(tracePrefix + '.trace', 'utf8'); const events = traceContent.split('\n').map(line => line.trim()).filter(line => !!line).map(line => JSON.parse(line)) as TraceEvent[]; const model = new TraceModel(snapshotStorage); model.appendEvents(events, snapshotStorage); diff --git a/src/server/validateDependencies.ts b/src/server/validateDependencies.ts index 765eceac6b..ee76ebf278 100644 --- a/src/server/validateDependencies.ts +++ b/src/server/validateDependencies.ts @@ -14,7 +14,6 @@ * limitations under the License. */ import fs from 'fs'; -import * as util from 'util'; import path from 'path'; import * as os from 'os'; import { getUbuntuVersion } from '../utils/ubuntuVersion'; @@ -22,10 +21,7 @@ import * as registry from '../utils/registry'; import * as utils from '../utils/utils'; import { printDepsWindowsExecutable } from '../utils/binaryPaths'; -const accessAsync = util.promisify(fs.access.bind(fs)); -const checkExecutable = (filePath: string) => accessAsync(filePath, fs.constants.X_OK).then(() => true).catch(e => false); -const statAsync = util.promisify(fs.stat.bind(fs)); -const readdirAsync = util.promisify(fs.readdir.bind(fs)); +const checkExecutable = (filePath: string) => fs.promises.access(filePath, fs.constants.X_OK).then(() => true).catch(e => false); export async function validateHostRequirements(registry: registry.Registry, browserName: registry.BrowserName) { if (utils.getAsBooleanFromENV('PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS')) { @@ -195,8 +191,8 @@ function isSharedLib(basename: string) { } async function executablesOrSharedLibraries(directoryPath: string): Promise { - const allPaths = (await readdirAsync(directoryPath)).map(file => path.resolve(directoryPath, file)); - const allStats = await Promise.all(allPaths.map(aPath => statAsync(aPath))); + const allPaths = (await fs.promises.readdir(directoryPath)).map(file => path.resolve(directoryPath, file)); + const allStats = await Promise.all(allPaths.map(aPath => fs.promises.stat(aPath))); const filePaths = allPaths.filter((aPath, index) => (allStats[index] as any).isFile()); const executablersOrLibraries = (await Promise.all(filePaths.map(async filePath => { diff --git a/src/utils/ubuntuVersion.ts b/src/utils/ubuntuVersion.ts index 0c1e580920..a8b893770e 100644 --- a/src/utils/ubuntuVersion.ts +++ b/src/utils/ubuntuVersion.ts @@ -17,16 +17,13 @@ import fs from 'fs'; import * as os from 'os'; -import * as util from 'util'; - -const readFileAsync = util.promisify(fs.readFile.bind(fs)); export async function getUbuntuVersion(): Promise { if (os.platform() !== 'linux') return ''; - let osReleaseText = await readFileAsync('/etc/upstream-release/lsb-release', 'utf8').catch(e => ''); + let osReleaseText = await fs.promises.readFile('/etc/upstream-release/lsb-release', 'utf8').catch(e => ''); if (!osReleaseText) - osReleaseText = await readFileAsync('/etc/os-release', 'utf8').catch(e => ''); + osReleaseText = await fs.promises.readFile('/etc/os-release', 'utf8').catch(e => ''); if (!osReleaseText) return ''; return getUbuntuVersionInternal(osReleaseText); diff --git a/src/utils/utils.ts b/src/utils/utils.ts index a90135ef9a..b94802920f 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -17,13 +17,10 @@ import path from 'path'; import fs from 'fs'; import removeFolder from 'rimraf'; -import * as util from 'util'; import * as crypto from 'crypto'; import os from 'os'; import { spawn } from 'child_process'; -const mkdirAsync = util.promisify(fs.mkdir.bind(fs)); - export function spawnAsync(cmd: string, args: string[], options: any): Promise<{stdout: string, stderr: string, code: number, error?: Error}> { const process = spawn(cmd, args, options); @@ -134,7 +131,7 @@ export function getAsBooleanFromENV(name: string): boolean { export async function mkdirIfNeeded(filePath: string) { // This will harmlessly throw on windows if the dirname is the root directory. - await mkdirAsync(path.dirname(filePath), {recursive: true}).catch(() => {}); + await fs.promises.mkdir(path.dirname(filePath), {recursive: true}).catch(() => {}); } type HeadersArray = { name: string, value: string }[]; diff --git a/tests/config/browserTest.ts b/tests/config/browserTest.ts index 76979827d1..e6270f1d3a 100644 --- a/tests/config/browserTest.ts +++ b/tests/config/browserTest.ts @@ -20,12 +20,9 @@ import { removeFolders } from '../../lib/utils/utils'; import * as path from 'path'; import * as fs from 'fs'; import * as os from 'os'; -import * as util from 'util'; import { RemoteServer, RemoteServerOptions } from './remoteServer'; import { baseTest, CommonWorkerFixtures } from './baseTest'; -const mkdtempAsync = util.promisify(fs.mkdtemp); - type PlaywrightWorkerOptions = { tracesDir: LaunchOptions['tracesDir']; executablePath: LaunchOptions['executablePath']; @@ -94,7 +91,7 @@ export const playwrightFixtures: folio.Fixtures { - const dir = await mkdtempAsync(path.join(os.tmpdir(), 'playwright-test-')); + const dir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'playwright-test-')); dirs.push(dir); return dir; }); diff --git a/tests/download.spec.ts b/tests/download.spec.ts index 90781eb144..87306fe1c4 100644 --- a/tests/download.spec.ts +++ b/tests/download.spec.ts @@ -17,7 +17,6 @@ import { browserTest as it, expect } from './config/browserTest'; import fs from 'fs'; import path from 'path'; -import util from 'util'; import crypto from 'crypto'; import { chromiumVersionLessThan } from './config/utils'; @@ -152,9 +151,9 @@ it.describe('download event', () => { const dir = testInfo.outputPath('downloads'); const userPath = path.join(dir, 'download.txt'); await download.saveAs(userPath); - expect((await util.promisify(fs.readdir)(dir)).length).toBe(1); + expect((await fs.promises.readdir(dir)).length).toBe(1); await download.saveAs(userPath); - expect((await util.promisify(fs.readdir)(dir)).length).toBe(1); + expect((await fs.promises.readdir(dir)).length).toBe(1); expect(fs.existsSync(userPath)).toBeTruthy(); expect(fs.readFileSync(userPath).toString()).toBe('Hello world'); await page.close(); diff --git a/utils/testserver/index.js b/utils/testserver/index.js index def8c362ff..18d7e9f63d 100644 --- a/utils/testserver/index.js +++ b/utils/testserver/index.js @@ -26,7 +26,6 @@ const WebSocketServer = require('ws').Server; const fulfillSymbol = Symbol('fullfil callback'); const rejectSymbol = Symbol('reject callback'); -const readFileAsync = util.promisify(fs.readFile.bind(fs)); const gzipAsync = util.promisify(zlib.gzip.bind(zlib)); class TestServer { @@ -50,8 +49,8 @@ class TestServer { */ static async createHTTPS(dirPath, port, loopback) { const server = new TestServer(dirPath, port, loopback, { - key: fs.readFileSync(path.join(__dirname, 'key.pem')), - cert: fs.readFileSync(path.join(__dirname, 'cert.pem')), + key: await fs.promises.readFile(path.join(__dirname, 'key.pem')), + cert: await fs.promises.readFile(path.join(__dirname, 'cert.pem')), passphrase: 'aaaa', }); await new Promise(x => server._server.once('listening', x)); @@ -273,7 +272,7 @@ class TestServer { if (this._csp.has(pathName)) response.setHeader('Content-Security-Policy', this._csp.get(pathName)); - const {err, data} = await readFileAsync(filePath).then(data => ({data})).catch(err => ({err})); + const {err, data} = await fs.promises.readFile(filePath).then(data => ({data})).catch(err => ({err})); // The HTTP transaction might be already terminated after async hop here - do nothing in this case. if (response.writableEnded) return;