diff --git a/cli/run/getConfigPath.ts b/cli/run/getConfigPath.ts index 322b363d358..c9a29dba737 100644 --- a/cli/run/getConfigPath.ts +++ b/cli/run/getConfigPath.ts @@ -1,13 +1,13 @@ -import { readdirSync } from 'fs'; +import { promises as fs } from 'fs'; import { resolve } from 'path'; import { cwd } from 'process'; import { handleError } from '../logging'; const DEFAULT_CONFIG_BASE = 'rollup.config'; -export function getConfigPath(commandConfig: string | true): string { +export async function getConfigPath(commandConfig: string | true): Promise { if (commandConfig === true) { - return resolve(findConfigFileNameInCwd()); + return resolve(await findConfigFileNameInCwd()); } if (commandConfig.slice(0, 5) === 'node:') { const pkgName = commandConfig.slice(5); @@ -30,8 +30,8 @@ export function getConfigPath(commandConfig: string | true): string { return resolve(commandConfig); } -function findConfigFileNameInCwd(): string { - const filesInWorkingDir = new Set(readdirSync(cwd())); +async function findConfigFileNameInCwd(): Promise { + const filesInWorkingDir = new Set(await fs.readdir(cwd())); for (const extension of ['mjs', 'cjs', 'ts']) { const fileName = `${DEFAULT_CONFIG_BASE}.${extension}`; if (filesInWorkingDir.has(fileName)) return fileName; diff --git a/cli/run/index.ts b/cli/run/index.ts index ed4478fa6d4..44278c1b90a 100644 --- a/cli/run/index.ts +++ b/cli/run/index.ts @@ -89,7 +89,7 @@ async function getConfigs( command: any ): Promise<{ options: MergedRollupOptions[]; warnings: BatchWarnings }> { if (command.config) { - const configFile = getConfigPath(command.config); + const configFile = await getConfigPath(command.config); const { options, warnings } = await loadAndParseConfigFile(configFile, command); return { options, warnings }; } diff --git a/cli/run/loadConfigFile.ts b/cli/run/loadConfigFile.ts index 3b07543aa6d..18c45e3fe8a 100644 --- a/cli/run/loadConfigFile.ts +++ b/cli/run/loadConfigFile.ts @@ -1,4 +1,4 @@ -import { realpathSync } from 'fs'; +import { promises as fs } from 'fs'; import { extname, isAbsolute } from 'path'; import { pathToFileURL } from 'url'; import * as rollup from '../../src/node-entry'; @@ -57,7 +57,7 @@ async function loadConfigFile( return getConfigList(configFileExport, commandOptions); } -function getDefaultFromCjs(namespace: GenericConfigObject) { +function getDefaultFromCjs(namespace: GenericConfigObject): unknown { return namespace.__esModule ? namespace.default : namespace; } @@ -103,7 +103,7 @@ async function getDefaultFromTranspiledConfigFile( } async function loadConfigFromBundledFile(fileName: string, bundledCode: string): Promise { - const resolvedFileName = realpathSync(fileName); + const resolvedFileName = await fs.realpath(fileName); const extension = extname(resolvedFileName); const defaultLoader = require.extensions[extension]; require.extensions[extension] = (module: NodeModule, requiredFileName: string) => { diff --git a/cli/run/watch-cli.ts b/cli/run/watch-cli.ts index 3e8e619a961..ee8e0f3d61b 100644 --- a/cli/run/watch-cli.ts +++ b/cli/run/watch-cli.ts @@ -1,4 +1,4 @@ -import { type FSWatcher, readFileSync } from 'fs'; +import { type FSWatcher, promises } from 'fs'; import chokidar from 'chokidar'; import dateTime from 'date-time'; import ms from 'pretty-ms'; @@ -22,7 +22,7 @@ export async function watch(command: Record): Promise { let watcher: RollupWatcher; let configWatcher: FSWatcher; let resetScreen: (heading: string) => void; - const configFile = command.config ? getConfigPath(command.config) : null; + const configFile = command.config ? await getConfigPath(command.config) : null; onExit(close); process.on('uncaughtException', close); @@ -40,7 +40,7 @@ export async function watch(command: Record): Promise { async function reloadConfigFile() { try { - const newConfigFileData = readFileSync(configFile, 'utf-8'); + const newConfigFileData = await promises.readFile(configFile, 'utf8'); if (newConfigFileData === configFileData) { return; } diff --git a/src/ModuleLoader.ts b/src/ModuleLoader.ts index 648d9aba78b..57f27726f1c 100644 --- a/src/ModuleLoader.ts +++ b/src/ModuleLoader.ts @@ -253,7 +253,8 @@ export class ModuleLoader { let source: LoadResult; try { source = await this.readQueue.run( - async () => (await this.pluginDriver.hookFirst('load', [id])) ?? (await readFile(id)) + async () => + (await this.pluginDriver.hookFirst('load', [id])) ?? (await readFile(id, 'utf8')) ); } catch (err: any) { timeEnd('load modules', 3); diff --git a/src/utils/fs.ts b/src/utils/fs.ts index 0dc8d1ab65d..f313e7486c3 100644 --- a/src/utils/fs.ts +++ b/src/utils/fs.ts @@ -1,28 +1,10 @@ -import fs from 'fs'; +import { promises as fs } from 'fs'; import { dirname } from './path'; -export * from 'fs'; +export const { lstat, readdir, readFile, realpath } = fs; -export const readFile = (file: string): Promise => - new Promise((fulfil, reject) => - fs.readFile(file, 'utf-8', (err, contents) => (err ? reject(err) : fulfil(contents))) - ); - -function mkdirpath(path: string) { - const dir = dirname(path); - fs.mkdirSync(dir, { recursive: true }); -} - -export function writeFile(dest: string, data: string | Uint8Array): Promise { - return new Promise((fulfil, reject) => { - mkdirpath(dest); - - fs.writeFile(dest, data, err => { - if (err) { - reject(err); - } else { - fulfil(); - } - }); - }); +export async function writeFile(dest: string, data: string | Uint8Array): Promise { + const dir = dirname(dest); + await fs.mkdir(dir, { recursive: true }); + await fs.writeFile(dest, data); } diff --git a/src/utils/resolveId.ts b/src/utils/resolveId.ts index 221cab3f79b..7e21b753aa7 100644 --- a/src/utils/resolveId.ts +++ b/src/utils/resolveId.ts @@ -1,6 +1,6 @@ import { CustomPluginOptions, Plugin, ResolvedId, ResolveIdResult } from '../rollup/types'; import { PluginDriver } from './PluginDriver'; -import { lstatSync, readdirSync, realpathSync } from './fs'; +import { lstat, readdir, realpath } from './fs'; import { basename, dirname, isAbsolute, resolve } from './path'; import { resolveIdViaPlugins } from './resolveIdViaPlugins'; @@ -45,26 +45,28 @@ export async function resolveId( ); } -function addJsExtensionIfNecessary(file: string, preserveSymlinks: boolean) { - let found = findFile(file, preserveSymlinks); - if (found) return found; - found = findFile(file + '.mjs', preserveSymlinks); - if (found) return found; - found = findFile(file + '.js', preserveSymlinks); - return found; +async function addJsExtensionIfNecessary( + file: string, + preserveSymlinks: boolean +): Promise { + return ( + (await findFile(file, preserveSymlinks)) ?? + (await findFile(file + '.mjs', preserveSymlinks)) ?? + (await findFile(file + '.js', preserveSymlinks)) + ); } -function findFile(file: string, preserveSymlinks: boolean): string | undefined { +async function findFile(file: string, preserveSymlinks: boolean): Promise { try { - const stats = lstatSync(file); + const stats = await lstat(file); if (!preserveSymlinks && stats.isSymbolicLink()) - return findFile(realpathSync(file), preserveSymlinks); + return await findFile(await realpath(file), preserveSymlinks); if ((preserveSymlinks && stats.isSymbolicLink()) || stats.isFile()) { // check case const name = basename(file); - const files = readdirSync(dirname(file)); + const files = await readdir(dirname(file)); - if (files.indexOf(name) !== -1) return file; + if (files.includes(name)) return file; } } catch { // suppress diff --git a/test/function/samples/max-parallel-file-reads-default/_config.js b/test/function/samples/max-parallel-file-reads-default/_config.js index 306952571a6..6284f3cb199 100644 --- a/test/function/samples/max-parallel-file-reads-default/_config.js +++ b/test/function/samples/max-parallel-file-reads-default/_config.js @@ -1,24 +1,23 @@ const assert = require('assert'); -const fs = require('fs'); +const { promises } = require('fs'); -const fsReadFile = fs.readFile; +const fsReadFile = promises.readFile; let currentReads = 0; let maxReads = 0; module.exports = { description: 'maxParallelFileReads not set', before() { - fs.readFile = (path, options, callback) => { + promises.readFile = async (path, options) => { currentReads++; maxReads = Math.max(maxReads, currentReads); - fsReadFile(path, options, (err, data) => { - currentReads--; - callback(err, data); - }); + const content = await fsReadFile(path, options); + currentReads--; + return content; }; }, after() { - fs.readFile = fsReadFile; + promises.readFile = fsReadFile; assert.strictEqual(maxReads, 5, 'Wrong number of parallel file reads: ' + maxReads); } }; diff --git a/test/function/samples/max-parallel-file-reads-error/_config.js b/test/function/samples/max-parallel-file-reads-error/_config.js index c535cfaa10c..08e4c8d3e85 100644 --- a/test/function/samples/max-parallel-file-reads-error/_config.js +++ b/test/function/samples/max-parallel-file-reads-error/_config.js @@ -1,8 +1,8 @@ -const fs = require('fs'); -const path = require('path'); +const { promises } = require('fs'); +const { join } = require('path'); const { loader } = require('../../../utils.js'); -const fsReadFile = fs.readFile; +const fsReadFile = promises.readFile; module.exports = { description: 'maxParallelFileReads: fileRead error is forwarded', @@ -13,19 +13,19 @@ module.exports = { }) }, before() { - fs.readFile = (path, options, callback) => { + promises.readFile = (path, options) => { if (path.endsWith('dep.js')) { - return callback(new Error('broken')); + throw new Error('broken'); } - fsReadFile(path, options, callback); + fsReadFile(path, options); }; }, after() { - fs.readFile = fsReadFile; + promises.readFile = fsReadFile; }, error: { - message: `Could not load ${path.join(__dirname, 'dep.js')} (imported by main): broken`, - watchFiles: ['main', path.join(__dirname, 'dep.js')] + message: `Could not load ${join(__dirname, 'dep.js')} (imported by main): broken`, + watchFiles: ['main', join(__dirname, 'dep.js')] } }; diff --git a/test/function/samples/max-parallel-file-reads-infinity/_config.js b/test/function/samples/max-parallel-file-reads-infinity/_config.js index 486ed945fd9..82cad65d3ca 100644 --- a/test/function/samples/max-parallel-file-reads-infinity/_config.js +++ b/test/function/samples/max-parallel-file-reads-infinity/_config.js @@ -1,7 +1,7 @@ const assert = require('assert'); -const fs = require('fs'); +const { promises } = require('fs'); -const fsReadFile = fs.readFile; +const fsReadFile = promises.readFile; let currentReads = 0; let maxReads = 0; @@ -11,17 +11,16 @@ module.exports = { maxParallelFileReads: 0 }, before() { - fs.readFile = (path, options, callback) => { + promises.readFile = async (path, options) => { currentReads++; maxReads = Math.max(maxReads, currentReads); - fsReadFile(path, options, (err, data) => { - currentReads--; - callback(err, data); - }); + const content = await fsReadFile(path, options); + currentReads--; + return content; }; }, after() { - fs.readFile = fsReadFile; + promises.readFile = fsReadFile; assert.strictEqual(maxReads, 5, 'Wrong number of parallel file reads: ' + maxReads); } }; diff --git a/test/function/samples/max-parallel-file-reads-set/_config.js b/test/function/samples/max-parallel-file-reads-set/_config.js index de68cc464a9..6b247837538 100644 --- a/test/function/samples/max-parallel-file-reads-set/_config.js +++ b/test/function/samples/max-parallel-file-reads-set/_config.js @@ -1,7 +1,7 @@ const assert = require('assert'); -const fs = require('fs'); +const { promises } = require('fs'); -const fsReadFile = fs.readFile; +const fsReadFile = promises.readFile; let currentReads = 0; let maxReads = 0; @@ -11,17 +11,16 @@ module.exports = { maxParallelFileReads: 3 }, before() { - fs.readFile = (path, options, callback) => { + promises.readFile = async (path, options) => { currentReads++; maxReads = Math.max(maxReads, currentReads); - fsReadFile(path, options, (err, data) => { - currentReads--; - callback(err, data); - }); + const content = await fsReadFile(path, options); + currentReads--; + return content; }; }, after() { - fs.readFile = fsReadFile; + promises.readFile = fsReadFile; assert.strictEqual(maxReads, 3, 'Wrong number of parallel file reads: ' + maxReads); } }; diff --git a/test/function/samples/max-parallel-file-reads-with-plugin/_config.js b/test/function/samples/max-parallel-file-reads-with-plugin/_config.js index 0e8b6fd3ea3..b4df04b0a34 100644 --- a/test/function/samples/max-parallel-file-reads-with-plugin/_config.js +++ b/test/function/samples/max-parallel-file-reads-with-plugin/_config.js @@ -1,7 +1,7 @@ const assert = require('assert'); -const fs = require('fs'); +const { promises } = require('fs'); -const fsReadFile = fs.readFile; +const fsReadFile = promises.readFile; let currentReads = 0; let maxReads = 0; @@ -11,26 +11,23 @@ module.exports = { maxParallelFileReads: 3, plugins: [ { - async load(id) { - return new Promise((fulfil, reject) => - fs.readFile(id, 'utf-8', (err, contents) => (err ? reject(err) : fulfil(contents))) - ); + load(id) { + return promises.readFile(id, 'utf-8'); } } ] }, before() { - fs.readFile = (path, options, callback) => { + promises.readFile = async (path, options) => { currentReads++; maxReads = Math.max(maxReads, currentReads); - fsReadFile(path, options, (err, data) => { - currentReads--; - callback(err, data); - }); + const content = await fsReadFile(path, options); + currentReads--; + return content; }; }, after() { - fs.readFile = fsReadFile; + promises.readFile = fsReadFile; assert.strictEqual(maxReads, 3, 'Wrong number of parallel file reads: ' + maxReads); } };