From 35fa868e36c461f586eb9790cedc668b6b2b2b61 Mon Sep 17 00:00:00 2001 From: liuxingbaoyu <30521560+liuxingbaoyu@users.noreply.github.com> Date: Sat, 11 Jun 2022 23:43:16 +0800 Subject: [PATCH] Improve babel-core typings (#14622) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nicolò Ribaudo --- packages/babel-core/src/config/caching.ts | 8 ++- .../babel-core/src/config/config-chain.ts | 67 +++++++++++++------ .../src/config/config-descriptors.ts | 4 +- .../src/config/files/configuration.ts | 6 +- .../src/config/files/import-meta-resolve.ts | 3 +- .../src/config/files/index-browser.ts | 2 +- .../src/config/files/module-types.ts | 2 +- packages/babel-core/src/config/files/types.ts | 4 +- packages/babel-core/src/config/full.ts | 15 +++-- .../src/config/helpers/config-api.ts | 21 ++++-- packages/babel-core/src/config/index.ts | 33 +++++---- .../babel-core/src/config/pattern-to-regex.ts | 2 +- packages/babel-core/src/config/plugin.ts | 6 +- .../src/config/resolve-targets-browser.ts | 23 ++++--- .../babel-core/src/config/resolve-targets.ts | 23 ++++--- packages/babel-core/src/config/util.ts | 6 +- .../config/validation/option-assertions.ts | 4 +- .../src/config/validation/options.ts | 2 +- .../src/config/validation/plugins.ts | 6 +- .../babel-core/src/gensync-utils/async.ts | 2 +- packages/babel-core/src/parse.ts | 13 ++-- .../src/parser/util/missing-plugin-helper.ts | 8 ++- .../src/tools/build-external-helpers.ts | 16 ++++- packages/babel-core/src/transform-ast.ts | 13 ++-- .../babel-core/src/transform-file-browser.ts | 10 ++- packages/babel-core/src/transform.ts | 15 ++++- .../src/transformation/block-hoist-plugin.ts | 8 ++- .../src/transformation/file/file.ts | 22 +++--- .../babel-core/src/transformation/index.ts | 10 +-- .../src/transformation/normalize-file.ts | 16 +++-- 30 files changed, 243 insertions(+), 127 deletions(-) diff --git a/packages/babel-core/src/config/caching.ts b/packages/babel-core/src/config/caching.ts index 2cd59d5f1c02..5575ff78b231 100644 --- a/packages/babel-core/src/config/caching.ts +++ b/packages/babel-core/src/config/caching.ts @@ -348,7 +348,7 @@ class CacheConfigurator { function makeSimpleConfigurator( cache: CacheConfigurator, ): SimpleCacheConfigurator { - function cacheFn(val) { + function cacheFn(val: any) { if (typeof val === "boolean") { if (val) cache.forever(); else cache.never(); @@ -359,8 +359,10 @@ function makeSimpleConfigurator( } cacheFn.forever = () => cache.forever(); cacheFn.never = () => cache.never(); - cacheFn.using = cb => cache.using(() => assertSimpleType(cb())); - cacheFn.invalidate = cb => cache.invalidate(() => assertSimpleType(cb())); + cacheFn.using = (cb: { (): SimpleType }) => + cache.using(() => assertSimpleType(cb())); + cacheFn.invalidate = (cb: { (): SimpleType }) => + cache.invalidate(() => assertSimpleType(cb())); return cacheFn as any; } diff --git a/packages/babel-core/src/config/config-chain.ts b/packages/babel-core/src/config/config-chain.ts index 3e8b45005a8b..b3f8e4139400 100644 --- a/packages/babel-core/src/config/config-chain.ts +++ b/packages/babel-core/src/config/config-chain.ts @@ -383,7 +383,12 @@ const loadFileChainWalker = makeChainWalker({ buildFileLogger(file.filepath, context, baseLogger), }); -function* loadFileChain(input, context, files, baseLogger) { +function* loadFileChain( + input: ValidatedFile, + context: ConfigContext, + files: Set, + baseLogger: ConfigPrinter, +) { const chain = yield* loadFileChainWalker(input, context, files, baseLogger); if (chain) { chain.files.add(input.filepath); @@ -443,11 +448,23 @@ function buildFileLogger( }); } -function buildRootDescriptors({ dirname, options }, alias, descriptors) { +function buildRootDescriptors( + { dirname, options }: Partial, + alias: string, + descriptors: ( + dirname: string, + options: ValidatedOptions, + alias: string, + ) => OptionsAndDescriptors, +) { return descriptors(dirname, options, alias); } -function buildProgrammaticLogger(_, context, baseLogger: ConfigPrinter | void) { +function buildProgrammaticLogger( + _: unknown, + context: ConfigContext, + baseLogger: ConfigPrinter | void, +) { if (!baseLogger) { return () => {}; } @@ -457,20 +474,28 @@ function buildProgrammaticLogger(_, context, baseLogger: ConfigPrinter | void) { } function buildEnvDescriptors( - { dirname, options }, - alias, - descriptors, - envName, + { dirname, options }: Partial, + alias: string, + descriptors: ( + dirname: string, + options: ValidatedOptions, + alias: string, + ) => OptionsAndDescriptors, + envName: string, ) { const opts = options.env && options.env[envName]; return opts ? descriptors(dirname, opts, `${alias}.env["${envName}"]`) : null; } function buildOverrideDescriptors( - { dirname, options }, - alias, - descriptors, - index, + { dirname, options }: Partial, + alias: string, + descriptors: ( + dirname: string, + options: ValidatedOptions, + alias: string, + ) => OptionsAndDescriptors, + index: number, ) { const opts = options.overrides && options.overrides[index]; if (!opts) throw new Error("Assertion failure - missing override"); @@ -479,11 +504,15 @@ function buildOverrideDescriptors( } function buildOverrideEnvDescriptors( - { dirname, options }, - alias, - descriptors, - index, - envName, + { dirname, options }: Partial, + alias: string, + descriptors: ( + dirname: string, + options: ValidatedOptions, + alias: string, + ) => OptionsAndDescriptors, + index: number, + envName: string, ) { const override = options.overrides && options.overrides[index]; if (!override) throw new Error("Assertion failure - missing override"); @@ -850,9 +879,9 @@ function matchesPatterns( } function matchPattern( - pattern, - dirname, - pathToTest, + pattern: IgnoreItem, + dirname: string, + pathToTest: unknown, context: ConfigContext, ): boolean { if (typeof pattern === "function") { diff --git a/packages/babel-core/src/config/config-descriptors.ts b/packages/babel-core/src/config/config-descriptors.ts index 9fe9df54a027..fe033eccc4aa 100644 --- a/packages/babel-core/src/config/config-descriptors.ts +++ b/packages/babel-core/src/config/config-descriptors.ts @@ -126,8 +126,8 @@ export function createUncachedDescriptors( // The returned result here is cached to represent a config object in // memory, so we build and memoize the descriptors to ensure the same // values are returned consistently. - let plugins; - let presets; + let plugins: UnloadedDescriptor[]; + let presets: UnloadedDescriptor[]; return { options: optionsWithResolvedBrowserslistConfigFile(options, dirname), diff --git a/packages/babel-core/src/config/files/configuration.ts b/packages/babel-core/src/config/files/configuration.ts index 99f49c0ce2f7..23104ea7ce4e 100644 --- a/packages/babel-core/src/config/files/configuration.ts +++ b/packages/babel-core/src/config/files/configuration.ts @@ -150,7 +150,11 @@ export function* loadConfig( * Read the given config file, returning the result. Returns null if no config was found, but will * throw if there are parsing errors while loading a config. */ -function readConfig(filepath, envName, caller): Handler { +function readConfig( + filepath: string, + envName: string, + caller: CallerMetadata | undefined, +): Handler { const ext = path.extname(filepath); return ext === ".js" || ext === ".cjs" || ext === ".mjs" ? readConfigJS(filepath, { envName, caller }) diff --git a/packages/babel-core/src/config/files/import-meta-resolve.ts b/packages/babel-core/src/config/files/import-meta-resolve.ts index 11c9731aa912..591aec4d9de4 100644 --- a/packages/babel-core/src/config/files/import-meta-resolve.ts +++ b/packages/babel-core/src/config/files/import-meta-resolve.ts @@ -34,7 +34,8 @@ const importMetaResolveP: Promise = // it throws because it's a module, will fallback to import(). process.execArgv.includes("--experimental-import-meta-resolve") ? import_("data:text/javascript,export default import.meta.resolve").then( - m => m.default || polyfill, + (m: { default: ImportMeta["resolve"] | undefined }) => + m.default || polyfill, () => polyfill, ) : Promise.resolve(polyfill); diff --git a/packages/babel-core/src/config/files/index-browser.ts b/packages/babel-core/src/config/files/index-browser.ts index 9acbcb6be68f..08f91f6a6751 100644 --- a/packages/babel-core/src/config/files/index-browser.ts +++ b/packages/babel-core/src/config/files/index-browser.ts @@ -72,7 +72,7 @@ export function* resolveShowConfigPath( return null; } -export const ROOT_CONFIG_FILENAMES = []; +export const ROOT_CONFIG_FILENAMES: string[] = []; // eslint-disable-next-line @typescript-eslint/no-unused-vars export function resolvePlugin(name: string, dirname: string): string | null { diff --git a/packages/babel-core/src/config/files/module-types.ts b/packages/babel-core/src/config/files/module-types.ts index 711c0f60079d..7ece0a7a8906 100644 --- a/packages/babel-core/src/config/files/module-types.ts +++ b/packages/babel-core/src/config/files/module-types.ts @@ -7,7 +7,7 @@ import semver from "semver"; const require = createRequire(import.meta.url); -let import_; +let import_: ((specifier: string | URL) => any) | undefined; try { // Old Node.js versions don't support import() syntax. import_ = require("./import").default; diff --git a/packages/babel-core/src/config/files/types.ts b/packages/babel-core/src/config/files/types.ts index a2e61f7ef7e5..3edf65b58f69 100644 --- a/packages/babel-core/src/config/files/types.ts +++ b/packages/babel-core/src/config/files/types.ts @@ -1,7 +1,9 @@ +import type { InputOptions } from ".."; + export type ConfigFile = { filepath: string; dirname: string; - options: {}; + options: InputOptions & { babel?: unknown }; }; export type IgnoreFile = { diff --git a/packages/babel-core/src/config/full.ts b/packages/babel-core/src/config/full.ts index 7121d4892902..abb022927652 100644 --- a/packages/babel-core/src/config/full.ts +++ b/packages/babel-core/src/config/full.ts @@ -181,7 +181,7 @@ export default gensync<(inputOpts: unknown) => ResolvedConfig | null>( pluginDescriptorsByPass[0].unshift(...initialPluginsDescriptors); for (const descs of pluginDescriptorsByPass) { - const pass = []; + const pass: Plugin[] = []; passes.push(pass); for (let i = 0; i < descs.length; i++) { @@ -223,8 +223,8 @@ export default gensync<(inputOpts: unknown) => ResolvedConfig | null>( }, ); -function enhanceError(context, fn: T): T { - return function* (arg1, arg2) { +function enhanceError(context: ConfigContext, fn: T): T { + return function* (arg1: unknown, arg2: unknown) { try { return yield* fn(arg1, arg2); } catch (e) { @@ -376,7 +376,7 @@ const instantiatePlugin = makeWeakCache(function* ( } if (plugin.inherits) { - const inheritsDescriptor = { + const inheritsDescriptor: UnloadedDescriptor = { name: undefined, alias: `${alias}$inherits`, value: plugin.inherits, @@ -490,11 +490,14 @@ const instantiatePreset = makeWeakCacheSync( }, ); -function chain(a, b) { +function chain( + a: undefined | ((...args: Args) => void), + b: undefined | ((...args: Args) => void), +) { const fns = [a, b].filter(Boolean); if (fns.length <= 1) return fns[0]; - return function (this: unknown, ...args) { + return function (this: unknown, ...args: unknown[]) { for (const fn of fns) { fn.apply(this, args); } diff --git a/packages/babel-core/src/config/helpers/config-api.ts b/packages/babel-core/src/config/helpers/config-api.ts index 8c9dcf25b6cc..724fdc431873 100644 --- a/packages/babel-core/src/config/helpers/config-api.ts +++ b/packages/babel-core/src/config/helpers/config-api.ts @@ -47,23 +47,29 @@ export type PluginAPI = { export function makeConfigAPI( cache: CacheConfigurator, ): ConfigAPI { - const env: any = value => + // TODO(@nicolo-ribaudo): If we remove the explicit type from `value` + // and the `as any` type cast, TypeScript crashes in an infinite + // recursion. After upgrading to TS4.7 and finishing the noImplicitAny + // PR, we should check if it still crashes and report it to the TS team. + const env: EnvFunction = (( + value: string | string[] | ((babelEnv: string) => T), + ) => cache.using(data => { if (typeof value === "undefined") return data.envName; if (typeof value === "function") { return assertSimpleType(value(data.envName)); } - if (!Array.isArray(value)) value = [value]; - - return value.some((entry: unknown) => { + return (Array.isArray(value) ? value : [value]).some(entry => { if (typeof entry !== "string") { throw new Error("Unexpected non-string value"); } return entry === data.envName; }); - }); + })) as any; - const caller = cb => cache.using(data => assertSimpleType(cb(data.caller))); + const caller = (cb: { + (CallerMetadata: CallerMetadata | undefined): SimpleType; + }) => cache.using(data => assertSimpleType(cb(data.caller))); return { version: coreVersion, @@ -98,7 +104,8 @@ export function makePluginAPI( cache: CacheConfigurator, externalDependencies: Array, ): PluginAPI { - const assumption = name => cache.using(data => data.assumptions[name]); + const assumption = (name: string) => + cache.using(data => data.assumptions[name]); return { ...makePresetAPI(cache, externalDependencies), assumption }; } diff --git a/packages/babel-core/src/config/index.ts b/packages/babel-core/src/config/index.ts index aff0cc5b7fd2..c01b90ca1c83 100644 --- a/packages/babel-core/src/config/index.ts +++ b/packages/babel-core/src/config/index.ts @@ -1,4 +1,5 @@ import gensync from "gensync"; +import type { Gensync } from "gensync"; export type { ResolvedConfig, @@ -23,7 +24,7 @@ export type { ValidatedOptions as PresetObject, } from "./validation/options"; -import loadFullConfig from "./full"; +import loadFullConfig, { type ResolvedConfig } from "./full"; import { loadPartialConfig as loadPartialConfigRunner } from "./partial"; export { loadFullConfig as default }; @@ -32,24 +33,28 @@ export type { PartialConfig } from "./partial"; import { createConfigItem as createConfigItemImpl } from "./item"; import type { ConfigItem } from "./item"; -const loadOptionsRunner = gensync<(opts: unknown) => any>(function* (opts) { - const config = yield* loadFullConfig(opts); - // NOTE: We want to return "null" explicitly, while ?. alone returns undefined - return config?.options ?? null; -}); +const loadOptionsRunner = gensync<(opts: unknown) => ResolvedConfig | null>( + function* (opts) { + const config = yield* loadFullConfig(opts); + // NOTE: We want to return "null" explicitly, while ?. alone returns undefined + return config?.options ?? null; + }, +); const createConfigItemRunner = gensync<(...args: Parameters) => ConfigItem>( createConfigItemImpl, ); -const maybeErrback = runner => (opts: unknown, callback?: Function) => { - if (callback === undefined && typeof opts === "function") { - callback = opts; - opts = undefined; - } - return callback ? runner.errback(opts, callback) : runner.sync(opts); -}; +const maybeErrback = + (runner: Gensync<(...args: any) => any>) => + (opts: unknown, callback?: any) => { + if (callback === undefined && typeof opts === "function") { + callback = opts; + opts = undefined; + } + return callback ? runner.errback(opts, callback) : runner.sync(opts); + }; export const loadPartialConfig = maybeErrback(loadPartialConfigRunner); export const loadPartialConfigSync = loadPartialConfigRunner.sync; @@ -63,7 +68,7 @@ export const createConfigItemSync = createConfigItemRunner.sync; export const createConfigItemAsync = createConfigItemRunner.async; export function createConfigItem( target: PluginTarget, - options: any, + options: Parameters[1], callback?: (err: Error, val: ConfigItem | null) => void, ) { if (callback !== undefined) { diff --git a/packages/babel-core/src/config/pattern-to-regex.ts b/packages/babel-core/src/config/pattern-to-regex.ts index a5078365fdcd..714207f8700e 100644 --- a/packages/babel-core/src/config/pattern-to-regex.ts +++ b/packages/babel-core/src/config/pattern-to-regex.ts @@ -11,7 +11,7 @@ const starPatLast = `(?:${substitution}${endSep})`; const starStarPat = `${starPat}*?`; const starStarPatLast = `${starPat}*?${starPatLast}?`; -function escapeRegExp(string) { +function escapeRegExp(string: string) { return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&"); } diff --git a/packages/babel-core/src/config/plugin.ts b/packages/babel-core/src/config/plugin.ts index ea10bb8c7eaa..782b57ec6175 100644 --- a/packages/babel-core/src/config/plugin.ts +++ b/packages/babel-core/src/config/plugin.ts @@ -5,9 +5,9 @@ import type { PluginObject } from "./validation/plugins"; export default class Plugin { key: string | undefined | null; manipulateOptions?: (options: unknown, parserOpts: unknown) => void; - post?: Function; - pre?: Function; - visitor: {}; + post?: PluginObject["post"]; + pre?: PluginObject["pre"]; + visitor: PluginObject["visitor"]; parserOverride?: Function; generatorOverride?: Function; diff --git a/packages/babel-core/src/config/resolve-targets-browser.ts b/packages/babel-core/src/config/resolve-targets-browser.ts index 2d91c9216975..60745dd7dca6 100644 --- a/packages/babel-core/src/config/resolve-targets-browser.ts +++ b/packages/babel-core/src/config/resolve-targets-browser.ts @@ -1,5 +1,7 @@ import type { ValidatedOptions } from "./validation/options"; -import getTargets from "@babel/helper-compilation-targets"; +import getTargets, { + type InputTargets, +} from "@babel/helper-compilation-targets"; import type { Targets } from "@babel/helper-compilation-targets"; @@ -17,13 +19,18 @@ export function resolveTargets( // eslint-disable-next-line @typescript-eslint/no-unused-vars root: string, ): Targets { - // todo(flow->ts) remove any and refactor to not assign different types into same variable - let targets: any = options.targets; - if (typeof targets === "string" || Array.isArray(targets)) { - targets = { browsers: targets }; - } - if (targets && targets.esmodules) { - targets = { ...targets, esmodules: "intersect" }; + const optTargets = options.targets; + let targets: InputTargets; + + if (typeof optTargets === "string" || Array.isArray(optTargets)) { + targets = { browsers: optTargets }; + } else if (optTargets) { + if ("esmodules" in optTargets) { + targets = { ...optTargets, esmodules: "intersect" }; + } else { + // https://github.com/microsoft/TypeScript/issues/17002 + targets = optTargets as InputTargets; + } } return getTargets(targets, { diff --git a/packages/babel-core/src/config/resolve-targets.ts b/packages/babel-core/src/config/resolve-targets.ts index 90a443ed3387..a7d9a790e99a 100644 --- a/packages/babel-core/src/config/resolve-targets.ts +++ b/packages/babel-core/src/config/resolve-targets.ts @@ -7,7 +7,9 @@ type nodeType = typeof import("./resolve-targets"); import type { ValidatedOptions } from "./validation/options"; import path from "path"; -import getTargets from "@babel/helper-compilation-targets"; +import getTargets, { + type InputTargets, +} from "@babel/helper-compilation-targets"; import type { Targets } from "@babel/helper-compilation-targets"; @@ -22,13 +24,18 @@ export function resolveTargets( options: ValidatedOptions, root: string, ): Targets { - // todo(flow->ts) remove any and refactor to not assign different types into same variable - let targets: any = options.targets; - if (typeof targets === "string" || Array.isArray(targets)) { - targets = { browsers: targets }; - } - if (targets && targets.esmodules) { - targets = { ...targets, esmodules: "intersect" }; + const optTargets = options.targets; + let targets: InputTargets; + + if (typeof optTargets === "string" || Array.isArray(optTargets)) { + targets = { browsers: optTargets }; + } else if (optTargets) { + if ("esmodules" in optTargets) { + targets = { ...optTargets, esmodules: "intersect" }; + } else { + // https://github.com/microsoft/TypeScript/issues/17002 + targets = optTargets as InputTargets; + } } const { browserslistConfigFile } = options; diff --git a/packages/babel-core/src/config/util.ts b/packages/babel-core/src/config/util.ts index 2bdce13b7071..76c7a7db7171 100644 --- a/packages/babel-core/src/config/util.ts +++ b/packages/babel-core/src/config/util.ts @@ -13,16 +13,18 @@ export function mergeOptions( const targetObj = target[k] || (target[k] = {}); mergeDefaultFields(targetObj, parserOpts); } else { + //@ts-expect-error const val = source[k]; + //@ts-expect-error if (val !== undefined) target[k] = val as any; } } } function mergeDefaultFields(target: T, source: T) { - for (const k of Object.keys(source)) { + for (const k of Object.keys(source) as (keyof T)[]) { const val = source[k]; - if (val !== undefined) target[k] = val as any; + if (val !== undefined) target[k] = val; } } diff --git a/packages/babel-core/src/config/validation/option-assertions.ts b/packages/babel-core/src/config/validation/option-assertions.ts index 9abc05582227..50c40c63633b 100644 --- a/packages/babel-core/src/config/validation/option-assertions.ts +++ b/packages/babel-core/src/config/validation/option-assertions.ts @@ -33,7 +33,7 @@ export type ValidatorSet = { export type Validator = (loc: OptionPath, value: unknown) => T; -export function msg(loc: NestingPath | GeneralPath) { +export function msg(loc: NestingPath | GeneralPath): string { switch (loc.type) { case "root": return ``; @@ -446,7 +446,7 @@ function assertBrowserVersion(loc: GeneralPath, value: unknown) { export function assertAssumptions( loc: GeneralPath, - value: unknown, + value: { [key: string]: unknown }, ): { [name: string]: boolean } | void { if (value === undefined) return; diff --git a/packages/babel-core/src/config/validation/options.ts b/packages/babel-core/src/config/validation/options.ts index 2b256fd2b8e5..588892994bda 100644 --- a/packages/babel-core/src/config/validation/options.ts +++ b/packages/babel-core/src/config/validation/options.ts @@ -296,7 +296,7 @@ export function validate(type: OptionsSource, opts: {}): ValidatedOptions { ); } -function validateNested(loc: NestingPath, opts: {}) { +function validateNested(loc: NestingPath, opts: { [key: string]: unknown }) { const type = getSource(loc); assertNoDuplicateSourcemap(opts); diff --git a/packages/babel-core/src/config/validation/plugins.ts b/packages/babel-core/src/config/validation/plugins.ts index 9364758f153b..0e29a78364b8 100644 --- a/packages/babel-core/src/config/validation/plugins.ts +++ b/packages/babel-core/src/config/validation/plugins.ts @@ -14,7 +14,7 @@ import type { import type { ParserOptions } from "@babel/parser"; import type { Visitor } from "@babel/traverse"; import type { ValidatedOptions } from "./options"; -import type { File, PluginPass } from "../../.."; +import type { File, PluginPass } from "../../index"; // Note: The casts here are just meant to be static assertions to make sure // that the assertion functions actually assert that the value's type matches @@ -92,7 +92,9 @@ export type PluginObject = { generatorOverride?: Function; }; -export function validatePluginObject(obj: {}): PluginObject { +export function validatePluginObject(obj: { + [key: string]: unknown; +}): PluginObject { const rootPath: RootPath = { type: "root", source: "plugin", diff --git a/packages/babel-core/src/gensync-utils/async.ts b/packages/babel-core/src/gensync-utils/async.ts index 7c5cc1da8101..af3e3da742b6 100644 --- a/packages/babel-core/src/gensync-utils/async.ts +++ b/packages/babel-core/src/gensync-utils/async.ts @@ -3,7 +3,7 @@ import gensync from "gensync"; import type { Gensync, Handler } from "gensync"; type MaybePromise = T | Promise; -const id = x => x; +const id = (x: T): T => x; const runGenerator: { sync(gen: Generator): Return; diff --git a/packages/babel-core/src/parse.ts b/packages/babel-core/src/parse.ts index 38765f06eebf..49a7587a0781 100644 --- a/packages/babel-core/src/parse.ts +++ b/packages/babel-core/src/parse.ts @@ -5,10 +5,11 @@ import type { InputOptions } from "./config"; import parser from "./parser"; import type { ParseResult } from "./parser"; import normalizeOptions from "./transformation/normalize-opts"; +import type { ValidatedOptions } from "./config/validation/options"; type FileParseCallback = { - (err: Error, ast: null): any; - (err: null, ast: ParseResult | null): any; + (err: Error, ast: null): void; + (err: null, ast: ParseResult | null): void; }; type Parse = { @@ -33,10 +34,14 @@ const parseRunner = gensync< return yield* parser(config.passes, normalizeOptions(config), code); }); -export const parse: Parse = function parse(code, opts?, callback?) { +export const parse: Parse = function parse( + code, + opts?, + callback?: FileParseCallback, +) { if (typeof opts === "function") { callback = opts; - opts = undefined; + opts = undefined as ValidatedOptions; } if (callback === undefined) { diff --git a/packages/babel-core/src/parser/util/missing-plugin-helper.ts b/packages/babel-core/src/parser/util/missing-plugin-helper.ts index 32f31b7201bd..7726dcd6aaf2 100644 --- a/packages/babel-core/src/parser/util/missing-plugin-helper.ts +++ b/packages/babel-core/src/parser/util/missing-plugin-helper.ts @@ -1,4 +1,7 @@ -const pluginNameMap = { +const pluginNameMap: Record< + string, + Partial>> +> = { asyncDoExpressions: { syntax: { name: "@babel/plugin-syntax-async-do-expressions", @@ -291,7 +294,8 @@ const pluginNameMap = { //todo: we don't have plugin-syntax-private-property-in-object pluginNameMap.privateIn.syntax = pluginNameMap.privateIn.transform; -const getNameURLCombination = ({ name, url }) => `${name} (${url})`; +const getNameURLCombination = ({ name, url }: { name: string; url: string }) => + `${name} (${url})`; /* Returns a string of the format: diff --git a/packages/babel-core/src/tools/build-external-helpers.ts b/packages/babel-core/src/tools/build-external-helpers.ts index ab7610bb9161..0c9f61e23bc3 100644 --- a/packages/babel-core/src/tools/build-external-helpers.ts +++ b/packages/babel-core/src/tools/build-external-helpers.ts @@ -24,10 +24,11 @@ import { } from "@babel/types"; import type * as t from "@babel/types"; import File from "../transformation/file/file"; +import type { PublicReplacements } from "@babel/template/src/options"; // Wrapped to avoid wasting time parsing this when almost no-one uses // build-external-helpers. -const buildUmdWrapper = replacements => +const buildUmdWrapper = (replacements: PublicReplacements) => template.statement` (function (root, factory) { if (typeof define === "function" && define.amd) { @@ -145,6 +146,17 @@ function buildVar(allowlist?: Array) { return tree; } +function buildHelpers( + body: t.Statement[], + namespace: t.Expression, + allowlist?: Array, +): Record; +function buildHelpers( + body: t.Statement[], + namespace: null, + allowlist?: Array, +): Record; + function buildHelpers( body: t.Statement[], namespace: t.Expression | null, @@ -156,7 +168,7 @@ function buildHelpers( : identifier(`_${name}`); }; - const refs = {}; + const refs: { [key: string]: t.Identifier | t.MemberExpression } = {}; helpers.list.forEach(function (name) { if (allowlist && allowlist.indexOf(name) < 0) return; diff --git a/packages/babel-core/src/transform-ast.ts b/packages/babel-core/src/transform-ast.ts index d42dbb79913f..6e16d52b0cb8 100644 --- a/packages/babel-core/src/transform-ast.ts +++ b/packages/babel-core/src/transform-ast.ts @@ -37,12 +37,17 @@ const transformFromAstRunner = gensync< export const transformFromAst: TransformFromAst = function transformFromAst( ast, code, - opts, - callback?, + optsOrCallback?: InputOptions | null | undefined | FileResultCallback, + maybeCallback?: FileResultCallback, ) { - if (typeof opts === "function") { - callback = opts; + let opts: InputOptions | undefined | null; + let callback: FileResultCallback | undefined; + if (typeof optsOrCallback === "function") { + callback = optsOrCallback; opts = undefined; + } else { + opts = optsOrCallback; + callback = maybeCallback; } if (callback === undefined) { diff --git a/packages/babel-core/src/transform-file-browser.ts b/packages/babel-core/src/transform-file-browser.ts index 1adbcd649b52..f316cb432e7c 100644 --- a/packages/babel-core/src/transform-file-browser.ts +++ b/packages/babel-core/src/transform-file-browser.ts @@ -1,13 +1,17 @@ // duplicated from transform-file so we do not have to import anything here type TransformFile = { - (filename: string, callback: Function): void; - (filename: string, opts: any, callback: Function): void; + (filename: string, callback: (error: Error, file: null) => void): void; + ( + filename: string, + opts: any, + callback: (error: Error, file: null) => void, + ): void; }; export const transformFile: TransformFile = function transformFile( filename, opts, - callback?, + callback?: (error: Error, file: null) => void, ) { if (typeof opts === "function") { callback = opts; diff --git a/packages/babel-core/src/transform.ts b/packages/babel-core/src/transform.ts index c44e62994a9d..310070bc7805 100644 --- a/packages/babel-core/src/transform.ts +++ b/packages/babel-core/src/transform.ts @@ -27,10 +27,19 @@ const transformRunner = gensync< return yield* run(config, code); }); -export const transform: Transform = function transform(code, opts?, callback?) { - if (typeof opts === "function") { - callback = opts; +export const transform: Transform = function transform( + code, + optsOrCallback?: InputOptions | null | undefined | FileResultCallback, + maybeCallback?: FileResultCallback, +) { + let opts: InputOptions | undefined | null; + let callback: FileResultCallback | undefined; + if (typeof optsOrCallback === "function") { + callback = optsOrCallback; opts = undefined; + } else { + opts = optsOrCallback; + callback = maybeCallback; } if (callback === undefined) { diff --git a/packages/babel-core/src/transformation/block-hoist-plugin.ts b/packages/babel-core/src/transformation/block-hoist-plugin.ts index 445e1866de8d..54b1eef5d31f 100644 --- a/packages/babel-core/src/transformation/block-hoist-plugin.ts +++ b/packages/babel-core/src/transformation/block-hoist-plugin.ts @@ -1,4 +1,6 @@ import traverse from "@babel/traverse"; +import type { Statement } from "@babel/types"; +import type { PluginObject } from "../config"; import Plugin from "../config/plugin"; let LOADED_PLUGIN: Plugin | void; @@ -17,14 +19,14 @@ export default function loadBlockHoistPlugin(): Plugin { return LOADED_PLUGIN; } -function priority(bodyNode) { +function priority(bodyNode: Statement & { _blockHoist?: number | true }) { const priority = bodyNode?._blockHoist; if (priority == null) return 1; if (priority === true) return 2; return priority; } -function stableSort(body) { +function stableSort(body: Statement[]) { // By default, we use priorities of 0-4. const buckets = Object.create(null); @@ -54,7 +56,7 @@ function stableSort(body) { return body; } -const blockHoistPlugin = { +const blockHoistPlugin: PluginObject = { /** * [Please add a description.] * diff --git a/packages/babel-core/src/transformation/file/file.ts b/packages/babel-core/src/transformation/file/file.ts index d44b64799941..ad3a5524718c 100644 --- a/packages/babel-core/src/transformation/file/file.ts +++ b/packages/babel-core/src/transformation/file/file.ts @@ -1,6 +1,6 @@ import * as helpers from "@babel/helpers"; import { NodePath, Scope } from "@babel/traverse"; -import type { HubInterface } from "@babel/traverse"; +import type { HubInterface, Visitor } from "@babel/traverse"; import { codeFrameColumns } from "@babel/code-frame"; import traverse from "@babel/traverse"; import { cloneNode, interpreterDirective } from "@babel/types"; @@ -10,7 +10,7 @@ import semver from "semver"; import type { NormalizedFile } from "../normalize-file"; -const errorVisitor = { +const errorVisitor: Visitor<{ loc: NodeLocation["loc"] | null }> = { enter(path, state) { const loc = path.node.loc; if (loc) { @@ -44,15 +44,15 @@ export type NodeLocation = { }; export default class File { - _map: Map = new Map(); - opts: any; - declarations: any = {}; - path: NodePath = null; - ast: any = {}; + _map: Map = new Map(); + opts: { [key: string]: any }; + declarations: { [key: string]: t.Identifier } = {}; + path: NodePath; + ast: t.File; scope: Scope; - metadata: {} = {}; + metadata: { [key: string]: any } = {}; code: string = ""; - inputMap: any | null = null; + inputMap: any; hub: HubInterface & { file: File } = { // keep it for the usage in babel-core, ex: path.hub.file.opts.filename @@ -191,7 +191,7 @@ export default class File { const uid = (this.declarations[name] = this.scope.generateUidIdentifier(name)); - const dependencies = {}; + const dependencies: { [key: string]: t.Identifier } = {}; for (const dep of helpers.getDependencies(name)) { dependencies[dep] = this.addHelper(dep); } @@ -239,7 +239,7 @@ export default class File { let loc = node && (node.loc || node._loc); if (!loc && node) { - const state = { + const state: { loc?: NodeLocation["loc"] | null } = { loc: null, }; traverse(node as t.Node, errorVisitor, this.scope, state); diff --git a/packages/babel-core/src/transformation/index.ts b/packages/babel-core/src/transformation/index.ts index b6d6875705b1..78d587c8e265 100644 --- a/packages/babel-core/src/transformation/index.ts +++ b/packages/babel-core/src/transformation/index.ts @@ -16,17 +16,17 @@ import type File from "./file/file"; import { flattenToSet } from "../config/helpers/deep-array"; export type FileResultCallback = { - (err: Error, file: null): any; - (err: null, file: FileResult | null): any; + (err: Error, file: null): void; + (err: null, file: FileResult | null): void; }; export type FileResult = { - metadata: {}; - options: {}; + metadata: { [key: string]: any }; + options: { [key: string]: any }; ast: t.File | null; code: string | null; map: SourceMap | null; - sourceType: "string" | "module"; + sourceType: "script" | "module"; externalDependencies: Set; }; diff --git a/packages/babel-core/src/transformation/normalize-file.ts b/packages/babel-core/src/transformation/normalize-file.ts index e1e730565068..16eba97d3180 100644 --- a/packages/babel-core/src/transformation/normalize-file.ts +++ b/packages/babel-core/src/transformation/normalize-file.ts @@ -16,13 +16,13 @@ const LARGE_INPUT_SOURCEMAP_THRESHOLD = 3_000_000; export type NormalizedFile = { code: string; - ast: {}; + ast: t.File; inputMap: Converter | null; }; export default function* normalizeFile( pluginPasses: PluginPasses, - options: any, + options: { [key: string]: any }, code: string, ast?: t.File | t.Program | null, ): Handler { @@ -36,7 +36,7 @@ export default function* normalizeFile( } if (options.cloneInputAst) { - ast = cloneDeep(ast); + ast = cloneDeep(ast) as t.File; } } else { ast = yield* parser(pluginPasses, options, code); @@ -105,7 +105,11 @@ const INLINE_SOURCEMAP_REGEX = const EXTERNAL_SOURCEMAP_REGEX = /^[@#][ \t]+sourceMappingURL=([^\s'"`]+)[ \t]*$/; -function extractCommentsFromList(regex, comments, lastComment) { +function extractCommentsFromList( + regex: RegExp, + comments: ReadonlyArray, + lastComment: string | null, +): [ReadonlyArray, string | null] { if (comments) { comments = comments.filter(({ value }) => { if (regex.test(value)) { @@ -118,8 +122,8 @@ function extractCommentsFromList(regex, comments, lastComment) { return [comments, lastComment]; } -function extractComments(regex, ast) { - let lastComment = null; +function extractComments(regex: RegExp, ast: t.Node) { + let lastComment: string = null; traverseFast(ast, node => { [node.leadingComments, lastComment] = extractCommentsFromList( regex,