diff --git a/cli/run/batchWarnings.ts b/cli/run/batchWarnings.ts index a18e2e87197..1180a517c72 100644 --- a/cli/run/batchWarnings.ts +++ b/cli/run/batchWarnings.ts @@ -14,11 +14,11 @@ export interface BatchWarnings { export default function batchWarnings(): BatchWarnings { let count = 0; - let deferredWarnings = new Map(); + const deferredWarnings = new Map(); let warningOccurred = false; return { - add: (warning: RollupWarning) => { + add(warning: RollupWarning) { count += 1; warningOccurred = true; @@ -48,7 +48,7 @@ export default function batchWarnings(): BatchWarnings { return count; }, - flush: () => { + flush() { if (count === 0) return; const codes = Array.from(deferredWarnings.keys()).sort( @@ -59,7 +59,7 @@ export default function batchWarnings(): BatchWarnings { deferredHandlers[code](deferredWarnings.get(code)!); } - deferredWarnings = new Map(); + deferredWarnings.clear(); count = 0; }, @@ -72,7 +72,7 @@ export default function batchWarnings(): BatchWarnings { const immediateHandlers: { [code: string]: (warning: RollupWarning) => void; } = { - MISSING_NODE_BUILTINS: warning => { + MISSING_NODE_BUILTINS(warning) { title(`Missing shims for Node.js built-ins`); stderr( @@ -82,7 +82,7 @@ const immediateHandlers: { ); }, - UNKNOWN_OPTION: warning => { + UNKNOWN_OPTION(warning) { title(`You have passed an unrecognized option`); stderr(warning.message); } @@ -138,7 +138,7 @@ const deferredHandlers: { } }, - MIXED_EXPORTS: warnings => { + MIXED_EXPORTS(warnings) { title('Mixing named and default exports'); info(`https://rollupjs.org/guide/en/#outputexports`); stderr(bold('The following entry modules are using named and default exports together:')); @@ -204,9 +204,7 @@ const deferredHandlers: { title(`Broken sourcemap`); info('https://rollupjs.org/guide/en/#warning-sourcemap-is-likely-to-be-incorrect'); - const plugins = [ - ...new Set(warnings.map(warning => warning.plugin).filter(Boolean)) - ] as string[]; + const plugins = [...new Set(warnings.map(({ plugin }) => plugin).filter(Boolean))] as string[]; stderr( `Plugins that transform code (such as ${printQuotedStringList( plugins @@ -224,13 +222,12 @@ const deferredHandlers: { title('Unresolved dependencies'); info('https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency'); - const dependencies = new Map(); + const dependencies = new Map(); for (const warning of warnings) { - getOrCreate(dependencies, warning.source, () => []).push(warning.importer); + getOrCreate(dependencies, warning.source, () => []).push(warning.importer!); } - for (const dependency of dependencies.keys()) { - const importers = dependencies.get(dependency); + for (const [dependency, importers] of dependencies) { stderr(`${bold(dependency)} (imported by ${importers.join(', ')})`); } }, @@ -243,7 +240,7 @@ const deferredHandlers: { ' imported from external module "' + warning.source + '" but never used in ' + - printQuotedStringList((warning.sources as string[]).map(id => relativeId(id))) + printQuotedStringList(warning.sources!.map(id => relativeId(id))) ); } } diff --git a/cli/run/index.ts b/cli/run/index.ts index 5c47db14e17..1c457e98041 100644 --- a/cli/run/index.ts +++ b/cli/run/index.ts @@ -1,3 +1,4 @@ +import { env } from 'process'; import type { MergedRollupOptions } from '../../src/rollup/types'; import { isWatchEnabled } from '../../src/utils/options/mergeOptions'; import { getAliasName } from '../../src/utils/relativeId'; @@ -48,11 +49,7 @@ export default async function runRollup(command: Record): Promise { arg.split(',').forEach((pair: string) => { const [key, ...value] = pair.split(':'); - if (value.length) { - process.env[key] = value.join(':'); - } else { - process.env[key] = String(true); - } + env[key] = value.length === 0 ? String(true) : value.join(':'); }); }); } diff --git a/cli/run/timings.ts b/cli/run/timings.ts index 4b4fbb400ad..6d66124a7e9 100644 --- a/cli/run/timings.ts +++ b/cli/run/timings.ts @@ -3,10 +3,9 @@ import type { SerializedTimings } from '../../src/rollup/types'; import { bold, underline } from '../../src/utils/colors'; export function printTimings(timings: SerializedTimings): void { - Object.keys(timings).forEach(label => { + Object.entries(timings).forEach(([label, [time, memory, total]]) => { const appliedColor = label[0] === '#' ? (label[1] !== '#' ? underline : bold) : (text: string) => text; - const [time, memory, total] = timings[label]; const row = `${label}: ${time.toFixed(0)}ms, ${prettyBytes(memory)} / ${prettyBytes(total)}`; console.info(appliedColor(row)); }); diff --git a/src/Bundle.ts b/src/Bundle.ts index fc48ccdf18e..53b1f2b87f4 100644 --- a/src/Bundle.ts +++ b/src/Bundle.ts @@ -35,7 +35,7 @@ export default class Bundle { constructor( private readonly outputOptions: NormalizedOutputOptions, - private readonly unsetOptions: Set, + private readonly unsetOptions: ReadonlySet, private readonly inputOptions: NormalizedInputOptions, private readonly pluginDriver: PluginDriver, private readonly graph: Graph @@ -189,14 +189,14 @@ export default class Bundle { ); (file as OutputAsset).type = 'asset'; } - if (this.outputOptions.validate && typeof (file as OutputChunk).code == 'string') { + if (this.outputOptions.validate && 'code' in file) { try { - this.graph.contextParse((file as OutputChunk).code, { + this.graph.contextParse(file.code, { allowHashBang: true, ecmaVersion: 'latest' }); } catch (err: any) { - this.inputOptions.onwarn(errChunkInvalid(file as OutputChunk, err)); + this.inputOptions.onwarn(errChunkInvalid(file, err)); } } } diff --git a/src/Chunk.ts b/src/Chunk.ts index 4629c4148a5..42a0ee0c7a9 100644 --- a/src/Chunk.ts +++ b/src/Chunk.ts @@ -319,7 +319,7 @@ export default class Chunk { const facades: Chunk[] = []; const entryModules = new Set([...this.entryModules, ...this.implicitEntryModules]); const exposedVariables = new Set( - this.dynamicEntryModules.map(module => module.namespace) + this.dynamicEntryModules.map(({ namespace }) => namespace) ); for (const module of entryModules) { if (module.preserveSignature) { @@ -333,6 +333,7 @@ export default class Chunk { new Set( module.chunkNames.filter(({ isUserDefined }) => isUserDefined).map(({ name }) => name) ), + // mapping must run after Set 'name' dedupe name => ({ name }) @@ -451,7 +452,7 @@ export default class Chunk { const extension = extname(sanitizedId); const fileName = renderNamePattern(pattern, 'output.entryFileNames', { assetExtname: () => (NON_ASSET_EXTENSIONS.includes(extension) ? '' : extension), - ext: () => extension.substr(1), + ext: () => extension.substring(1), extname: () => extension, format: () => options.format as string, name: () => this.getChunkName() @@ -467,7 +468,7 @@ export default class Chunk { const extension = extname(sanitizedId); const fileName = renderNamePattern(pattern, 'output.entryFileNames', { assetExtname: () => (NON_ASSET_EXTENSIONS.includes(extension) ? '' : extension), - ext: () => extension.substr(1), + ext: () => extension.substring(1), extname: () => extension, format: () => options.format as string, name: () => getAliasName(sanitizedId) @@ -1162,7 +1163,7 @@ export default class Chunk { let imported: string; let needsLiveBinding = false; if (exportName[0] === '*') { - const id = exportName.substr(1); + const id = exportName.substring(1); if (interop(id) === 'defaultOnly') { this.inputOptions.onwarn(errUnexpectedNamespaceReexport(id)); } diff --git a/src/Module.ts b/src/Module.ts index 789b5cad9b9..e65975a4325 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -264,12 +264,13 @@ export default class Module { const { dynamicImports, dynamicImporters, - reexportDescriptions, implicitlyLoadedAfter, implicitlyLoadedBefore, - sources, - importers + importers, + reexportDescriptions, + sources } = this; + this.info = { ast: null, code: null, @@ -281,13 +282,7 @@ export default class Module { get dynamicallyImportedIds() { // We cannot use this.dynamicDependencies because this is needed before // dynamicDependencies are populated - const dynamicallyImportedIds: string[] = []; - for (const { id } of dynamicImports) { - if (id) { - dynamicallyImportedIds.push(id); - } - } - return dynamicallyImportedIds; + return dynamicImports.map(({ id }) => id).filter((id): id is string => id != null); }, get dynamicImporters() { return dynamicImporters.sort(); @@ -305,7 +300,7 @@ export default class Module { false, options ); - return module.info.moduleSideEffects; + return this.moduleSideEffects; }, id, get implicitlyLoadedAfterOneOf() { diff --git a/src/ModuleLoader.ts b/src/ModuleLoader.ts index 9589da12e51..729afd56185 100644 --- a/src/ModuleLoader.ts +++ b/src/ModuleLoader.ts @@ -439,9 +439,8 @@ export class ModuleLoader { return error(errInternalIdCannotBeExternal(source, importer)); } return Promise.resolve(externalModule); - } else { - return this.fetchModule(resolvedId, importer, false, false); } + return this.fetchModule(resolvedId, importer, false, false); } private async fetchStaticDependencies( @@ -673,13 +672,11 @@ export class ModuleLoader { } as ResolvedId; } if (resolution == null) { - return (module.resolvedIds[specifier] = - module.resolvedIds[specifier] || - this.handleResolveId( - await this.resolveId(specifier, module.id, EMPTY_OBJECT, false), - specifier, - module.id - )); + return (module.resolvedIds[specifier] ??= this.handleResolveId( + await this.resolveId(specifier, module.id, EMPTY_OBJECT, false), + specifier, + module.id + )); } return this.handleResolveId( this.getResolvedIdWithDefaults( diff --git a/src/ast/nodes/MetaProperty.ts b/src/ast/nodes/MetaProperty.ts index e8868968998..5ec993c9bc0 100644 --- a/src/ast/nodes/MetaProperty.ts +++ b/src/ast/nodes/MetaProperty.ts @@ -43,7 +43,7 @@ export default class MetaProperty extends NodeBase { getReferencedFileName(outputPluginDriver: PluginDriver): string | null { const metaProperty = this.metaProperty as string | null; if (metaProperty && metaProperty.startsWith(FILE_PREFIX)) { - return outputPluginDriver.getFileName(metaProperty.substr(FILE_PREFIX.length)); + return outputPluginDriver.getFileName(metaProperty.substring(FILE_PREFIX.length)); } return null; } @@ -91,7 +91,7 @@ export default class MetaProperty extends NodeBase { let chunkReferenceId: string | null = null; let fileName: string; if (metaProperty.startsWith(FILE_PREFIX)) { - referenceId = metaProperty.substr(FILE_PREFIX.length); + referenceId = metaProperty.substring(FILE_PREFIX.length); fileName = outputPluginDriver.getFileName(referenceId); } else if (metaProperty.startsWith(ASSET_PREFIX)) { warnDeprecation( @@ -99,7 +99,7 @@ export default class MetaProperty extends NodeBase { true, this.context.options ); - assetReferenceId = metaProperty.substr(ASSET_PREFIX.length); + assetReferenceId = metaProperty.substring(ASSET_PREFIX.length); fileName = outputPluginDriver.getFileName(assetReferenceId); } else { warnDeprecation( @@ -107,7 +107,7 @@ export default class MetaProperty extends NodeBase { true, this.context.options ); - chunkReferenceId = metaProperty.substr(CHUNK_PREFIX.length); + chunkReferenceId = metaProperty.substring(CHUNK_PREFIX.length); fileName = outputPluginDriver.getFileName(chunkReferenceId); } const relativePath = normalize(relative(dirname(chunkId), fileName)); diff --git a/src/ast/values.ts b/src/ast/values.ts index 0c636e53a6c..019d79f4028 100644 --- a/src/ast/values.ts +++ b/src/ast/values.ts @@ -236,9 +236,8 @@ export function getLiteralMembersForValue return literalNumberMembers; case 'string': return literalStringMembers; - default: - return Object.create(null); } + return Object.create(null); } export function hasMemberEffectWhenCalled( diff --git a/src/rollup/rollup.ts b/src/rollup/rollup.ts index 037986872e4..68cd3dd04d6 100644 --- a/src/rollup/rollup.ts +++ b/src/rollup/rollup.ts @@ -137,12 +137,11 @@ function applyOptionHook(watchMode: boolean) { } function normalizePlugins(plugins: readonly Plugin[], anonymousPrefix: string): void { - for (let pluginIndex = 0; pluginIndex < plugins.length; pluginIndex++) { - const plugin = plugins[pluginIndex]; + plugins.forEach((plugin, index) => { if (!plugin.name) { - plugin.name = `${anonymousPrefix}${pluginIndex + 1}`; + plugin.name = `${anonymousPrefix}${index + 1}`; } - } + }); } async function handleGenerateWrite( diff --git a/src/utils/FileEmitter.ts b/src/utils/FileEmitter.ts index 2845bcafff6..18edfa2ec96 100644 --- a/src/utils/FileEmitter.ts +++ b/src/utils/FileEmitter.ts @@ -42,16 +42,17 @@ function generateAssetFileName( : outputOptions.assetFileNames, 'output.assetFileNames', { - ext: () => extname(emittedName).substr(1), + ext: () => extname(emittedName).substring(1), extname: () => extname(emittedName), hash() { - const hash = createHash(); - hash.update(emittedName); - hash.update(':'); - hash.update(source); - return hash.digest('hex').substr(0, 8); + return createHash() + .update(emittedName) + .update(':') + .update(source) + .digest('hex') + .substring(0, 8); }, - name: () => emittedName.substr(0, emittedName.length - extname(emittedName).length) + name: () => emittedName.substring(0, emittedName.length - extname(emittedName).length) } ), bundle @@ -165,7 +166,7 @@ export class FileEmitter { } public assertAssetsFinalized = (): void => { - for (const [referenceId, emittedFile] of this.filesByReferenceId.entries()) { + for (const [referenceId, emittedFile] of this.filesByReferenceId) { if (emittedFile.type === 'asset' && typeof emittedFile.fileName !== 'string') return error(errNoAssetSourceSet(emittedFile.name || referenceId)); } @@ -192,9 +193,8 @@ export class FileEmitter { } if (emittedFile.type === 'chunk') { return this.emitChunk(emittedFile); - } else { - return this.emitAsset(emittedFile); } + return this.emitAsset(emittedFile); }; public getFileName = (fileReferenceId: string): string => { @@ -202,9 +202,8 @@ export class FileEmitter { if (!emittedFile) return error(errFileReferenceIdNotFoundForFilename(fileReferenceId)); if (emittedFile.type === 'chunk') { return getChunkFileName(emittedFile, this.facadeChunkByModule); - } else { - return getAssetFileName(emittedFile, fileReferenceId); } + return getAssetFileName(emittedFile, fileReferenceId); }; public setAssetSource = (referenceId: string, requestedSource: unknown): void => { @@ -241,7 +240,7 @@ export class FileEmitter { reserveFileNameInBundle(emittedFile.fileName, this.bundle, this.options.onwarn); } } - for (const [referenceId, consumedFile] of this.filesByReferenceId.entries()) { + for (const [referenceId, consumedFile] of this.filesByReferenceId) { if (consumedFile.type === 'asset' && consumedFile.source !== undefined) { this.finalizeAsset(consumedFile, consumedFile.source, referenceId, this.bundle); } @@ -250,15 +249,14 @@ export class FileEmitter { private assignReferenceId(file: ConsumedFile, idBase: string): string { let referenceId: string | undefined; + do { - const hash = createHash(); - if (referenceId) { - hash.update(referenceId); - } else { - hash.update(idBase); - } - referenceId = hash.digest('hex').substr(0, 8); + referenceId = createHash() + .update(referenceId || idBase) + .digest('hex') + .substring(0, 8); } while (this.filesByReferenceId.has(referenceId)); + this.filesByReferenceId.set(referenceId, file); return referenceId; } diff --git a/src/utils/PluginContext.ts b/src/utils/PluginContext.ts index 2994e32c501..f1ca5bc4dd9 100644 --- a/src/utils/PluginContext.ts +++ b/src/utils/PluginContext.ts @@ -18,17 +18,20 @@ import { throwPluginError } from './pluginUtils'; -// eslint-disable-next-line @typescript-eslint/ban-types -function getDeprecatedContextHandler( - handler: H, +function getDeprecatedContextHandler< + THandler extends (...args: TParams) => TResult, + TParams extends readonly any[], + TResult +>( + handler: THandler, handlerName: string, newHandlerName: string, pluginName: string, activeDeprecation: boolean, options: NormalizedInputOptions -): H { +): THandler { let deprecationWarningShown = false; - return ((...args: any[]) => { + return ((...args: TParams): TResult => { if (!deprecationWarningShown) { deprecationWarningShown = true; warnDeprecation( @@ -41,7 +44,7 @@ function getDeprecatedContextHandler( ); } return handler(...args); - }) as unknown as H; + }) as THandler; } export function getPluginContext( diff --git a/src/utils/PluginDriver.ts b/src/utils/PluginDriver.ts index e37bdab5e0b..512120459e2 100644 --- a/src/utils/PluginDriver.ts +++ b/src/utils/PluginDriver.ts @@ -133,7 +133,7 @@ export class PluginDriver { hookName: H, args: Parameters, replaceContext?: ReplaceContext | null, - skipped?: Set | null + skipped?: ReadonlySet | null ): EnsurePromise> { let promise: EnsurePromise> = Promise.resolve(undefined as any); for (const plugin of this.plugins) { diff --git a/src/utils/hookActions.ts b/src/utils/hookActions.ts index e9f3a38b571..3e669c2a134 100644 --- a/src/utils/hookActions.ts +++ b/src/utils/hookActions.ts @@ -11,24 +11,19 @@ export function resolveAction(actionTuple: [string, string, Parameters]): v } function formatAction([pluginName, hookName, args]: [string, string, Parameters]): string { - let action = `(${pluginName}) ${hookName}`; + const action = `(${pluginName}) ${hookName}`; const s = JSON.stringify; switch (hookName) { case 'resolveId': - action += ` ${s(args[0])} ${s(args[1])}`; - break; + return `${action} ${s(args[0])} ${s(args[1])}`; case 'load': - action += ` ${s(args[0])}`; - break; + return `${action} ${s(args[0])}`; case 'transform': - action += ` ${s(args[1])}`; - break; + return `${action} ${s(args[1])}`; case 'shouldTransformCachedModule': - action += ` ${s((args[0] as { id: string }).id)}`; - break; + return `${action} ${s((args[0] as { id: string }).id)}`; case 'moduleParsed': - action += ` ${s((args[0] as { id: string }).id)}`; - break; + return `${action} ${s((args[0] as { id: string }).id)}`; } return action; } diff --git a/src/utils/options/normalizeOutputOptions.ts b/src/utils/options/normalizeOutputOptions.ts index 038204ff2db..d6f4fb9ef0a 100644 --- a/src/utils/options/normalizeOutputOptions.ts +++ b/src/utils/options/normalizeOutputOptions.ts @@ -380,9 +380,9 @@ const getInterop = ( errInvalidOption( 'output.interop', 'outputinterop', - `use one of ${Array.from(ALLOWED_INTEROP_TYPES.values(), value => - JSON.stringify(value) - ).join(', ')}`, + `use one of ${Array.from(ALLOWED_INTEROP_TYPES, value => JSON.stringify(value)).join( + ', ' + )}`, interop ) ); diff --git a/src/utils/relativeId.ts b/src/utils/relativeId.ts index 0502c5563d0..743f6a27ef2 100644 --- a/src/utils/relativeId.ts +++ b/src/utils/relativeId.ts @@ -2,7 +2,7 @@ import { basename, extname, isAbsolute, relative, resolve } from './path'; export function getAliasName(id: string): string { const base = basename(id); - return base.substr(0, base.length - extname(id).length); + return base.substring(0, base.length - extname(id).length); } export default function relativeId(id: string): string { diff --git a/src/utils/renderNamePattern.ts b/src/utils/renderNamePattern.ts index 0bf89b563b7..cccff7f8de5 100644 --- a/src/utils/renderNamePattern.ts +++ b/src/utils/renderNamePattern.ts @@ -35,7 +35,7 @@ export function makeUnique(name: string, existingNames: Record) if (!existingNamesLowercase.has(name.toLocaleLowerCase())) return name; const ext = extname(name); - name = name.substr(0, name.length - ext.length); + name = name.substring(0, name.length - ext.length); let uniqueName: string, uniqueIndex = 1; while (existingNamesLowercase.has((uniqueName = name + ++uniqueIndex + ext).toLowerCase())); diff --git a/src/watch/watch.ts b/src/watch/watch.ts index 0675c32079e..2c2e16c0675 100644 --- a/src/watch/watch.ts +++ b/src/watch/watch.ts @@ -89,7 +89,7 @@ export class Watcher { this.buildTimeout = setTimeout(() => { this.buildTimeout = null; - for (const [id, event] of this.invalidatedIds.entries()) { + for (const [id, event] of this.invalidatedIds) { this.emitter.emit('change', id, { event }); } this.invalidatedIds.clear();