Convert @babel/core to TypeScript (#12929)

Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
This commit is contained in:
Bogdan Savluk 2021-03-27 02:03:15 +01:00 committed by Nicolò Ribaudo
parent c8a91d9eef
commit a647b9ea6b
53 changed files with 1265 additions and 1200 deletions

View File

@ -42,10 +42,10 @@
"./lib/config/resolve-targets.js": "./lib/config/resolve-targets-browser.js",
"./lib/transform-file.js": "./lib/transform-file-browser.js",
"./lib/transformation/util/clone-deep.js": "./lib/transformation/util/clone-deep-browser.js",
"./src/config/files/index.js": "./src/config/files/index-browser.js",
"./src/config/resolve-targets.js": "./src/config/resolve-targets-browser.js",
"./src/transform-file.js": "./src/transform-file-browser.js",
"./src/transformation/util/clone-deep.js": "./src/transformation/util/clone-deep-browser.js"
"./src/config/files/index.ts": "./src/config/files/index-browser.ts",
"./src/config/resolve-targets.ts": "./src/config/resolve-targets-browser.ts",
"./src/transform-file.ts": "./src/transform-file-browser.ts",
"./src/transformation/util/clone-deep.ts": "./src/transformation/util/clone-deep-browser.ts"
},
"dependencies": {
"@babel/code-frame": "workspace:^7.12.13",
@ -65,6 +65,12 @@
"source-map": "^0.5.0"
},
"devDependencies": {
"@babel/helper-transform-fixture-test-runner": "workspace:*"
"@babel/helper-transform-fixture-test-runner": "workspace:*",
"@types/convert-source-map": "^1.5.1",
"@types/debug": "^4.1.0",
"@types/lodash": "^4.14.150",
"@types/resolve": "^1.3.2",
"@types/semver": "^5.4.0",
"@types/source-map": "^0.5.0"
}
}

View File

@ -1,5 +1,3 @@
// @flow
import type { Targets } from "@babel/helper-compilation-targets";
import type { ConfigContext } from "./config-chain";
@ -8,25 +6,23 @@ import type { CallerMetadata } from "./validation/options";
export type { ConfigContext as FullConfig };
export type FullPreset = {
...ConfigContext,
targets: Targets,
};
targets: Targets;
} & ConfigContext;
export type FullPlugin = {
...FullPreset,
assumptions: { [name: string]: boolean },
};
assumptions: { [name: string]: boolean };
} & FullPreset;
// Context not including filename since it is used in places that cannot
// process 'ignore'/'only' and other filename-based logic.
export type SimpleConfig = {
envName: string,
caller: CallerMetadata | void,
envName: string;
caller: CallerMetadata | void;
};
export type SimplePreset = {
...SimpleConfig,
targets: Targets,
};
targets: Targets;
} & SimpleConfig;
export type SimplePlugin = {
...SimplePreset,
assumptions: { [name: string]: boolean },
assumptions: {
[name: string]: boolean;
};
} & SimplePreset;

View File

@ -1,6 +1,5 @@
// @flow
import gensync, { type Handler } from "gensync";
import gensync from "gensync";
import type { Handler } from "gensync";
import {
maybeAsync,
isAsync,
@ -12,60 +11,61 @@ import { isIterableIterator } from "./util";
export type { CacheConfigurator };
export type SimpleCacheConfigurator = SimpleCacheConfiguratorFn &
SimpleCacheConfiguratorObj;
export type SimpleCacheConfigurator = {
(forever: boolean): void;
<T>(handler: () => T): T;
type SimpleCacheConfiguratorFn = {
(boolean): void,
<T>(handler: () => T): T,
};
type SimpleCacheConfiguratorObj = {
forever: () => void,
never: () => void,
using: <T>(handler: () => T) => T,
invalidate: <T>(handler: () => T) => T,
forever: () => void;
never: () => void;
using: <T>(handler: () => T) => T;
invalidate: <T>(handler: () => T) => T;
};
export type CacheEntry<ResultT, SideChannel> = Array<{
value: ResultT,
valid: SideChannel => Handler<boolean>,
value: ResultT;
valid: (channel: SideChannel) => Handler<boolean>;
}>;
const synchronize = <ArgsT, ResultT>(
gen: (...ArgsT) => Handler<ResultT>,
// $FlowIssue https://github.com/facebook/flow/issues/7279
const synchronize = <ArgsT extends any[], ResultT>(
gen: (...args: ArgsT) => Handler<ResultT>,
): ((...args: ArgsT) => ResultT) => {
return gensync(gen).sync;
};
// eslint-disable-next-line require-yield, no-unused-vars
function* genTrue(data: any) {
// eslint-disable-next-line require-yield
function* genTrue() {
return true;
}
export function makeWeakCache<ArgT, ResultT, SideChannel>(
handler: (ArgT, CacheConfigurator<SideChannel>) => Handler<ResultT> | ResultT,
): (ArgT, SideChannel) => Handler<ResultT> {
return makeCachedFunction<ArgT, ResultT, SideChannel, *>(WeakMap, handler);
export function makeWeakCache<ArgT extends object, ResultT, SideChannel>(
handler: (
arg: ArgT,
cache: CacheConfigurator<SideChannel>,
) => Handler<ResultT> | ResultT,
): (arg: ArgT, data: SideChannel) => Handler<ResultT> {
return makeCachedFunction<ArgT, ResultT, SideChannel>(WeakMap, handler);
}
export function makeWeakCacheSync<ArgT, ResultT, SideChannel>(
handler: (ArgT, CacheConfigurator<SideChannel>) => ResultT,
): (ArgT, SideChannel) => ResultT {
export function makeWeakCacheSync<ArgT extends object, ResultT, SideChannel>(
handler: (arg: ArgT, cache?: CacheConfigurator<SideChannel>) => ResultT,
): (arg: ArgT, data?: SideChannel) => ResultT {
return synchronize<[ArgT, SideChannel], ResultT>(
makeWeakCache<ArgT, ResultT, SideChannel>(handler),
);
}
export function makeStrongCache<ArgT, ResultT, SideChannel>(
handler: (ArgT, CacheConfigurator<SideChannel>) => Handler<ResultT> | ResultT,
): (ArgT, SideChannel) => Handler<ResultT> {
return makeCachedFunction<ArgT, ResultT, SideChannel, *>(Map, handler);
handler: (
arg: ArgT,
cache: CacheConfigurator<SideChannel>,
) => Handler<ResultT> | ResultT,
): (arg: ArgT, data: SideChannel) => Handler<ResultT> {
return makeCachedFunction<ArgT, ResultT, SideChannel>(Map, handler);
}
export function makeStrongCacheSync<ArgT, ResultT, SideChannel>(
handler: (ArgT, CacheConfigurator<SideChannel>) => ResultT,
): (ArgT, SideChannel) => ResultT {
handler: (arg: ArgT, cache?: CacheConfigurator<SideChannel>) => ResultT,
): (arg: ArgT, data?: SideChannel) => ResultT {
return synchronize<[ArgT, SideChannel], ResultT>(
makeStrongCache<ArgT, ResultT, SideChannel>(handler),
);
@ -96,13 +96,16 @@ export function makeStrongCacheSync<ArgT, ResultT, SideChannel>(
* 6. Store the result in the cache
* 7. RETURN the result
*/
function makeCachedFunction<ArgT, ResultT, SideChannel, Cache: *>(
CallCache: Class<Cache>,
handler: (ArgT, CacheConfigurator<SideChannel>) => Handler<ResultT> | ResultT,
): (ArgT, SideChannel) => Handler<ResultT> {
const callCacheSync = new CallCache();
const callCacheAsync = new CallCache();
const futureCache = new CallCache();
function makeCachedFunction<ArgT, ResultT, SideChannel>(
CallCache: new <Cached>() => CacheMap<ArgT, Cached, SideChannel>,
handler: (
arg: ArgT,
cache: CacheConfigurator<SideChannel>,
) => Handler<ResultT> | ResultT,
): (arg: ArgT, data: SideChannel) => Handler<ResultT> {
const callCacheSync = new CallCache<ResultT>();
const callCacheAsync = new CallCache<ResultT>();
const futureCache = new CallCache<Lock<ResultT>>();
return function* cachedFunction(arg: ArgT, data: SideChannel) {
const asyncContext = yield* isAsync();
@ -121,19 +124,17 @@ function makeCachedFunction<ArgT, ResultT, SideChannel, Cache: *>(
const handlerResult: Handler<ResultT> | ResultT = handler(arg, cache);
let finishLock: ?Lock<ResultT>;
let finishLock: Lock<ResultT>;
let value: ResultT;
if (isIterableIterator(handlerResult)) {
// Flow refines handlerResult to Generator<any, any, any>
const gen = (handlerResult: Generator<*, ResultT, *>);
const gen = handlerResult as Generator<unknown, ResultT, unknown>;
value = yield* onFirstPause(gen, () => {
finishLock = setupAsyncLocks(cache, futureCache, arg);
});
} else {
// $FlowIgnore doesn't refine handlerResult to ResultT
value = (handlerResult: ResultT);
value = handlerResult;
}
updateFunctionCache(callCache, cache, arg, value);
@ -149,19 +150,14 @@ function makeCachedFunction<ArgT, ResultT, SideChannel, Cache: *>(
type CacheMap<ArgT, ResultT, SideChannel> =
| Map<ArgT, CacheEntry<ResultT, SideChannel>>
// @ts-expect-error todo(flow->ts): add `extends object` constraint to ArgT
| WeakMap<ArgT, CacheEntry<ResultT, SideChannel>>;
function* getCachedValue<
ArgT,
ResultT,
SideChannel,
// $FlowIssue https://github.com/facebook/flow/issues/4528
Cache: CacheMap<ArgT, ResultT, SideChannel>,
>(
cache: Cache,
function* getCachedValue<ArgT, ResultT, SideChannel>(
cache: CacheMap<ArgT, ResultT, SideChannel>,
arg: ArgT,
data: SideChannel,
): Handler<{ valid: true, value: ResultT } | { valid: false, value: null }> {
): Handler<{ valid: true; value: ResultT } | { valid: false; value: null }> {
const cachedValue: CacheEntry<ResultT, SideChannel> | void = cache.get(arg);
if (cachedValue) {
@ -179,7 +175,7 @@ function* getCachedValueOrWait<ArgT, ResultT, SideChannel>(
futureCache: CacheMap<ArgT, Lock<ResultT>, SideChannel>,
arg: ArgT,
data: SideChannel,
): Handler<{ valid: true, value: ResultT } | { valid: false, value: null }> {
): Handler<{ valid: true; value: ResultT } | { valid: false; value: null }> {
const cached = yield* getCachedValue(callCache, arg, data);
if (cached.valid) {
return cached;
@ -212,8 +208,7 @@ function updateFunctionCache<
ArgT,
ResultT,
SideChannel,
// $FlowIssue https://github.com/facebook/flow/issues/4528
Cache: CacheMap<ArgT, ResultT, SideChannel>,
Cache extends CacheMap<ArgT, ResultT, SideChannel>
>(
cache: Cache,
config: CacheConfigurator<SideChannel>,
@ -253,7 +248,9 @@ class CacheConfigurator<SideChannel = void> {
_configured: boolean = false;
_pairs: Array<[mixed, (SideChannel) => Handler<mixed>]> = [];
_pairs: Array<
[cachedValue: unknown, handler: (data: SideChannel) => Handler<unknown>]
> = [];
_data: SideChannel;
@ -294,7 +291,7 @@ class CacheConfigurator<SideChannel = void> {
this._configured = true;
}
using<T>(handler: SideChannel => T): T {
using<T>(handler: (data: SideChannel) => T): T {
if (!this._active) {
throw new Error("Cannot change caching after evaluation has completed.");
}
@ -313,7 +310,8 @@ class CacheConfigurator<SideChannel = void> {
);
if (isThenable(key)) {
return key.then((key: mixed) => {
// @ts-expect-error todo(flow->ts): improve function return type annotation
return key.then((key: unknown) => {
this._pairs.push([key, fn]);
return key;
});
@ -323,12 +321,12 @@ class CacheConfigurator<SideChannel = void> {
return key;
}
invalidate<T>(handler: SideChannel => T): T {
invalidate<T>(handler: (data: SideChannel) => T): T {
this._invalidate = true;
return this.using(handler);
}
validator(): SideChannel => Handler<boolean> {
validator(): (data: SideChannel) => Handler<boolean> {
const pairs = this._pairs;
return function* (data: SideChannel) {
for (const [key, fn] of pairs) {
@ -364,7 +362,7 @@ function makeSimpleConfigurator(
cacheFn.using = cb => cache.using(() => assertSimpleType(cb()));
cacheFn.invalidate = cb => cache.invalidate(() => assertSimpleType(cb()));
return (cacheFn: any);
return cacheFn as any;
}
// Types are limited here so that in the future these values can be used
@ -376,7 +374,7 @@ export type SimpleType =
| null
| void
| Promise<SimpleType>;
export function assertSimpleType(value: mixed): SimpleType {
export function assertSimpleType(value: unknown): SimpleType {
if (isThenable(value)) {
throw new Error(
`You appear to be using an async cache handler, ` +
@ -397,6 +395,7 @@ export function assertSimpleType(value: mixed): SimpleType {
"Cache keys must be either string, boolean, number, null, or undefined.",
);
}
// @ts-expect-error todo(flow->ts) value is still typed as unknown, also assert function typically should not return a value
return value;
}

View File

@ -1,15 +1,14 @@
// @flow
import path from "path";
import buildDebug from "debug";
import type { Handler } from "gensync";
import {
validate,
type ValidatedOptions,
type IgnoreList,
type ConfigApplicableTest,
type BabelrcSearch,
type CallerMetadata,
import { validate } from "./validation/options";
import type {
ValidatedOptions,
IgnoreList,
ConfigApplicableTest,
BabelrcSearch,
CallerMetadata,
IgnoreItem,
} from "./validation/options";
import pathPatternToRegex from "./pattern-to-regex";
import { ConfigPrinter, ChainFormatter } from "./printer";
@ -21,41 +20,41 @@ import {
findRelativeConfig,
findRootConfig,
loadConfig,
type ConfigFile,
type IgnoreFile,
type FilePackageData,
} from "./files";
import type { ConfigFile, IgnoreFile, FilePackageData } from "./files";
import { makeWeakCacheSync, makeStrongCacheSync } from "./caching";
import {
createCachedDescriptors,
createUncachedDescriptors,
type UnloadedDescriptor,
type OptionsAndDescriptors,
type ValidatedFile,
} from "./config-descriptors";
import type {
UnloadedDescriptor,
OptionsAndDescriptors,
ValidatedFile,
} from "./config-descriptors";
export type ConfigChain = {
plugins: Array<UnloadedDescriptor>,
presets: Array<UnloadedDescriptor>,
options: Array<ValidatedOptions>,
files: Set<string>,
plugins: Array<UnloadedDescriptor>;
presets: Array<UnloadedDescriptor>;
options: Array<ValidatedOptions>;
files: Set<string>;
};
export type PresetInstance = {
options: ValidatedOptions,
alias: string,
dirname: string,
options: ValidatedOptions;
alias: string;
dirname: string;
};
export type ConfigContext = {
filename: string | void,
cwd: string,
root: string,
envName: string,
caller: CallerMetadata | void,
showConfig: boolean,
filename: string | void;
cwd: string;
root: string;
envName: string;
caller: CallerMetadata | void;
showConfig: boolean;
};
/**
@ -63,7 +62,7 @@ export type ConfigContext = {
*/
export function* buildPresetChain(
arg: PresetInstance,
context: *,
context: any,
): Handler<ConfigChain | null> {
const chain = yield* buildPresetChainWalker(arg, context);
if (!chain) return null;
@ -76,10 +75,7 @@ export function* buildPresetChain(
};
}
export const buildPresetChainWalker: (
arg: PresetInstance,
context: *,
) => * = makeChainWalker({
export const buildPresetChainWalker = makeChainWalker<PresetInstance>({
root: preset => loadPresetDescriptors(preset),
env: (preset, envName) => loadPresetEnvDescriptors(preset)(envName),
overrides: (preset, index) => loadPresetOverridesDescriptors(preset)(index),
@ -128,11 +124,11 @@ const loadPresetOverridesEnvDescriptors = makeWeakCacheSync(
export type FileHandling = "transpile" | "ignored" | "unsupported";
export type RootConfigChain = ConfigChain & {
babelrc: ConfigFile | void,
config: ConfigFile | void,
ignore: IgnoreFile | void,
fileHandling: FileHandling,
files: Set<string>,
babelrc: ConfigFile | void;
config: ConfigFile | void;
ignore: IgnoreFile | void;
fileHandling: FileHandling;
files: Set<string>;
};
/**
@ -257,7 +253,6 @@ export function* buildRootChain(
if (context.showConfig) {
console.log(
// $FlowIgnore: context.showConfig implies context.filename is not null
`Babel configs on "${context.filename}" (ascending priority):\n` +
// print config by the order of ascending priority
[configReport, babelRcReport, programmaticReport]
@ -288,7 +283,7 @@ export function* buildRootChain(
function babelrcLoadEnabled(
context: ConfigContext,
pkgData: FilePackageData,
babelrcRoots: BabelrcSearch | void,
babelrcRoots: BabelrcSearch | undefined,
babelrcRootsDirectory: string,
): boolean {
if (typeof babelrcRoots === "boolean") return babelrcRoots;
@ -302,7 +297,9 @@ function babelrcLoadEnabled(
}
let babelrcPatterns = babelrcRoots;
if (!Array.isArray(babelrcPatterns)) babelrcPatterns = [babelrcPatterns];
if (!Array.isArray(babelrcPatterns)) {
babelrcPatterns = [babelrcPatterns as IgnoreItem];
}
babelrcPatterns = babelrcPatterns.map(pat => {
return typeof pat === "string"
? path.resolve(babelrcRootsDirectory, pat)
@ -374,7 +371,7 @@ const loadProgrammaticChain = makeChainWalker({
/**
* Build a config chain for a given file.
*/
const loadFileChainWalker = makeChainWalker({
const loadFileChainWalker = makeChainWalker<ValidatedFile>({
root: file => loadFileDescriptors(file),
env: (file, envName) => loadFileEnvDescriptors(file)(envName),
overrides: (file, index) => loadFileOverridesDescriptors(file)(index),
@ -499,36 +496,46 @@ function buildOverrideEnvDescriptors(
: null;
}
function makeChainWalker<ArgT: { options: ValidatedOptions, dirname: string }>({
function makeChainWalker<
ArgT extends { options: ValidatedOptions; dirname: string }
>({
root,
env,
overrides,
overridesEnv,
createLogger,
}: {|
root: ArgT => OptionsAndDescriptors,
env: (ArgT, string) => OptionsAndDescriptors | null,
overrides: (ArgT, number) => OptionsAndDescriptors,
overridesEnv: (ArgT, number, string) => OptionsAndDescriptors | null,
}: {
root: (configEntry: ArgT) => OptionsAndDescriptors;
env: (configEntry: ArgT, env: string) => OptionsAndDescriptors | null;
overrides: (configEntry: ArgT, index: number) => OptionsAndDescriptors;
overridesEnv: (
configEntry: ArgT,
index: number,
env: string,
) => OptionsAndDescriptors | null;
createLogger: (
ArgT,
ConfigContext,
ConfigPrinter | void,
) => (OptionsAndDescriptors, ?number, ?string) => void,
|}): (
ArgT,
ConfigContext,
files?: Set<ConfigFile> | void,
baseLogger: ConfigPrinter | void,
configEntry: ArgT,
context: ConfigContext,
printer: ConfigPrinter | void,
) => (
opts: OptionsAndDescriptors,
index?: number | null,
env?: string | null,
) => void;
}): (
configEntry: ArgT,
context: ConfigContext,
files?: Set<ConfigFile>,
baseLogger?: ConfigPrinter,
) => Handler<ConfigChain | null> {
return function* (input, context, files = new Set(), baseLogger) {
const { dirname } = input;
const flattenedConfigs: Array<{|
config: OptionsAndDescriptors,
index: ?number,
envName: ?string,
|}> = [];
const flattenedConfigs: Array<{
config: OptionsAndDescriptors;
index: number | undefined | null;
envName: string | undefined | null;
}> = [];
const rootOpts = root(input);
if (configIsApplicable(rootOpts, dirname, context)) {
@ -612,7 +619,7 @@ function* mergeExtendsChain(
dirname: string,
context: ConfigContext,
files: Set<ConfigFile>,
baseLogger: ConfigPrinter | void,
baseLogger?: ConfigPrinter,
): Handler<boolean> {
if (opts.extends === undefined) return true;
@ -708,7 +715,7 @@ function dedupDescriptors(
): Array<UnloadedDescriptor> {
const map: Map<
Function,
Map<string | void, { value: UnloadedDescriptor }>,
Map<string | void, { value: UnloadedDescriptor }>
> = new Map();
const descriptors = [];
@ -773,8 +780,8 @@ function configFieldIsApplicable(
*/
function shouldIgnore(
context: ConfigContext,
ignore: ?IgnoreList,
only: ?IgnoreList,
ignore: IgnoreList | undefined | null,
only: IgnoreList | undefined | null,
dirname: string,
): boolean {
if (ignore && matchesPatterns(context, ignore, dirname)) {

View File

@ -1,6 +1,6 @@
// @flow
import gensync from "gensync";
import gensync, { type Handler } from "gensync";
import type { Handler } from "gensync";
import { loadPlugin, loadPreset } from "./files";
@ -10,8 +10,8 @@ import {
makeWeakCacheSync,
makeStrongCacheSync,
makeStrongCache,
type CacheConfigurator,
} from "./caching";
import type { CacheConfigurator } from "./caching";
import type {
ValidatedOptions,
@ -25,25 +25,25 @@ import { resolveBrowserslistConfigFile } from "./resolve-targets";
// for the plugins and presets so we don't load the plugins/presets unless
// the options object actually ends up being applicable.
export type OptionsAndDescriptors = {
options: ValidatedOptions,
plugins: () => Handler<Array<UnloadedDescriptor>>,
presets: () => Handler<Array<UnloadedDescriptor>>,
options: ValidatedOptions;
plugins: () => Handler<Array<UnloadedDescriptor>>;
presets: () => Handler<Array<UnloadedDescriptor>>;
};
// Represents a plugin or presets at a given location in a config object.
// At this point these have been resolved to a specific object or function,
// but have not yet been executed to call functions with options.
export type UnloadedDescriptor = {
name: string | void,
value: {} | Function,
options: {} | void | false,
dirname: string,
alias: string,
ownPass?: boolean,
name: string | undefined;
value: any | Function;
options: {} | undefined | false;
dirname: string;
alias: string;
ownPass?: boolean;
file?: {
request: string,
resolved: string,
} | void,
request: string;
resolved: string;
};
};
function isEqualDescriptor(
@ -63,9 +63,9 @@ function isEqualDescriptor(
}
export type ValidatedFile = {
filepath: string,
dirname: string,
options: ValidatedOptions,
filepath: string;
dirname: string;
options: ValidatedOptions;
};
// eslint-disable-next-line require-yield
@ -100,10 +100,13 @@ export function createCachedDescriptors(
return {
options: optionsWithResolvedBrowserslistConfigFile(options, dirname),
plugins: plugins
? () => createCachedPluginDescriptors(plugins, dirname)(alias)
? () =>
// @ts-expect-error todo(flow->ts) ts complains about incorrect arguments
createCachedPluginDescriptors(plugins, dirname)(alias)
: () => handlerOf([]),
presets: presets
? () =>
// @ts-expect-error todo(flow->ts) ts complains about incorrect arguments
createCachedPresetDescriptors(presets, dirname)(alias)(
!!passPerPreset,
)
@ -295,9 +298,9 @@ export function* createDescriptor(
alias,
ownPass,
}: {
type?: "plugin" | "preset",
alias: string,
ownPass?: boolean,
type?: "plugin" | "preset";
alias: string;
ownPass?: boolean;
},
): Handler<UnloadedDescriptor> {
const desc = getItemDescriptor(pair);
@ -307,7 +310,8 @@ export function* createDescriptor(
let name;
let options;
let value = pair;
// todo(flow->ts) better type annotation
let value: any = pair;
if (Array.isArray(value)) {
if (value.length === 3) {
[value, options, name] = value;

View File

@ -1,15 +1,12 @@
// @flow
import buildDebug from "debug";
import path from "path";
import json5 from "json5";
import gensync, { type Handler } from "gensync";
import {
makeStrongCache,
makeWeakCacheSync,
type CacheConfigurator,
} from "../caching";
import { makeConfigAPI, type ConfigAPI } from "../helpers/config-api";
import gensync from "gensync";
import type { Handler } from "gensync";
import { makeStrongCache, makeWeakCacheSync } from "../caching";
import type { CacheConfigurator } from "../caching";
import { makeConfigAPI } from "../helpers/config-api";
import type { ConfigAPI } from "../helpers/config-api";
import { makeStaticFileCache } from "./utils";
import loadCjsOrMjsDefault from "./module-types";
import pathPatternToRegex from "../pattern-to-regex";
@ -19,8 +16,7 @@ import type { CallerMetadata } from "../validation/options";
import * as fs from "../../gensync-utils/fs";
import { createRequire } from "module";
// $FlowIgnore - https://github.com/facebook/flow/issues/6913#issuecomment-662787504
const require = createRequire(import /*::("")*/.meta.url);
const require = createRequire(import.meta.url);
const debug = buildDebug("babel:config:loading:files:configuration");
@ -75,8 +71,7 @@ export function* findRelativeConfig(
envName,
caller,
packageData.pkg?.dirname === loc
? // $FlowIgnore - packageData.pkg is not null
packageToBabelConfig((packageData.pkg: ConfigFile))
? packageToBabelConfig(packageData.pkg as ConfigFile)
: null,
);
}
@ -107,7 +102,7 @@ function* loadOneConfig(
dirname: string,
envName: string,
caller: CallerMetadata | void,
previousConfig?: ConfigFile | null = null,
previousConfig: ConfigFile | null = null,
): Handler<ConfigFile | null> {
const configs = yield* gensync.all(
names.map(filename =>
@ -166,8 +161,8 @@ const LOADING_CONFIGS = new Set();
const readConfigJS = makeStrongCache(function* readConfigJS(
filepath: string,
cache: CacheConfigurator<{
envName: string,
caller: CallerMetadata | void,
envName: string;
caller: CallerMetadata | void;
}>,
): Handler<ConfigFile | null> {
if (!fs.exists.sync(filepath)) {
@ -189,14 +184,14 @@ const readConfigJS = makeStrongCache(function* readConfigJS(
};
}
let options: mixed;
let options: unknown;
try {
LOADING_CONFIGS.add(filepath);
options = (yield* loadCjsOrMjsDefault(
options = yield* loadCjsOrMjsDefault(
filepath,
"You appear to be using a native ECMAScript module configuration " +
"file, which is only supported when running Babel asynchronously.",
): mixed);
);
} catch (err) {
err.message = `${filepath}: Error while loading config - ${err.message}`;
throw err;
@ -206,8 +201,12 @@ const readConfigJS = makeStrongCache(function* readConfigJS(
let assertCache = false;
if (typeof options === "function") {
yield* []; // if we want to make it possible to use async configs
options = ((options: any): (api: ConfigAPI) => {})(makeConfigAPI(cache));
// @ts-expect-error - if we want to make it possible to use async configs
yield* [];
options = ((options as any) as (api: ConfigAPI) => {})(
makeConfigAPI(cache),
);
assertCache = true;
}
@ -218,6 +217,7 @@ const readConfigJS = makeStrongCache(function* readConfigJS(
);
}
// @ts-expect-error todo(flow->ts)
if (typeof options.then === "function") {
throw new Error(
`You appear to be using an async configuration, ` +
@ -239,7 +239,7 @@ const readConfigJS = makeStrongCache(function* readConfigJS(
const packageToBabelConfig = makeWeakCacheSync(
(file: ConfigFile): ConfigFile | null => {
const babel: mixed = file.options[("babel": string)];
const babel: unknown = file.options["babel"];
if (typeof babel === "undefined") return null;
@ -255,7 +255,8 @@ const packageToBabelConfig = makeWeakCacheSync(
},
);
const readConfigJSON5 = makeStaticFileCache((filepath, content): ConfigFile => {
const readConfigJSON5 = makeStaticFileCache(
(filepath, content): ConfigFile => {
let options;
try {
options = json5.parse(content);
@ -278,7 +279,8 @@ const readConfigJSON5 = makeStaticFileCache((filepath, content): ConfigFile => {
dirname: path.dirname(filepath),
options,
};
});
},
);
const readIgnoreConfig = makeStaticFileCache((filepath, content) => {
const ignoreDir = path.dirname(filepath);
@ -319,7 +321,7 @@ export function* resolveShowConfigPath(
return null;
}
function throwConfigError(): empty {
function throwConfigError(): never {
throw new Error(`\
Caching was left unconfigured. Babel's plugins, presets, and .babelrc.js files can be configured
for various types of caching, using the first param of their handler functions:

View File

@ -1,4 +1,3 @@
// @flow
// We keep this in a separate file so that in older node versions, where
// import() isn't supported, we can try/catch around the require() call
// when loading this file.

View File

@ -1,5 +1,3 @@
// @flow
import type { Handler } from "gensync";
import type {
@ -15,7 +13,8 @@ export type { ConfigFile, IgnoreFile, RelativeConfig, FilePackageData };
// eslint-disable-next-line require-yield
export function* findConfigUpwards(
rootDir: string, // eslint-disable-line no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-unused-vars
rootDir: string,
): Handler<string | null> {
return null;
}
@ -32,18 +31,24 @@ export function* findPackageData(filepath: string): Handler<FilePackageData> {
// eslint-disable-next-line require-yield
export function* findRelativeConfig(
pkgData: FilePackageData, // eslint-disable-line no-unused-vars
envName: string, // eslint-disable-line no-unused-vars
caller: CallerMetadata | void, // eslint-disable-line no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-unused-vars
pkgData: FilePackageData,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
envName: string,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
caller: CallerMetadata | void,
): Handler<RelativeConfig> {
return { pkg: null, config: null, ignore: null };
return { config: null, ignore: null };
}
// eslint-disable-next-line require-yield
export function* findRootConfig(
dirname: string, // eslint-disable-line no-unused-vars
envName: string, // eslint-disable-line no-unused-vars
caller: CallerMetadata | void, // eslint-disable-line no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-unused-vars
dirname: string,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
envName: string,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
caller: CallerMetadata | void,
): Handler<ConfigFile | null> {
return null;
}
@ -52,27 +57,30 @@ export function* findRootConfig(
export function* loadConfig(
name: string,
dirname: string,
envName: string, // eslint-disable-line no-unused-vars
caller: CallerMetadata | void, // eslint-disable-line no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-unused-vars
envName: string,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
caller: CallerMetadata | void,
): Handler<ConfigFile> {
throw new Error(`Cannot load ${name} relative to ${dirname} in a browser`);
}
// eslint-disable-next-line require-yield
export function* resolveShowConfigPath(
dirname: string, // eslint-disable-line no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-unused-vars
dirname: string,
): Handler<string | null> {
return null;
}
export const ROOT_CONFIG_FILENAMES = [];
// eslint-disable-next-line no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function resolvePlugin(name: string, dirname: string): string | null {
return null;
}
// eslint-disable-next-line no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function resolvePreset(name: string, dirname: string): string | null {
return null;
}
@ -80,7 +88,10 @@ export function resolvePreset(name: string, dirname: string): string | null {
export function loadPlugin(
name: string,
dirname: string,
): Handler<{ filepath: string, value: mixed }> {
): Handler<{
filepath: string;
value: unknown;
}> {
throw new Error(
`Cannot load plugin ${name} relative to ${dirname} in a browser`,
);
@ -89,7 +100,10 @@ export function loadPlugin(
export function loadPreset(
name: string,
dirname: string,
): Handler<{ filepath: string, value: mixed }> {
): Handler<{
filepath: string;
value: unknown;
}> {
throw new Error(
`Cannot load preset ${name} relative to ${dirname} in a browser`,
);

View File

@ -1,11 +1,9 @@
// @flow
import typeof * as indexBrowserType from "./index-browser";
import typeof * as indexType from "./index";
type indexBrowserType = typeof import("./index-browser");
type indexType = typeof import("./index");
// Kind of gross, but essentially asserting that the exports of this module are the same as the
// exports of index-browser, since this file may be replaced at bundle time with index-browser.
((({}: any): $Exact<indexBrowserType>): $Exact<indexType>);
((({} as any) as indexBrowserType) as indexType);
export { findPackageData } from "./package";

View File

@ -17,7 +17,7 @@ export default function* loadCjsOrMjsDefault(
asyncError: string,
// TODO(Babel 8): Remove this
fallbackToTranspiledModule: boolean = false,
): Handler<mixed> {
): Handler<unknown> {
switch (guessJSModuleType(filepath)) {
case "cjs":
return loadCjsDefault(filepath, fallbackToTranspiledModule);
@ -48,7 +48,7 @@ function guessJSModuleType(filename: string): "cjs" | "mjs" | "unknown" {
}
function loadCjsDefault(filepath: string, fallbackToTranspiledModule: boolean) {
const module = (require(filepath): mixed);
const module = require(filepath) as any;
return module?.__esModule
? // TODO (Babel 8): Remove "module" and "undefined" fallback
module.default || (fallbackToTranspiledModule ? module : undefined)

View File

@ -1,5 +1,3 @@
// @flow
import path from "path";
import type { Handler } from "gensync";
import { makeStaticFileCache } from "./utils";
@ -39,7 +37,7 @@ const readConfigPackage = makeStaticFileCache(
(filepath, content): ConfigFile => {
let options;
try {
options = (JSON.parse(content): mixed);
options = JSON.parse(content) as unknown;
} catch (err) {
err.message = `${filepath}: Error while parsing JSON - ${err.message}`;
throw err;

View File

@ -1,17 +1,14 @@
// @flow
/**
* This file handles all logic for converting string-based configuration references into loaded objects.
*/
import buildDebug from "debug";
import path from "path";
import { type Handler } from "gensync";
import type { Handler } from "gensync";
import loadCjsOrMjsDefault from "./module-types";
import { createRequire } from "module";
// $FlowIgnore - https://github.com/facebook/flow/issues/6913#issuecomment-662787504
const require = createRequire(import /*::("")*/.meta.url);
const require = createRequire(import.meta.url);
const debug = buildDebug("babel:config:loading:files:plugins");
@ -35,7 +32,7 @@ export function resolvePreset(name: string, dirname: string): string | null {
export function* loadPlugin(
name: string,
dirname: string,
): Handler<{ filepath: string, value: mixed }> {
): Handler<{ filepath: string; value: unknown }> {
const filepath = resolvePlugin(name, dirname);
if (!filepath) {
throw new Error(`Plugin ${name} not found relative to ${dirname}`);
@ -50,7 +47,7 @@ export function* loadPlugin(
export function* loadPreset(
name: string,
dirname: string,
): Handler<{ filepath: string, value: mixed }> {
): Handler<{ filepath: string; value: unknown }> {
const filepath = resolvePreset(name, dirname);
if (!filepath) {
throw new Error(`Preset ${name} not found relative to ${dirname}`);
@ -151,7 +148,7 @@ function resolveStandardizedName(
}
const LOADING_MODULES = new Set();
function* requireModule(type: string, name: string): Handler<mixed> {
function* requireModule(type: string, name: string): Handler<unknown> {
if (LOADING_MODULES.has(name)) {
throw new Error(
`Reentrant ${type} detected trying to load "${name}". This module is not ignored ` +
@ -162,7 +159,7 @@ function* requireModule(type: string, name: string): Handler<mixed> {
try {
LOADING_MODULES.add(name);
return (yield* loadCjsOrMjsDefault(
return yield* loadCjsOrMjsDefault(
name,
`You appear to be using a native ECMAScript module ${type}, ` +
"which is only supported when running Babel asynchronously.",
@ -171,7 +168,7 @@ function* requireModule(type: string, name: string): Handler<mixed> {
// export.
// See packages/babel-core/test/fixtures/option-manager/presets/es2015_named.js
true,
): mixed);
);
} catch (err) {
err.message = `[BABEL]: ${err.message} (While processing: ${name})`;
throw err;

View File

@ -1,38 +1,32 @@
// @flow
export type ConfigFile = {
filepath: string,
dirname: string,
options: {},
filepath: string;
dirname: string;
options: {};
};
export type IgnoreFile = {
filepath: string,
dirname: string,
ignore: Array<RegExp>,
filepath: string;
dirname: string;
ignore: Array<RegExp>;
};
export type RelativeConfig = {
// The actual config, either from package.json#babel, .babelrc, or
// .babelrc.js, if there was one.
config: ConfigFile | null,
config: ConfigFile | null;
// The .babelignore, if there was one.
ignore: IgnoreFile | null,
ignore: IgnoreFile | null;
};
export type FilePackageData = {
// The file in the package.
filepath: string,
filepath: string;
// Any ancestor directories of the file that are within the package.
directories: Array<string>,
directories: Array<string>;
// The contents of the package.json. May not be found if the package just
// terminated at a node_modules folder without finding one.
pkg: ConfigFile | null,
pkg: ConfigFile | null;
// True if a package.json or node_modules folder was found while traversing
// the directory structure.
isPackage: boolean,
isPackage: boolean;
};

View File

@ -1,17 +1,16 @@
// @flow
import type { Handler } from "gensync";
import type { Gensync, Handler } from "gensync";
import { makeStrongCache, type CacheConfigurator } from "../caching";
import { makeStrongCache } from "../caching";
import type { CacheConfigurator } from "../caching";
import * as fs from "../../gensync-utils/fs";
import nodeFs from "fs";
export function makeStaticFileCache<T>(
fn: (string, string) => T,
): Gensync<[string], T | null> {
return (makeStrongCache(function* (
fn: (filepath: string, contents: string) => T,
) {
return makeStrongCache(function* (
filepath: string,
cache: CacheConfigurator<?void>,
cache: CacheConfigurator<void>,
): Handler<null | T> {
const cached = cache.invalidate(() => fileMtime(filepath));
@ -20,7 +19,7 @@ export function makeStaticFileCache<T>(
}
return fn(filepath, yield* fs.readFile(filepath, "utf8"));
}): Gensync<any, *>);
});
}
function fileMtime(filepath: string): number | null {

View File

@ -1,32 +1,29 @@
// @flow
import gensync, { type Handler } from "gensync";
import gensync from "gensync";
import type { Handler } from "gensync";
import { forwardAsync, maybeAsync, isThenable } from "../gensync-utils/async";
import { mergeOptions } from "./util";
import * as context from "../index";
import Plugin from "./plugin";
import { getItemDescriptor } from "./item";
import {
buildPresetChain,
type ConfigContext,
type ConfigChain,
type PresetInstance,
import { buildPresetChain } from "./config-chain";
import type {
ConfigContext,
ConfigChain,
PresetInstance,
} from "./config-chain";
import type { UnloadedDescriptor } from "./config-descriptors";
import traverse from "@babel/traverse";
import {
makeWeakCache,
makeWeakCacheSync,
type CacheConfigurator,
} from "./caching";
import { makeWeakCache, makeWeakCacheSync } from "./caching";
import type { CacheConfigurator } from "./caching";
import {
validate,
checkNoUnwrappedItemOptionPairs,
type PluginItem,
} from "./validation/options";
import type { PluginItem } from "./validation/options";
import { validatePluginObject } from "./validation/plugins";
import { makePluginAPI, makePresetAPI } from "./helpers/config-api";
import type { PluginAPI, PresetAPI } from "./helpers/config-api";
import loadPrivatePartialConfig from "./partial";
import type { ValidatedOptions } from "./validation/options";
@ -34,26 +31,25 @@ import type { ValidatedOptions } from "./validation/options";
import * as Context from "./cache-contexts";
type LoadedDescriptor = {
value: {},
options: {},
dirname: string,
alias: string,
value: {};
options: {};
dirname: string;
alias: string;
};
export type { InputOptions } from "./validation/options";
export type ResolvedConfig = {
options: Object,
passes: PluginPasses,
options: any;
passes: PluginPasses;
};
export type { Plugin };
export type PluginPassList = Array<Plugin>;
export type PluginPasses = Array<PluginPassList>;
export default gensync<[any], ResolvedConfig | null>(function* loadFullConfig(
inputOpts: mixed,
): Handler<ResolvedConfig | null> {
export default gensync<(inputOpts: unknown) => ResolvedConfig | null>(
function* loadFullConfig(inputOpts) {
const result = yield* loadPrivatePartialConfig(inputOpts);
if (!result) {
return null;
@ -98,10 +94,10 @@ export default gensync<[any], ResolvedConfig | null>(function* loadFullConfig(
rawPresets: Array<UnloadedDescriptor>,
pluginDescriptorsPass: Array<UnloadedDescriptor>,
) {
const presets: Array<{|
preset: ConfigChain | null,
pass: Array<UnloadedDescriptor>,
|}> = [];
const presets: Array<{
preset: ConfigChain | null;
pass: Array<UnloadedDescriptor>;
}> = [];
for (let i = 0; i < rawPresets.length; i++) {
const descriptor = rawPresets[i];
@ -112,12 +108,18 @@ export default gensync<[any], ResolvedConfig | null>(function* loadFullConfig(
// in the previous pass.
if (descriptor.ownPass) {
presets.push({
preset: yield* loadPresetDescriptor(descriptor, pluginContext),
preset: yield* loadPresetDescriptor(
descriptor,
pluginContext,
),
pass: [],
});
} else {
presets.unshift({
preset: yield* loadPresetDescriptor(descriptor, pluginContext),
preset: yield* loadPresetDescriptor(
descriptor,
pluginContext,
),
pass: pluginDescriptorsPass,
});
}
@ -137,7 +139,9 @@ export default gensync<[any], ResolvedConfig | null>(function* loadFullConfig(
pluginDescriptorsByPass.splice(
1,
0,
...presets.map(o => o.pass).filter(p => p !== pluginDescriptorsPass),
...presets
.map(o => o.pass)
.filter(p => p !== pluginDescriptorsPass),
);
for (const { preset, pass } of presets) {
@ -145,7 +149,10 @@ export default gensync<[any], ResolvedConfig | null>(function* loadFullConfig(
pass.push(...preset.plugins);
const ignored = yield* recursePresetDescriptors(preset.presets, pass);
const ignored = yield* recursePresetDescriptors(
preset.presets,
pass,
);
if (ignored) return true;
preset.options.forEach(opts => {
@ -158,7 +165,7 @@ export default gensync<[any], ResolvedConfig | null>(function* loadFullConfig(
if (ignored) return null;
const opts: Object = optionDefaults;
const opts: any = optionDefaults;
mergeOptions(opts, options);
yield* enhanceError(context, function* loadPluginDescriptors() {
@ -196,10 +203,11 @@ export default gensync<[any], ResolvedConfig | null>(function* loadFullConfig(
options: opts,
passes: passes,
};
});
},
);
function enhanceError<T: Function>(context, fn: T): T {
return (function* (arg1, arg2) {
function enhanceError<T extends Function>(context, fn: T): T {
return function* (arg1, arg2) {
try {
return yield* fn(arg1, arg2);
} catch (e) {
@ -211,7 +219,7 @@ function enhanceError<T: Function>(context, fn: T): T {
throw e;
}
}: any);
} as any;
}
/**
@ -255,7 +263,8 @@ const makeDescriptorLoader = <Context, API>(
}
if (isThenable(item)) {
yield* []; // if we want to support async plugins
// @ts-expect-error - if we want to support async plugins
yield* [];
throw new Error(
`You appear to be using a promise as a plugin, ` +
@ -270,12 +279,14 @@ const makeDescriptorLoader = <Context, API>(
return { value: item, options, dirname, alias };
});
const pluginDescriptorLoader = makeDescriptorLoader<Context.SimplePlugin, *>(
makePluginAPI,
);
const presetDescriptorLoader = makeDescriptorLoader<Context.SimplePreset, *>(
makePresetAPI,
);
const pluginDescriptorLoader = makeDescriptorLoader<
Context.SimplePlugin,
PluginAPI
>(makePluginAPI);
const presetDescriptorLoader = makeDescriptorLoader<
Context.SimplePreset,
PresetAPI
>(makePresetAPI);
/**
* Instantiate a plugin for the given descriptor, returning the plugin/options pair.

View File

@ -1,14 +1,12 @@
// @flow
import semver from "semver";
import type { Targets } from "@babel/helper-compilation-targets";
import { version as coreVersion } from "../../";
import {
assertSimpleType,
type CacheConfigurator,
type SimpleCacheConfigurator,
type SimpleType,
import { assertSimpleType } from "../caching";
import type {
CacheConfigurator,
SimpleCacheConfigurator,
SimpleType,
} from "../caching";
import type { CallerMetadata } from "../validation/options";
@ -16,38 +14,36 @@ import type { CallerMetadata } from "../validation/options";
import * as Context from "../cache-contexts";
type EnvFunction = {
(): string,
<T>((string) => T): T,
(string): boolean,
(Array<string>): boolean,
(): string;
<T>(extractor: (babelEnv: string) => T): T;
(envVar: string): boolean;
(envVars: Array<string>): boolean;
};
type CallerFactory = ((CallerMetadata | void) => mixed) => SimpleType;
type CallerFactory = (
extractor: (callerMetadata: CallerMetadata | void) => unknown,
) => SimpleType;
type TargetsFunction = () => Targets;
type AssumptionFunction = (name: string) => boolean | void;
export type ConfigAPI = {|
version: string,
cache: SimpleCacheConfigurator,
env: EnvFunction,
async: () => boolean,
assertVersion: typeof assertVersion,
caller?: CallerFactory,
|};
export type ConfigAPI = {
version: string;
cache: SimpleCacheConfigurator;
env: EnvFunction;
async: () => boolean;
assertVersion: typeof assertVersion;
caller?: CallerFactory;
};
export type PresetAPI = {|
...ConfigAPI,
targets: TargetsFunction,
|};
export type PresetAPI = {
targets: TargetsFunction;
} & ConfigAPI;
export type PluginAPI = {|
...PresetAPI,
assumption: AssumptionFunction,
|};
export type PluginAPI = {
assumption: AssumptionFunction;
} & PresetAPI;
export function makeConfigAPI<SideChannel: Context.SimpleConfig>(
export function makeConfigAPI<SideChannel extends Context.SimpleConfig>(
cache: CacheConfigurator<SideChannel>,
): ConfigAPI {
const env: any = value =>
@ -58,7 +54,7 @@ export function makeConfigAPI<SideChannel: Context.SimpleConfig>(
}
if (!Array.isArray(value)) value = [value];
return value.some((entry: mixed) => {
return value.some((entry: unknown) => {
if (typeof entry !== "string") {
throw new Error("Unexpected non-string value");
}
@ -79,7 +75,7 @@ export function makeConfigAPI<SideChannel: Context.SimpleConfig>(
};
}
export function makePresetAPI<SideChannel: Context.SimplePreset>(
export function makePresetAPI<SideChannel extends Context.SimplePreset>(
cache: CacheConfigurator<SideChannel>,
): PresetAPI {
const targets = () =>
@ -91,7 +87,7 @@ export function makePresetAPI<SideChannel: Context.SimplePreset>(
return { ...makeConfigAPI(cache), targets };
}
export function makePluginAPI<SideChannel: Context.SimplePlugin>(
export function makePluginAPI<SideChannel extends Context.SimplePlugin>(
cache: CacheConfigurator<SideChannel>,
): PluginAPI {
const assumption = name => cache.using(data => data.assumptions[name]);
@ -133,12 +129,9 @@ function assertVersion(range: string | number): void {
Error.stackTraceLimit = limit;
}
throw Object.assign(
err,
({
throw Object.assign(err, {
code: "BABEL_VERSION_UNSUPPORTED",
version: coreVersion,
range,
}: any),
);
});
}

View File

@ -1,5 +1,3 @@
// @flow
export function getEnv(defaultValue: string = "development"): string {
return process.env.BABEL_ENV || process.env.NODE_ENV || defaultValue;
}

View File

@ -1,5 +1,3 @@
// @flow
import gensync from "gensync";
export type {
@ -18,19 +16,19 @@ export { loadFullConfig as default };
export type { PartialConfig } from "./partial";
import { createConfigItem as createConfigItemImpl } from "./item";
import type { ConfigItem } from "./item";
const loadOptionsRunner = gensync<[mixed], Object | null>(function* (opts) {
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 createConfigItemRunner = gensync<[PluginTarget, any], Object | null>(
// $FlowIgnore
createConfigItemImpl,
);
const createConfigItemRunner = gensync<
(...args: Parameters<typeof createConfigItemImpl>) => ConfigItem
>(createConfigItemImpl);
const maybeErrback = runner => (opts: mixed, callback: Function) => {
const maybeErrback = runner => (opts: unknown, callback?: Function) => {
if (callback === undefined && typeof opts === "function") {
callback = opts;
opts = undefined;
@ -51,7 +49,7 @@ export const createConfigItemAsync = createConfigItemRunner.async;
export function createConfigItem(
target: PluginTarget,
options: any,
callback?: Function,
callback?: (err: Error, val: ConfigItem | null) => void,
) {
if (callback !== undefined) {
return createConfigItemRunner.errback(target, options, callback);

View File

@ -1,15 +1,10 @@
// @flow
/*:: declare var invariant; */
import type { Handler } from "gensync";
import type { PluginTarget, PluginOptions } from "./validation/options";
import path from "path";
import {
createDescriptor,
type UnloadedDescriptor,
} from "./config-descriptors";
import { createDescriptor } from "./config-descriptors";
import type { UnloadedDescriptor } from "./config-descriptors";
export function createItemFromDescriptor(desc: UnloadedDescriptor): ConfigItem {
return new ConfigItem(desc);
@ -30,8 +25,8 @@ export function* createConfigItem(
dirname = ".",
type,
}: {
dirname?: string,
type?: "preset" | "plugin",
dirname?: string;
type?: "preset" | "plugin";
} = {},
): Handler<ConfigItem> {
const descriptor = yield* createDescriptor(value, path.resolve(dirname), {
@ -42,10 +37,9 @@ export function* createConfigItem(
return createItemFromDescriptor(descriptor);
}
export function getItemDescriptor(item: mixed): UnloadedDescriptor | void {
if ((item: any)?.[CONFIG_ITEM_BRAND]) {
/*:: invariant(item instanceof ConfigItem) */
return item._descriptor;
export function getItemDescriptor(item: unknown): UnloadedDescriptor | void {
if ((item as any)?.[CONFIG_ITEM_BRAND]) {
return (item as ConfigItem)._descriptor;
}
return undefined;
@ -74,7 +68,6 @@ class ConfigItem {
/**
* Used to detect ConfigItem instances from other Babel instances.
*/
// $FlowIgnore
[CONFIG_ITEM_BRAND] = true;
/**
@ -105,10 +98,9 @@ class ConfigItem {
*/
file: {
// The requested path, e.g. "@babel/env".
request: string,
request: string;
// The resolved absolute path of the file.
resolved: string,
resolved: string;
} | void;
constructor(descriptor: UnloadedDescriptor) {

View File

@ -1,30 +1,26 @@
// @flow
import path from "path";
import gensync, { type Handler } from "gensync";
import gensync from "gensync";
import type { Handler } from "gensync";
import Plugin from "./plugin";
import { mergeOptions } from "./util";
import { createItemFromDescriptor } from "./item";
import {
buildRootChain,
type ConfigContext,
type FileHandling,
} from "./config-chain";
import { buildRootChain } from "./config-chain";
import type { ConfigContext, FileHandling } from "./config-chain";
import { getEnv } from "./helpers/environment";
import {
validate,
type ValidatedOptions,
type NormalizedOptions,
type RootMode,
import { validate } from "./validation/options";
import type {
ValidatedOptions,
NormalizedOptions,
RootMode,
} from "./validation/options";
import {
findConfigUpwards,
resolveShowConfigPath,
ROOT_CONFIG_FILENAMES,
type ConfigFile,
type IgnoreFile,
} from "./files";
import type { ConfigFile, IgnoreFile } from "./files";
import { resolveTargets } from "./resolve-targets";
function* resolveRootMode(
@ -45,12 +41,12 @@ function* resolveRootMode(
if (upwardRootDir !== null) return upwardRootDir;
throw Object.assign(
(new Error(
new Error(
`Babel was run with rootMode:"upward" but a root could not ` +
`be found when searching upward from "${rootDir}".\n` +
`One of the following config files must be in the directory tree: ` +
`"${ROOT_CONFIG_FILENAMES.join(", ")}".`,
): any),
) as any,
{
code: "BABEL_ROOT_NOT_FOUND",
dirname: rootDir,
@ -63,17 +59,17 @@ function* resolveRootMode(
}
type PrivPartialConfig = {
options: NormalizedOptions,
context: ConfigContext,
fileHandling: FileHandling,
ignore: IgnoreFile | void,
babelrc: ConfigFile | void,
config: ConfigFile | void,
files: Set<string>,
options: NormalizedOptions;
context: ConfigContext;
fileHandling: FileHandling;
ignore: IgnoreFile | void;
babelrc: ConfigFile | void;
config: ConfigFile | void;
files: Set<string>;
};
export default function* loadPrivatePartialConfig(
inputOpts: mixed,
inputOpts: unknown,
): Handler<PrivPartialConfig | null> {
if (
inputOpts != null &&
@ -121,7 +117,7 @@ export default function* loadPrivatePartialConfig(
assumptions: {},
};
configChain.options.forEach(opts => {
mergeOptions((merged: any), opts);
mergeOptions(merged as any, opts);
});
const options: NormalizedOptions = {
@ -163,12 +159,12 @@ export default function* loadPrivatePartialConfig(
}
type LoadPartialConfigOpts = {
showIgnoredFiles?: boolean,
...
showIgnoredFiles?: boolean;
};
export const loadPartialConfig = gensync<[any], PartialConfig | null>(
function* (opts?: LoadPartialConfigOpts): Handler<PartialConfig | null> {
export const loadPartialConfig = gensync<
(opts?: LoadPartialConfigOpts) => PartialConfig | null
>(function* (opts) {
let showIgnoredFiles = false;
// We only extract showIgnoredFiles if opts is an object, so that
// loadPrivatePartialConfig can throw the appropriate error if it's not.
@ -176,7 +172,10 @@ export const loadPartialConfig = gensync<[any], PartialConfig | null>(
({ showIgnoredFiles, ...opts } = opts);
}
const result: ?PrivPartialConfig = yield* loadPrivatePartialConfig(opts);
const result:
| PrivPartialConfig
| undefined
| null = yield* loadPrivatePartialConfig(opts);
if (!result) return null;
const { options, babelrc, ignore, config, fileHandling, files } = result;
@ -186,6 +185,7 @@ export const loadPartialConfig = gensync<[any], PartialConfig | null>(
}
(options.plugins || []).forEach(item => {
// @ts-expect-error todo(flow->ts): better type annotation for `item.value`
if (item.value instanceof Plugin) {
throw new Error(
"Passing cached plugin instances is not supported in " +
@ -202,8 +202,7 @@ export const loadPartialConfig = gensync<[any], PartialConfig | null>(
fileHandling,
files,
);
},
);
});
export type { PartialConfig };

View File

@ -1,4 +1,3 @@
// @flow
import path from "path";
const sep = `\\${path.sep}`;

View File

@ -1,10 +1,8 @@
// @flow
import type { PluginObject } from "./validation/plugins";
export default class Plugin {
key: ?string;
manipulateOptions: ((options: mixed, parserOpts: mixed) => void) | void;
key: string | undefined | null;
manipulateOptions: ((options: unknown, parserOpts: unknown) => void) | void;
post: Function | void;
pre: Function | void;
visitor: {};

View File

@ -1,6 +1,6 @@
// @flow
import gensync from "gensync";
import gensync, { type Handler } from "gensync";
import type { Handler } from "gensync";
import type {
OptionsAndDescriptors,
@ -14,19 +14,19 @@ export const ChainFormatter = {
};
type PrintableConfig = {
content: OptionsAndDescriptors,
type: $Values<typeof ChainFormatter>,
callerName: ?string,
filepath: ?string,
index: ?number,
envName: ?string,
content: OptionsAndDescriptors;
type: typeof ChainFormatter[keyof typeof ChainFormatter];
callerName: string | undefined | null;
filepath: string | undefined | null;
index: number | undefined | null;
envName: string | undefined | null;
};
const Formatter = {
title(
type: $Values<typeof ChainFormatter>,
callerName: ?string,
filepath: ?string,
type: typeof ChainFormatter[keyof typeof ChainFormatter],
callerName?: string | null,
filepath?: string | null,
): string {
let title = "";
if (type === ChainFormatter.Programmatic) {
@ -35,12 +35,11 @@ const Formatter = {
title += " from " + callerName;
}
} else {
// $FlowIgnore
title = "config " + filepath;
}
return title;
},
loc(index: ?number, envName: ?string): string {
loc(index?: number | null, envName?: string | null): string {
let loc = "";
if (index != null) {
loc += `.overrides[${index}]`;
@ -69,7 +68,9 @@ const Formatter = {
},
};
function descriptorToConfig(d: UnloadedDescriptor): string | {} | Array<mixed> {
function descriptorToConfig(
d: UnloadedDescriptor,
): string | {} | Array<unknown> {
let name = d.file?.request;
if (name == null) {
if (typeof d.value === "object") {
@ -97,14 +98,20 @@ export class ConfigPrinter {
_stack: Array<PrintableConfig> = [];
configure(
enabled: boolean,
type: $Values<typeof ChainFormatter>,
{ callerName, filepath }: { callerName?: string, filepath?: string },
type: typeof ChainFormatter[keyof typeof ChainFormatter],
{
callerName,
filepath,
}: {
callerName?: string;
filepath?: string;
},
) {
if (!enabled) return () => {};
return (
content: OptionsAndDescriptors,
index: ?number,
envName: ?string,
index?: number | null,
envName?: string | null,
) => {
this._stack.push({
type,

View File

@ -1,12 +1,12 @@
// @flow
import type { ValidatedOptions } from "./validation/options";
import getTargets, { type Targets } from "@babel/helper-compilation-targets";
import getTargets from "@babel/helper-compilation-targets";
import type { Targets } from "@babel/helper-compilation-targets";
export function resolveBrowserslistConfigFile(
// eslint-disable-next-line no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-unused-vars
browserslistConfigFile: string,
// eslint-disable-next-line no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-unused-vars
configFilePath: string,
): string | void {
return undefined;
@ -14,19 +14,19 @@ export function resolveBrowserslistConfigFile(
export function resolveTargets(
options: ValidatedOptions,
// eslint-disable-next-line no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-unused-vars
root: string,
): Targets {
let { targets } = options;
// 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 };
}
// $FlowIgnore it thinks that targets.esmodules doesn't exist.
if (targets && targets.esmodules) {
targets = { ...targets, esmodules: "intersect" };
}
return getTargets((targets: any), {
return getTargets(targets, {
ignoreBrowserslistConfig: true,
browserslistEnv: options.browserslistEnv,
});

View File

@ -1,20 +1,20 @@
// @flow
import typeof * as browserType from "./resolve-targets-browser";
import typeof * as nodeType from "./resolve-targets";
type browserType = typeof import("./resolve-targets-browser");
type nodeType = typeof import("./resolve-targets");
// Kind of gross, but essentially asserting that the exports of this module are the same as the
// exports of index-browser, since this file may be replaced at bundle time with index-browser.
((({}: any): $Exact<browserType>): $Exact<nodeType>);
((({} as any) as browserType) as nodeType);
import type { ValidatedOptions } from "./validation/options";
import path from "path";
import getTargets, { type Targets } from "@babel/helper-compilation-targets";
import getTargets from "@babel/helper-compilation-targets";
import type { Targets } from "@babel/helper-compilation-targets";
export function resolveBrowserslistConfigFile(
browserslistConfigFile: string,
configFileDir: string,
): string | void {
): string | undefined {
return path.resolve(configFileDir, browserslistConfigFile);
}
@ -22,11 +22,11 @@ export function resolveTargets(
options: ValidatedOptions,
root: string,
): Targets {
let { targets } = options;
// 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 };
}
// $FlowIgnore it thinks that targets.esmodules doesn't exist.
if (targets && targets.esmodules) {
targets = { ...targets, esmodules: "intersect" };
}
@ -40,7 +40,7 @@ export function resolveTargets(
ignoreBrowserslistConfig = browserslistConfigFile === false;
}
return getTargets((targets: any), {
return getTargets(targets, {
ignoreBrowserslistConfig,
configFile,
configPath: root,

View File

@ -1,5 +1,3 @@
// @flow
import type { ValidatedOptions, NormalizedOptions } from "./validation/options";
export function mergeOptions(
@ -16,25 +14,22 @@ export function mergeOptions(
mergeDefaultFields(targetObj, parserOpts);
} else {
const val = source[k];
if (val !== undefined) target[k] = (val: any);
if (val !== undefined) target[k] = val as any;
}
}
}
function mergeDefaultFields<T: {}>(target: T, source: T) {
function mergeDefaultFields<T extends {}>(target: T, source: T) {
for (const k of Object.keys(source)) {
const val = source[k];
if (val !== undefined) target[k] = (val: any);
if (val !== undefined) target[k] = val as any;
}
}
export function isIterableIterator(value: mixed): boolean %checks {
export function isIterableIterator(value: any): value is IterableIterator<any> {
return (
/*:: value instanceof Generator && */
// /*:: "@@iterator" in value && */
!!value &&
typeof value.next === "function" &&
// $FlowIgnore
typeof value[Symbol.iterator] === "function"
);
}

View File

@ -1,5 +1,3 @@
// @flow
import {
isBrowsersQueryValid,
TargetNames,
@ -29,10 +27,10 @@ import { assumptionsNames } from "./options";
export type { RootPath } from "./options";
export type ValidatorSet = {
[string]: Validator<any>,
[name: string]: Validator<any>;
};
export type Validator<T> = (OptionPath, mixed) => T;
export type Validator<T> = (loc: OptionPath, value: unknown) => T;
export function msg(loc: NestingPath | GeneralPath) {
switch (loc.type) {
@ -47,6 +45,7 @@ export function msg(loc: NestingPath | GeneralPath) {
case "access":
return `${msg(loc.parent)}[${JSON.stringify(loc.name)}]`;
default:
// @ts-ignore should not happen when code is type checked
throw new Error(`Assertion failure: Unknown type ${loc.type}`);
}
}
@ -59,19 +58,22 @@ export function access(loc: GeneralPath, name: string | number): AccessPath {
};
}
export type OptionPath = $ReadOnly<{
type: "option",
name: string,
parent: NestingPath,
export type OptionPath = Readonly<{
type: "option";
name: string;
parent: NestingPath;
}>;
type AccessPath = $ReadOnly<{
type: "access",
name: string | number,
parent: GeneralPath,
type AccessPath = Readonly<{
type: "access";
name: string | number;
parent: GeneralPath;
}>;
type GeneralPath = OptionPath | AccessPath;
export function assertRootMode(loc: OptionPath, value: mixed): RootMode | void {
export function assertRootMode(
loc: OptionPath,
value: unknown,
): RootMode | void {
if (
value !== undefined &&
value !== "root" &&
@ -87,7 +89,7 @@ export function assertRootMode(loc: OptionPath, value: mixed): RootMode | void {
export function assertSourceMaps(
loc: OptionPath,
value: mixed,
value: unknown,
): SourceMapsOption | void {
if (
value !== undefined &&
@ -104,7 +106,7 @@ export function assertSourceMaps(
export function assertCompact(
loc: OptionPath,
value: mixed,
value: unknown,
): CompactOption | void {
if (value !== undefined && typeof value !== "boolean" && value !== "auto") {
throw new Error(`${msg(loc)} must be a boolean, "auto", or undefined`);
@ -114,7 +116,7 @@ export function assertCompact(
export function assertSourceType(
loc: OptionPath,
value: mixed,
value: unknown,
): SourceTypeOption | void {
if (
value !== undefined &&
@ -131,11 +133,11 @@ export function assertSourceType(
export function assertCallerMetadata(
loc: OptionPath,
value: mixed,
value: unknown,
): CallerMetadata | void {
const obj = assertObject(loc, value);
if (obj) {
if (typeof obj[("name": string)] !== "string") {
if (typeof obj.name !== "string") {
throw new Error(
`${msg(loc)} set but does not contain "name" property string`,
);
@ -161,12 +163,13 @@ export function assertCallerMetadata(
}
}
}
return (value: any);
// @ts-expect-error todo(flow->ts)
return value;
}
export function assertInputSourceMap(
loc: OptionPath,
value: mixed,
value: unknown,
): RootInputSourceMapOption | void {
if (
value !== undefined &&
@ -178,7 +181,7 @@ export function assertInputSourceMap(
return value;
}
export function assertString(loc: GeneralPath, value: mixed): string | void {
export function assertString(loc: GeneralPath, value: unknown): string | void {
if (value !== undefined && typeof value !== "string") {
throw new Error(`${msg(loc)} must be a string, or undefined`);
}
@ -187,7 +190,7 @@ export function assertString(loc: GeneralPath, value: mixed): string | void {
export function assertFunction(
loc: GeneralPath,
value: mixed,
value: unknown,
): Function | void {
if (value !== undefined && typeof value !== "function") {
throw new Error(`${msg(loc)} must be a function, or undefined`);
@ -195,7 +198,10 @@ export function assertFunction(
return value;
}
export function assertBoolean(loc: GeneralPath, value: mixed): boolean | void {
export function assertBoolean(
loc: GeneralPath,
value: unknown,
): boolean | void {
if (value !== undefined && typeof value !== "boolean") {
throw new Error(`${msg(loc)} must be a boolean, or undefined`);
}
@ -204,21 +210,22 @@ export function assertBoolean(loc: GeneralPath, value: mixed): boolean | void {
export function assertObject(
loc: GeneralPath,
value: mixed,
): { +[string]: mixed } | void {
value: unknown,
): { readonly [key: string]: unknown } | void {
if (
value !== undefined &&
(typeof value !== "object" || Array.isArray(value) || !value)
) {
throw new Error(`${msg(loc)} must be an object, or undefined`);
}
// @ts-expect-error todo(flow->ts) value is still typed as unknown, also assert function typically should not return a value
return value;
}
export function assertArray(
export function assertArray<T>(
loc: GeneralPath,
value: mixed,
): ?$ReadOnlyArray<mixed> {
value: Array<T> | undefined | null,
): ReadonlyArray<T> | undefined | null {
if (value != null && !Array.isArray(value)) {
throw new Error(`${msg(loc)} must be an array, or undefined`);
}
@ -227,15 +234,16 @@ export function assertArray(
export function assertIgnoreList(
loc: OptionPath,
value: mixed,
value: unknown[] | undefined,
): IgnoreList | void {
const arr = assertArray(loc, value);
if (arr) {
arr.forEach((item, i) => assertIgnoreItem(access(loc, i), item));
}
return (arr: any);
// @ts-expect-error todo(flow->ts)
return arr;
}
function assertIgnoreItem(loc: GeneralPath, value: mixed): IgnoreItem {
function assertIgnoreItem(loc: GeneralPath, value: unknown): IgnoreItem {
if (
typeof value !== "string" &&
typeof value !== "function" &&
@ -252,7 +260,7 @@ function assertIgnoreItem(loc: GeneralPath, value: mixed): IgnoreItem {
export function assertConfigApplicableTest(
loc: OptionPath,
value: mixed,
value: unknown,
): ConfigApplicableTest | void {
if (value === undefined) return value;
@ -269,10 +277,10 @@ export function assertConfigApplicableTest(
`${msg(loc)} must be a string/Function/RegExp, or an array of those`,
);
}
return (value: any);
return value;
}
function checkValidTest(value: mixed): boolean {
function checkValidTest(value: unknown): value is string | Function | RegExp {
return (
typeof value === "string" ||
typeof value === "function" ||
@ -282,7 +290,7 @@ function checkValidTest(value: mixed): boolean {
export function assertConfigFileSearch(
loc: OptionPath,
value: mixed,
value: unknown,
): ConfigFileSearch | void {
if (
value !== undefined &&
@ -291,7 +299,7 @@ export function assertConfigFileSearch(
) {
throw new Error(
`${msg(loc)} must be a undefined, a boolean, a string, ` +
`got ${JSON.stringify((value: any))}`,
`got ${JSON.stringify(value)}`,
);
}
@ -300,7 +308,7 @@ export function assertConfigFileSearch(
export function assertBabelrcSearch(
loc: OptionPath,
value: mixed,
value: unknown,
): BabelrcSearch | void {
if (value === undefined || typeof value === "boolean") return value;
@ -315,15 +323,15 @@ export function assertBabelrcSearch(
} else if (!checkValidTest(value)) {
throw new Error(
`${msg(loc)} must be a undefined, a boolean, a string/Function/RegExp ` +
`or an array of those, got ${JSON.stringify((value: any))}`,
`or an array of those, got ${JSON.stringify(value as any)}`,
);
}
return (value: any);
return value;
}
export function assertPluginList(
loc: OptionPath,
value: mixed,
value: unknown[] | null | undefined,
): PluginList | void {
const arr = assertArray(loc, value);
if (arr) {
@ -331,9 +339,9 @@ export function assertPluginList(
// for plugin array for use during config chain processing.
arr.forEach((item, i) => assertPluginItem(access(loc, i), item));
}
return (arr: any);
return arr as any;
}
function assertPluginItem(loc: GeneralPath, value: mixed): PluginItem {
function assertPluginItem(loc: GeneralPath, value: unknown): PluginItem {
if (Array.isArray(value)) {
if (value.length === 0) {
throw new Error(`${msg(loc)} must include an object`);
@ -369,9 +377,10 @@ function assertPluginItem(loc: GeneralPath, value: mixed): PluginItem {
assertPluginTarget(loc, value);
}
return (value: any);
// @ts-expect-error todo(flow->ts)
return value;
}
function assertPluginTarget(loc: GeneralPath, value: mixed): PluginTarget {
function assertPluginTarget(loc: GeneralPath, value: unknown): PluginTarget {
if (
(typeof value !== "object" || !value) &&
typeof value !== "string" &&
@ -384,9 +393,9 @@ function assertPluginTarget(loc: GeneralPath, value: mixed): PluginTarget {
export function assertTargets(
loc: GeneralPath,
value: mixed,
value: any,
): TargetsListOrObject {
if (isBrowsersQueryValid(value)) return (value: any);
if (isBrowsersQueryValid(value)) return value;
if (typeof value !== "object" || !value || Array.isArray(value)) {
throw new Error(
@ -416,10 +425,10 @@ export function assertTargets(
} else assertBrowserVersion(subLoc, val);
}
return (value: any);
return value;
}
function assertBrowsersList(loc: GeneralPath, value: mixed) {
function assertBrowsersList(loc: GeneralPath, value: unknown) {
if (value !== undefined && !isBrowsersQueryValid(value)) {
throw new Error(
`${msg(loc)} must be undefined, a string or an array of strings`,
@ -427,7 +436,7 @@ function assertBrowsersList(loc: GeneralPath, value: mixed) {
}
}
function assertBrowserVersion(loc: GeneralPath, value: mixed) {
function assertBrowserVersion(loc: GeneralPath, value: unknown) {
if (typeof value === "number" && Math.round(value) === value) return;
if (typeof value === "string") return;
@ -436,7 +445,7 @@ function assertBrowserVersion(loc: GeneralPath, value: mixed) {
export function assertAssumptions(
loc: GeneralPath,
value: mixed,
value: unknown,
): { [name: string]: boolean } | void {
if (value === undefined) return;
@ -444,7 +453,8 @@ export function assertAssumptions(
throw new Error(`${msg(loc)} must be an object or undefined.`);
}
let root = loc;
// todo(flow->ts): remove any
let root: any = loc;
do {
root = root.parent;
} while (root.type !== "root");
@ -465,5 +475,6 @@ export function assertAssumptions(
}
}
return (value: any);
// @ts-expect-error todo(flow->ts)
return value;
}

View File

@ -1,5 +1,3 @@
// @flow
import type { InputTargets, Targets } from "@babel/helper-compilation-targets";
import type { ConfigItem } from "../item";
@ -26,159 +24,99 @@ import {
assertCompact,
assertSourceType,
assertTargets,
type ValidatorSet,
type Validator,
type OptionPath,
assertAssumptions,
} from "./option-assertions";
import type { ValidatorSet, Validator, OptionPath } from "./option-assertions";
import type { UnloadedDescriptor } from "../config-descriptors";
const ROOT_VALIDATORS: ValidatorSet = {
cwd: (assertString: Validator<$PropertyType<ValidatedOptions, "cwd">>),
root: (assertString: Validator<$PropertyType<ValidatedOptions, "root">>),
rootMode: (assertRootMode: Validator<
$PropertyType<ValidatedOptions, "rootMode">,
>),
configFile: (assertConfigFileSearch: Validator<
$PropertyType<ValidatedOptions, "configFile">,
>),
cwd: assertString as Validator<ValidatedOptions["cwd"]>,
root: assertString as Validator<ValidatedOptions["root"]>,
rootMode: assertRootMode as Validator<ValidatedOptions["rootMode"]>,
configFile: assertConfigFileSearch as Validator<
ValidatedOptions["configFile"]
>,
caller: (assertCallerMetadata: Validator<
$PropertyType<ValidatedOptions, "caller">,
>),
filename: (assertString: Validator<
$PropertyType<ValidatedOptions, "filename">,
>),
filenameRelative: (assertString: Validator<
$PropertyType<ValidatedOptions, "filenameRelative">,
>),
code: (assertBoolean: Validator<$PropertyType<ValidatedOptions, "code">>),
ast: (assertBoolean: Validator<$PropertyType<ValidatedOptions, "ast">>),
caller: assertCallerMetadata as Validator<ValidatedOptions["caller"]>,
filename: assertString as Validator<ValidatedOptions["filename"]>,
filenameRelative: assertString as Validator<
ValidatedOptions["filenameRelative"]
>,
code: assertBoolean as Validator<ValidatedOptions["code"]>,
ast: assertBoolean as Validator<ValidatedOptions["ast"]>,
cloneInputAst: (assertBoolean: Validator<
$PropertyType<ValidatedOptions, "cloneInputAst">,
>),
cloneInputAst: assertBoolean as Validator<ValidatedOptions["cloneInputAst"]>,
envName: (assertString: Validator<
$PropertyType<ValidatedOptions, "envName">,
>),
envName: assertString as Validator<ValidatedOptions["envName"]>,
};
const BABELRC_VALIDATORS: ValidatorSet = {
babelrc: (assertBoolean: Validator<
$PropertyType<ValidatedOptions, "babelrc">,
>),
babelrcRoots: (assertBabelrcSearch: Validator<
$PropertyType<ValidatedOptions, "babelrcRoots">,
>),
babelrc: assertBoolean as Validator<ValidatedOptions["babelrc"]>,
babelrcRoots: assertBabelrcSearch as Validator<
ValidatedOptions["babelrcRoots"]
>,
};
const NONPRESET_VALIDATORS: ValidatorSet = {
extends: (assertString: Validator<
$PropertyType<ValidatedOptions, "extends">,
>),
ignore: (assertIgnoreList: Validator<
$PropertyType<ValidatedOptions, "ignore">,
>),
only: (assertIgnoreList: Validator<$PropertyType<ValidatedOptions, "only">>),
extends: assertString as Validator<ValidatedOptions["extends"]>,
ignore: assertIgnoreList as Validator<ValidatedOptions["ignore"]>,
only: assertIgnoreList as Validator<ValidatedOptions["only"]>,
targets: (assertTargets: Validator<
$PropertyType<ValidatedOptions, "targets">,
>),
browserslistConfigFile: (assertConfigFileSearch: Validator<
$PropertyType<ValidatedOptions, "browserslistConfigFile">,
>),
browserslistEnv: (assertString: Validator<
$PropertyType<ValidatedOptions, "browserslistEnv">,
>),
targets: assertTargets as Validator<ValidatedOptions["targets"]>,
browserslistConfigFile: assertConfigFileSearch as Validator<
ValidatedOptions["browserslistConfigFile"]
>,
browserslistEnv: assertString as Validator<
ValidatedOptions["browserslistEnv"]
>,
};
const COMMON_VALIDATORS: ValidatorSet = {
// TODO: Should 'inputSourceMap' be moved to be a root-only option?
// We may want a boolean-only version to be a common option, with the
// object only allowed as a root config argument.
inputSourceMap: (assertInputSourceMap: Validator<
$PropertyType<ValidatedOptions, "inputSourceMap">,
>),
presets: (assertPluginList: Validator<
$PropertyType<ValidatedOptions, "presets">,
>),
plugins: (assertPluginList: Validator<
$PropertyType<ValidatedOptions, "plugins">,
>),
passPerPreset: (assertBoolean: Validator<
$PropertyType<ValidatedOptions, "passPerPreset">,
>),
assumptions: (assertAssumptions: Validator<
$PropertyType<ValidatedOptions, "assumptions">,
>),
inputSourceMap: assertInputSourceMap as Validator<
ValidatedOptions["inputSourceMap"]
>,
presets: assertPluginList as Validator<ValidatedOptions["presets"]>,
plugins: assertPluginList as Validator<ValidatedOptions["plugins"]>,
passPerPreset: assertBoolean as Validator<ValidatedOptions["passPerPreset"]>,
assumptions: assertAssumptions as Validator<ValidatedOptions["assumptions"]>,
env: (assertEnvSet: Validator<$PropertyType<ValidatedOptions, "env">>),
overrides: (assertOverridesList: Validator<
$PropertyType<ValidatedOptions, "overrides">,
>),
env: assertEnvSet as Validator<ValidatedOptions["env"]>,
overrides: assertOverridesList as Validator<ValidatedOptions["overrides"]>,
// We could limit these to 'overrides' blocks, but it's not clear why we'd
// bother, when the ability to limit a config to a specific set of files
// is a fairly general useful feature.
test: (assertConfigApplicableTest: Validator<
$PropertyType<ValidatedOptions, "test">,
>),
include: (assertConfigApplicableTest: Validator<
$PropertyType<ValidatedOptions, "include">,
>),
exclude: (assertConfigApplicableTest: Validator<
$PropertyType<ValidatedOptions, "exclude">,
>),
test: assertConfigApplicableTest as Validator<ValidatedOptions["test"]>,
include: assertConfigApplicableTest as Validator<ValidatedOptions["include"]>,
exclude: assertConfigApplicableTest as Validator<ValidatedOptions["exclude"]>,
retainLines: (assertBoolean: Validator<
$PropertyType<ValidatedOptions, "retainLines">,
>),
comments: (assertBoolean: Validator<
$PropertyType<ValidatedOptions, "comments">,
>),
shouldPrintComment: (assertFunction: Validator<
$PropertyType<ValidatedOptions, "shouldPrintComment">,
>),
compact: (assertCompact: Validator<
$PropertyType<ValidatedOptions, "compact">,
>),
minified: (assertBoolean: Validator<
$PropertyType<ValidatedOptions, "minified">,
>),
auxiliaryCommentBefore: (assertString: Validator<
$PropertyType<ValidatedOptions, "auxiliaryCommentBefore">,
>),
auxiliaryCommentAfter: (assertString: Validator<
$PropertyType<ValidatedOptions, "auxiliaryCommentAfter">,
>),
sourceType: (assertSourceType: Validator<
$PropertyType<ValidatedOptions, "sourceType">,
>),
wrapPluginVisitorMethod: (assertFunction: Validator<
$PropertyType<ValidatedOptions, "wrapPluginVisitorMethod">,
>),
highlightCode: (assertBoolean: Validator<
$PropertyType<ValidatedOptions, "highlightCode">,
>),
sourceMaps: (assertSourceMaps: Validator<
$PropertyType<ValidatedOptions, "sourceMaps">,
>),
sourceMap: (assertSourceMaps: Validator<
$PropertyType<ValidatedOptions, "sourceMap">,
>),
sourceFileName: (assertString: Validator<
$PropertyType<ValidatedOptions, "sourceFileName">,
>),
sourceRoot: (assertString: Validator<
$PropertyType<ValidatedOptions, "sourceRoot">,
>),
parserOpts: (assertObject: Validator<
$PropertyType<ValidatedOptions, "parserOpts">,
>),
generatorOpts: (assertObject: Validator<
$PropertyType<ValidatedOptions, "generatorOpts">,
>),
retainLines: assertBoolean as Validator<ValidatedOptions["retainLines"]>,
comments: assertBoolean as Validator<ValidatedOptions["comments"]>,
shouldPrintComment: assertFunction as Validator<
ValidatedOptions["shouldPrintComment"]
>,
compact: assertCompact as Validator<ValidatedOptions["compact"]>,
minified: assertBoolean as Validator<ValidatedOptions["minified"]>,
auxiliaryCommentBefore: assertString as Validator<
ValidatedOptions["auxiliaryCommentBefore"]
>,
auxiliaryCommentAfter: assertString as Validator<
ValidatedOptions["auxiliaryCommentAfter"]
>,
sourceType: assertSourceType as Validator<ValidatedOptions["sourceType"]>,
wrapPluginVisitorMethod: assertFunction as Validator<
ValidatedOptions["wrapPluginVisitorMethod"]
>,
highlightCode: assertBoolean as Validator<ValidatedOptions["highlightCode"]>,
sourceMaps: assertSourceMaps as Validator<ValidatedOptions["sourceMaps"]>,
sourceMap: assertSourceMaps as Validator<ValidatedOptions["sourceMap"]>,
sourceFileName: assertString as Validator<ValidatedOptions["sourceFileName"]>,
sourceRoot: assertString as Validator<ValidatedOptions["sourceRoot"]>,
parserOpts: assertObject as Validator<ValidatedOptions["parserOpts"]>,
generatorOpts: assertObject as Validator<ValidatedOptions["generatorOpts"]>,
};
if (!process.env.BABEL_8_BREAKING) {
Object.assign(COMMON_VALIDATORS, {
@ -192,95 +130,86 @@ if (!process.env.BABEL_8_BREAKING) {
export type InputOptions = ValidatedOptions;
export type ValidatedOptions = {
cwd?: string,
filename?: string,
filenameRelative?: string,
babelrc?: boolean,
babelrcRoots?: BabelrcSearch,
configFile?: ConfigFileSearch,
root?: string,
rootMode?: RootMode,
code?: boolean,
ast?: boolean,
cloneInputAst?: boolean,
inputSourceMap?: RootInputSourceMapOption,
envName?: string,
caller?: CallerMetadata,
extends?: string,
env?: EnvSet<ValidatedOptions>,
ignore?: IgnoreList,
only?: IgnoreList,
overrides?: OverridesList,
cwd?: string;
filename?: string;
filenameRelative?: string;
babelrc?: boolean;
babelrcRoots?: BabelrcSearch;
configFile?: ConfigFileSearch;
root?: string;
rootMode?: RootMode;
code?: boolean;
ast?: boolean;
cloneInputAst?: boolean;
inputSourceMap?: RootInputSourceMapOption;
envName?: string;
caller?: CallerMetadata;
extends?: string;
env?: EnvSet<ValidatedOptions>;
ignore?: IgnoreList;
only?: IgnoreList;
overrides?: OverridesList;
// Generally verify if a given config object should be applied to the given file.
test?: ConfigApplicableTest,
include?: ConfigApplicableTest,
exclude?: ConfigApplicableTest,
presets?: PluginList,
plugins?: PluginList,
passPerPreset?: boolean,
assumptions?: { [name: string]: boolean },
test?: ConfigApplicableTest;
include?: ConfigApplicableTest;
exclude?: ConfigApplicableTest;
presets?: PluginList;
plugins?: PluginList;
passPerPreset?: boolean;
assumptions?: {
[name: string]: boolean;
};
// browserslists-related options
targets?: TargetsListOrObject,
browserslistConfigFile?: ConfigFileSearch,
browserslistEnv?: string,
targets?: TargetsListOrObject;
browserslistConfigFile?: ConfigFileSearch;
browserslistEnv?: string;
// Options for @babel/generator
retainLines?: boolean,
comments?: boolean,
shouldPrintComment?: Function,
compact?: CompactOption,
minified?: boolean,
auxiliaryCommentBefore?: string,
auxiliaryCommentAfter?: string,
retainLines?: boolean;
comments?: boolean;
shouldPrintComment?: Function;
compact?: CompactOption;
minified?: boolean;
auxiliaryCommentBefore?: string;
auxiliaryCommentAfter?: string;
// Parser
sourceType?: SourceTypeOption,
wrapPluginVisitorMethod?: Function,
highlightCode?: boolean,
sourceType?: SourceTypeOption;
wrapPluginVisitorMethod?: Function;
highlightCode?: boolean;
// Sourcemap generation options.
sourceMaps?: SourceMapsOption,
sourceMap?: SourceMapsOption,
sourceFileName?: string,
sourceRoot?: string,
sourceMaps?: SourceMapsOption;
sourceMap?: SourceMapsOption;
sourceFileName?: string;
sourceRoot?: string;
// Deprecate top level parserOpts
parserOpts?: {},
parserOpts?: {};
// Deprecate top level generatorOpts
generatorOpts?: {},
generatorOpts?: {};
};
export type NormalizedOptions = {
...$Diff<ValidatedOptions, { targets: any }>,
+targets: Targets,
};
readonly targets: Targets;
} & Omit<ValidatedOptions, "targets">;
export type CallerMetadata = {
// If 'caller' is specified, require that the name is given for debugging
// messages.
name: string,
name: string;
};
export type EnvSet<T> = {
[string]: ?T,
[x: string]: T;
};
export type IgnoreItem = string | Function | RegExp;
export type IgnoreList = $ReadOnlyArray<IgnoreItem>;
export type IgnoreList = ReadonlyArray<IgnoreItem>;
export type PluginOptions = {} | void | false;
export type PluginTarget = string | {} | Function;
export type PluginOptions = object | void | false;
export type PluginTarget = string | object | Function;
export type PluginItem =
| ConfigItem
| Plugin
| PluginTarget
| [PluginTarget, PluginOptions]
| [PluginTarget, PluginOptions, string | void];
export type PluginList = $ReadOnlyArray<PluginItem>;
export type PluginList = ReadonlyArray<PluginItem>;
export type OverridesList = Array<ValidatedOptions>;
export type ConfigApplicableTest = IgnoreItem | Array<IgnoreItem>;
@ -296,7 +225,7 @@ export type RootMode = "root" | "upward" | "upward-optional";
export type TargetsListOrObject =
| Targets
| InputTargets
| $PropertyType<InputTargets, "browsers">;
| InputTargets["browsers"];
export type OptionsSource =
| "arguments"
@ -306,20 +235,23 @@ export type OptionsSource =
| "preset"
| "plugin";
export type RootPath = $ReadOnly<{
type: "root",
source: OptionsSource,
export type RootPath = Readonly<{
type: "root";
source: OptionsSource;
}>;
type OverridesPath = $ReadOnly<{
type: "overrides",
index: number,
parent: RootPath,
type OverridesPath = Readonly<{
type: "overrides";
index: number;
parent: RootPath;
}>;
type EnvPath = $ReadOnly<{
type: "env",
name: string,
parent: RootPath | OverridesPath,
type EnvPath = Readonly<{
type: "env";
name: string;
parent: RootPath | OverridesPath;
}>;
export type NestingPath = RootPath | OverridesPath | EnvPath;
export const assumptionsNames = new Set<string>([
@ -369,7 +301,7 @@ function validateNested(loc: NestingPath, opts: {}) {
type: "option",
name: key,
parent: loc,
};
} as const;
if (type === "preset" && NONPRESET_VALIDATORS[key]) {
throw new Error(`${msg(optLoc)} is not allowed in preset options`);
@ -405,22 +337,19 @@ function validateNested(loc: NestingPath, opts: {}) {
NONPRESET_VALIDATORS[key] ||
BABELRC_VALIDATORS[key] ||
ROOT_VALIDATORS[key] ||
(throwUnknownError: Validator<void>);
(throwUnknownError as Validator<void>);
validator(optLoc, opts[key]);
});
return (opts: any);
return opts;
}
function throwUnknownError(loc: OptionPath) {
const key = loc.name;
if (removed[key]) {
const {
message,
version = 5,
}: { message: string, version?: number } = removed[key];
const { message, version = 5 } = removed[key];
throw new Error(
`Using removed Babel ${version} option: ${msg(loc)} - ${message}`,
@ -432,7 +361,7 @@ function throwUnknownError(loc: OptionPath) {
loc,
)}. Check out https://babeljs.io/docs/en/babel-core/#options for more information about options.`,
);
// $FlowIgnore
// @ts-expect-error todo(flow->ts): consider creating something like BabelConfigError with code field in it
unknownOptErr.code = "BABEL_UNKNOWN_OPTION";
throw unknownOptErr;
@ -449,7 +378,10 @@ function assertNoDuplicateSourcemap(opts: {}): void {
}
}
function assertEnvSet(loc: OptionPath, value: mixed): EnvSet<ValidatedOptions> {
function assertEnvSet(
loc: OptionPath,
value: unknown,
): void | EnvSet<ValidatedOptions> {
if (loc.parent.type === "env") {
throw new Error(`${msg(loc)} is not allowed inside of another .env block`);
}
@ -467,14 +399,17 @@ function assertEnvSet(loc: OptionPath, value: mixed): EnvSet<ValidatedOptions> {
type: "env",
name: envName,
parent,
};
} as const;
validateNested(envLoc, env);
}
}
return (obj: any);
return obj;
}
function assertOverridesList(loc: OptionPath, value: mixed): OverridesList {
function assertOverridesList(
loc: OptionPath,
value: unknown[],
): undefined | OverridesList {
if (loc.parent.type === "env") {
throw new Error(`${msg(loc)} is not allowed inside an .env block`);
}
@ -494,11 +429,12 @@ function assertOverridesList(loc: OptionPath, value: mixed): OverridesList {
type: "overrides",
index,
parent,
};
} as const;
validateNested(overridesLoc, env);
}
}
return (arr: any);
// @ts-expect-error
return arr;
}
export function checkNoUnwrappedItemOptionPairs(

View File

@ -1,45 +1,42 @@
// @flow
import {
assertString,
assertFunction,
assertObject,
msg,
type ValidatorSet,
type Validator,
type OptionPath,
type RootPath,
} from "./option-assertions";
import type {
ValidatorSet,
Validator,
OptionPath,
RootPath,
} from "./option-assertions";
// 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
// the declared types.
const VALIDATORS: ValidatorSet = {
name: (assertString: Validator<$PropertyType<PluginObject, "name">>),
manipulateOptions: (assertFunction: Validator<
$PropertyType<PluginObject, "manipulateOptions">,
>),
pre: (assertFunction: Validator<$PropertyType<PluginObject, "pre">>),
post: (assertFunction: Validator<$PropertyType<PluginObject, "post">>),
inherits: (assertFunction: Validator<
$PropertyType<PluginObject, "inherits">,
>),
visitor: (assertVisitorMap: Validator<
$PropertyType<PluginObject, "visitor">,
>),
name: assertString as Validator<PluginObject["name"]>,
manipulateOptions: assertFunction as Validator<
PluginObject["manipulateOptions"]
>,
pre: assertFunction as Validator<PluginObject["pre"]>,
post: assertFunction as Validator<PluginObject["post"]>,
inherits: assertFunction as Validator<PluginObject["inherits"]>,
visitor: assertVisitorMap as Validator<PluginObject["visitor"]>,
parserOverride: (assertFunction: Validator<
$PropertyType<PluginObject, "parserOverride">,
>),
generatorOverride: (assertFunction: Validator<
$PropertyType<PluginObject, "generatorOverride">,
>),
parserOverride: assertFunction as Validator<PluginObject["parserOverride"]>,
generatorOverride: assertFunction as Validator<
PluginObject["generatorOverride"]
>,
};
function assertVisitorMap(loc: OptionPath, value: mixed): VisitorMap {
function assertVisitorMap(loc: OptionPath, value: unknown): VisitorMap {
const obj = assertObject(loc, value);
if (obj) {
Object.keys(obj).forEach(prop => assertVisitorHandler(prop, obj[prop]));
// @ts-ignore
if (obj.enter || obj.exit) {
throw new Error(
`${msg(
@ -48,12 +45,12 @@ function assertVisitorMap(loc: OptionPath, value: mixed): VisitorMap {
);
}
}
return (obj: any);
return obj as VisitorMap;
}
function assertVisitorHandler(
key: string,
value: mixed,
value: unknown,
): VisitorHandler | void {
if (value && typeof value === "object") {
Object.keys(value).forEach((handler: string) => {
@ -67,26 +64,29 @@ function assertVisitorHandler(
throw new Error(`.visitor["${key}"] must be a function`);
}
return (value: any);
return value as any;
}
type VisitorHandler = Function | { enter?: Function, exit?: Function };
type VisitorHandler =
| Function
| {
enter?: Function;
exit?: Function;
};
export type VisitorMap = {
[string]: VisitorHandler,
[x: string]: VisitorHandler;
};
export type PluginObject = {
name?: string,
manipulateOptions?: (options: mixed, parserOpts: mixed) => void,
pre?: Function,
post?: Function,
inherits?: Function,
visitor?: VisitorMap,
parserOverride?: Function,
generatorOverride?: Function,
name?: string;
manipulateOptions?: (options: unknown, parserOpts: unknown) => void;
pre?: Function;
post?: Function;
inherits?: Function;
visitor?: VisitorMap;
parserOverride?: Function;
generatorOverride?: Function;
};
export function validatePluginObject(obj: {}): PluginObject {
@ -108,11 +108,11 @@ export function validatePluginObject(obj: {}): PluginObject {
const invalidPluginPropertyError = new Error(
`.${key} is not a valid Plugin property`,
);
// $FlowIgnore
// @ts-expect-error todo(flow->ts) consider additing BabelConfigError with code field
invalidPluginPropertyError.code = "BABEL_UNKNOWN_PLUGIN_PROPERTY";
throw invalidPluginPropertyError;
}
});
return (obj: any);
return obj as any;
}

View File

@ -1,5 +1,3 @@
// @flow
export default {
auxiliaryComment: {
message: "Use `auxiliaryCommentBefore` or `auxiliaryCommentAfter`",
@ -64,17 +62,15 @@ export default {
version: 6,
message: "Use `babel-plugin-module-resolver@3`'s 'resolvePath' options",
},
metadata: {
version: 6,
message:
"Generated plugin metadata is always included in the output result",
},
sourceMapTarget: {
version: 6,
message:
"The `sourceMapTarget` option has been removed because it makes more sense for the tooling " +
"that calls Babel to assign `map.file` themselves.",
},
};
} as { [name: string]: { version?: number; message: string } };

View File

@ -1,18 +1,26 @@
// @flow
import gensync, { type Gensync, type Handler } from "gensync";
import gensync from "gensync";
import type { Gensync, Handler } from "gensync";
type MaybePromise<T> = T | Promise<T>;
const id = x => x;
const runGenerator = gensync(function* (item) {
const runGenerator: {
sync<Return>(gen: Generator<unknown, Return>): Return;
async<Return>(gen: Generator<unknown, Return>): Promise<Return>;
errback<Return>(
gen: Generator<unknown, Return>,
cb: (err: Error, val: Return) => void,
): void;
} = gensync<(item: Generator) => any>(function* <Return>(
item: Generator<unknown, Return>,
) {
return yield* item;
});
// This Gensync returns true if the current execution context is
// asynchronous, otherwise it returns false.
export const isAsync = gensync<[], boolean>({
export const isAsync = gensync<() => boolean>({
sync: () => false,
errback: cb => cb(null, true),
});
@ -22,13 +30,13 @@ export const isAsync = gensync<[], boolean>({
// but the current execution context is synchronous, it will throw the
// provided error.
// This is used to handle user-provided functions which could be asynchronous.
export function maybeAsync<T, Args: any[]>(
fn: (...args: Args) => T,
export function maybeAsync<Fn extends (...args: any) => any>(
fn: Fn,
message: string,
): Gensync<Args, T> {
): Gensync<Fn> {
return gensync({
sync(...args) {
const result = fn.apply(this, args);
const result = fn.apply(this, args) as ReturnType<Fn>;
if (isThenable(result)) throw new Error(message);
return result;
},
@ -38,10 +46,10 @@ export function maybeAsync<T, Args: any[]>(
});
}
const withKind = (gensync<[any], any>({
const withKind = gensync<(cb: (kind: "sync" | "async") => any) => any>({
sync: cb => cb("sync"),
async: cb => cb("async"),
}): <T>(cb: (kind: "sync" | "async") => MaybePromise<T>) => Handler<T>);
}) as <T>(cb: (kind: "sync" | "async") => MaybePromise<T>) => Handler<T>;
// This function wraps a generator (or a Gensync) into another function which,
// when called, will run the provided generator in a sync or async way, depending
@ -57,14 +65,17 @@ const withKind = (gensync<[any], any>({
// return wrappedFn(x);
// })
// )
export function forwardAsync<ActionArgs: mixed[], ActionReturn, Return>(
action: (...args: ActionArgs) => Handler<ActionReturn>,
export function forwardAsync<
Action extends (...args: unknown[]) => any,
Return
>(
action: (...args: Parameters<Action>) => Handler<ReturnType<Action>>,
cb: (
adapted: (...args: ActionArgs) => MaybePromise<ActionReturn>,
adapted: (...args: Parameters<Action>) => MaybePromise<ReturnType<Action>>,
) => MaybePromise<Return>,
): Handler<Return> {
const g = gensync<ActionArgs, ActionReturn>(action);
return withKind<Return>(kind => {
const g = gensync<Action>(action);
return withKind(kind => {
const adapted = g[kind];
return cb(adapted);
});
@ -73,7 +84,7 @@ export function forwardAsync<ActionArgs: mixed[], ActionReturn, Return>(
// If the given generator is executed asynchronously, the first time that it
// is paused (i.e. When it yields a gensync generator which can't be run
// synchronously), call the "firstPause" callback.
export const onFirstPause = (gensync<[any, any], any>({
export const onFirstPause = gensync<(gen: Generator, cb: Function) => any>({
name: "onFirstPause",
arity: 2,
sync: function (item) {
@ -91,17 +102,16 @@ export const onFirstPause = (gensync<[any, any], any>({
firstPause();
}
},
}): <T>(gen: Generator<*, T, *>, cb: Function) => Handler<T>);
}) as <T>(gen: Generator<any, T, any>, cb: Function) => Handler<T>;
// Wait for the given promise to be resolved
export const waitFor = (gensync<[any], any>({
export const waitFor = gensync({
sync: id,
async: id,
}): <T>(p: T | Promise<T>) => Handler<T>);
}) as <T>(p: T | Promise<T>) => Handler<T>;
export function isThenable(val: mixed): boolean %checks {
export function isThenable<T = any>(val: any): val is PromiseLike<T> {
return (
/*:: val instanceof Promise && */
!!val &&
(typeof val === "object" || typeof val === "function") &&
!!val.then &&

View File

@ -1,14 +1,14 @@
// @flow
import fs from "fs";
import gensync from "gensync";
export const readFile = gensync<[string, "utf8"], string>({
export const readFile = gensync<(filepath: string, encoding: "utf8") => string>(
{
sync: fs.readFileSync,
errback: fs.readFile,
});
},
);
export const exists = gensync<[string], boolean>({
export const exists = gensync<(filepath: string) => boolean>({
sync(path) {
try {
fs.accessSync(path);
@ -20,7 +20,7 @@ export const exists = gensync<[string], boolean>({
errback: (path, cb) => fs.access(path, undefined, err => cb(null, !err)),
});
export const stat = gensync<[string], *>({
export const stat = gensync<typeof fs.statSync>({
sync: fs.statSync,
errback: fs.stat,
});

View File

@ -0,0 +1,37 @@
declare module "gensync" {
declare type Next = undefined | Function;
declare type Yield = mixed;
declare type Callback<Return> =
| ((err: Error, val: Return) => void)
| ((err: unknown) => void);
export type Gensync<Fn extends (...args: any) => any> = {
(...args: Parameters<Fn>): Handler<ReturnType<Fn>>;
sync(...args: Parameters<Fn>): ReturnType<Fn>;
async(...args: Parameters<Fn>): Promise<ReturnType<Fn>>;
errback(...args: [...Parameters<Fn>, Callback<ReturnType<Fn>>]): void;
};
export type Handler<Return> = Generator<Yield, Return, Next>;
export type Options<Fn extends (...args: any) => any> = {
sync(...args: Parameters<Fn>): ReturnType<Fn>;
arity?: number;
name?: string;
} & (
| { async?: (...args: Parameters<Fn>) => Promise<ReturnType<Fn>> }
| {
errback(...args: [...Parameters<Fn>, Callback<ReturnType<Fn>>]): void;
}
);
declare const gensync: {
<Fn extends (...args: any) => any>(
_: Options<Fn> | ((...args: Parameters<Fn>) => Handler<ReturnType<Fn>>),
): Gensync<Fn>;
all<Return>(gensyncs: Array<Handler<Return>>): Handler<Return[]>;
race<Return>(gensyncs: Array<Handler<Return>>): Handler<Return>;
};
export default gensync;
}

View File

@ -1,5 +1,4 @@
// @flow
declare const PACKAGE_JSON: { name: string; version: string };
export const version = PACKAGE_JSON.version;
export { default as File } from "./transformation/file/file";
@ -53,7 +52,7 @@ export const DEFAULT_EXTENSIONS = Object.freeze([
".es",
".mjs",
".cjs",
]);
] as const);
// For easier backward-compatibility, provide an API like the one we exposed in Babel 6.
import { loadOptions } from "./config";

View File

@ -1,28 +1,29 @@
// @flow
import gensync from "gensync";
import loadConfig, { type InputOptions } from "./config";
import loadConfig from "./config";
import type { InputOptions } from "./config";
import parser from "./parser";
import type { ParseResult } from "./parser";
import normalizeOptions from "./transformation/normalize-opts";
type FileParseCallback = {
(Error, null): any,
(null, ParseResult | null): any,
(err: Error, ast: null): any;
(err: null, ast: ParseResult | null): any;
};
type Parse = {
(code: string, callback: FileParseCallback): void,
(code: string, opts: ?InputOptions, callback: FileParseCallback): void,
// Here for backward-compatibility. Ideally use ".parseSync" if you want
// a synchronous API.
(code: string, opts: ?InputOptions): ParseResult | null,
(code: string, callback: FileParseCallback): void;
(
code: string,
opts: InputOptions | undefined | null,
callback: FileParseCallback,
): void;
(code: string, opts?: InputOptions | null): ParseResult | null;
};
const parseRunner = gensync<[string, ?InputOptions], ParseResult | null>(
function* parse(code, opts) {
const parseRunner = gensync<
(code: string, opts: InputOptions | undefined | null) => ParseResult | null
>(function* parse(code, opts) {
const config = yield* loadConfig(opts);
if (config === null) {
@ -30,10 +31,9 @@ const parseRunner = gensync<[string, ?InputOptions], ParseResult | null>(
}
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?) {
if (typeof opts === "function") {
callback = opts;
opts = undefined;
@ -44,7 +44,7 @@ export const parse: Parse = (function parse(code, opts, callback) {
if (callback === undefined) return parseRunner.sync(code, opts);
parseRunner.errback(code, opts, callback);
}: Function);
};
export const parseSync = parseRunner.sync;
export const parseAsync = parseRunner.async;

View File

@ -1,15 +1,17 @@
import type { Handler } from "gensync";
import { parse } from "@babel/parser";
import type * as t from "@babel/types";
import { codeFrameColumns } from "@babel/code-frame";
import generateMissingPluginMessage from "./util/missing-plugin-helper";
import type { PluginPasses } from "../config";
type AstRoot = BabelNodeFile | BabelNodeProgram;
type AstRoot = t.File | t.Program;
export type ParseResult = AstRoot;
export default function* parser(
pluginPasses: PluginPasses,
{ parserOpts, highlightCode = true, filename = "unknown" }: Object,
{ parserOpts, highlightCode = true, filename = "unknown" }: any,
code: string,
): Handler<ParseResult> {
try {
@ -28,7 +30,8 @@ export default function* parser(
if (results.length === 0) {
return parse(code, parserOpts);
} else if (results.length === 1) {
yield* []; // If we want to allow async parsers
// @ts-expect-error - If we want to allow async parsers
yield* [];
if (typeof results[0].then === "function") {
throw new Error(
`You appear to be using an async parser plugin, ` +

View File

@ -1,5 +1,3 @@
// @flow
const pluginNameMap = {
classProperties: {
syntax: {
@ -290,7 +288,10 @@ to enable [parsing|transformation].
*/
export default function generateMissingPluginMessage(
missingPluginName: string,
loc: { line: number, column: number },
loc: {
line: number;
column: number;
},
codeFrame: string,
): string {
let helpMessage =

View File

@ -105,7 +105,7 @@ function buildUmd(allowlist) {
AMD_ARGUMENTS: t.arrayExpression([t.stringLiteral("exports")]),
FACTORY_BODY: body,
UMD_ROOT: t.identifier("this"),
}),
}) as t.Statement,
]);
}

View File

@ -1,33 +1,30 @@
// @flow
import gensync from "gensync";
import loadConfig, { type InputOptions, type ResolvedConfig } from "./config";
import {
run,
type FileResult,
type FileResultCallback,
} from "./transformation";
import loadConfig from "./config";
import type { InputOptions, ResolvedConfig } from "./config";
import { run } from "./transformation";
import type * as t from "@babel/types";
type AstRoot = BabelNodeFile | BabelNodeProgram;
import type { FileResult, FileResultCallback } from "./transformation";
type AstRoot = t.File | t.Program;
type TransformFromAst = {
(ast: AstRoot, code: string, callback: FileResultCallback): void,
(ast: AstRoot, code: string, callback: FileResultCallback): void;
(
ast: AstRoot,
code: string,
opts: ?InputOptions,
opts: InputOptions | undefined | null,
callback: FileResultCallback,
): void,
// Here for backward-compatibility. Ideally use ".transformSync" if you want
// a synchronous API.
(ast: AstRoot, code: string, opts: ?InputOptions): FileResult | null,
): void;
(ast: AstRoot, code: string, opts?: InputOptions | null): FileResult | null;
};
const transformFromAstRunner = gensync<
[AstRoot, string, ?InputOptions],
FileResult | null,
(
ast: AstRoot,
code: string,
opts: InputOptions | undefined | null,
) => FileResult | null
>(function* (ast, code, opts) {
const config: ResolvedConfig | null = yield* loadConfig(opts);
if (config === null) return null;
@ -37,11 +34,11 @@ const transformFromAstRunner = gensync<
return yield* run(config, code, ast);
});
export const transformFromAst: TransformFromAst = (function transformFromAst(
export const transformFromAst: TransformFromAst = function transformFromAst(
ast,
code,
opts,
callback,
callback?,
) {
if (typeof opts === "function") {
callback = opts;
@ -55,7 +52,7 @@ export const transformFromAst: TransformFromAst = (function transformFromAst(
}
transformFromAstRunner.errback(ast, code, opts, callback);
}: Function);
};
export const transformFromAstSync = transformFromAstRunner.sync;
export const transformFromAstAsync = transformFromAstRunner.async;

View File

@ -1,24 +1,22 @@
// @flow
// duplicated from transform-file so we do not have to import anything here
type TransformFile = {
(filename: string, callback: Function): void,
(filename: string, opts: ?Object, callback: Function): void,
(filename: string, callback: Function): void;
(filename: string, opts: any, callback: Function): void;
};
export const transformFile: TransformFile = (function transformFile(
export const transformFile: TransformFile = function transformFile(
filename,
opts,
callback,
callback?,
) {
if (typeof opts === "function") {
callback = opts;
}
callback(new Error("Transforming files is not supported in browsers"), null);
}: Function);
};
export function transformFileSync() {
export function transformFileSync(): never {
throw new Error("Transforming files is not supported in browsers");
}

View File

@ -1,30 +1,31 @@
// @flow
import gensync from "gensync";
import loadConfig, { type InputOptions, type ResolvedConfig } from "./config";
import {
run,
type FileResult,
type FileResultCallback,
} from "./transformation";
import loadConfig from "./config";
import type { InputOptions, ResolvedConfig } from "./config";
import { run } from "./transformation";
import type { FileResult, FileResultCallback } from "./transformation";
import * as fs from "./gensync-utils/fs";
import typeof * as transformFileBrowserType from "./transform-file-browser";
import typeof * as transformFileType from "./transform-file";
type transformFileBrowserType = typeof import("./transform-file-browser");
type transformFileType = typeof import("./transform-file");
// Kind of gross, but essentially asserting that the exports of this module are the same as the
// exports of transform-file-browser, since this file may be replaced at bundle time with
// transform-file-browser.
((({}: any): $Exact<transformFileBrowserType>): $Exact<transformFileType>);
((({} as any) as transformFileBrowserType) as transformFileType);
type TransformFile = {
(filename: string, callback: FileResultCallback): void,
(filename: string, opts: ?InputOptions, callback: FileResultCallback): void,
(filename: string, callback: FileResultCallback): void;
(
filename: string,
opts: InputOptions | undefined | null,
callback: FileResultCallback,
): void;
};
const transformFileRunner = gensync<[string, ?InputOptions], FileResult | null>(
function* (filename, opts) {
const transformFileRunner = gensync<
(filename: string, opts?: InputOptions) => FileResult | null
>(function* (filename, opts: InputOptions) {
const options = { ...opts, filename };
const config: ResolvedConfig | null = yield* loadConfig(options);
@ -32,9 +33,8 @@ const transformFileRunner = gensync<[string, ?InputOptions], FileResult | null>(
const code = yield* fs.readFile(filename, "utf8");
return yield* run(config, code);
},
);
});
export const transformFile: TransformFile = transformFileRunner.errback;
export const transformFile = transformFileRunner.errback as TransformFile;
export const transformFileSync = transformFileRunner.sync;
export const transformFileAsync = transformFileRunner.async;

View File

@ -1,33 +1,31 @@
// @flow
import gensync from "gensync";
import loadConfig, { type InputOptions, type ResolvedConfig } from "./config";
import {
run,
type FileResult,
type FileResultCallback,
} from "./transformation";
import loadConfig from "./config";
import type { InputOptions, ResolvedConfig } from "./config";
import { run } from "./transformation";
import type { FileResult, FileResultCallback } from "./transformation";
type Transform = {
(code: string, callback: FileResultCallback): void,
(code: string, opts: ?InputOptions, callback: FileResultCallback): void,
// Here for backward-compatibility. Ideally use ".transformSync" if you want
// a synchronous API.
(code: string, opts: ?InputOptions): FileResult | null,
(code: string, callback: FileResultCallback): void;
(
code: string,
opts: InputOptions | undefined | null,
callback: FileResultCallback,
): void;
(code: string, opts?: InputOptions | null): FileResult | null;
};
const transformRunner = gensync<[string, ?InputOptions], FileResult | null>(
function* transform(code, opts) {
const transformRunner = gensync<
(code: string, opts?: InputOptions) => FileResult | null
>(function* transform(code, opts) {
const config: ResolvedConfig | null = yield* loadConfig(opts);
if (config === null) return null;
return yield* run(config, code);
},
);
});
export const transform: Transform = (function transform(code, opts, callback) {
export const transform: Transform = function transform(code, opts?, callback?) {
if (typeof opts === "function") {
callback = opts;
opts = undefined;
@ -38,7 +36,7 @@ export const transform: Transform = (function transform(code, opts, callback) {
if (callback === undefined) return transformRunner.sync(code, opts);
transformRunner.errback(code, opts, callback);
}: Function);
};
export const transformSync = transformRunner.sync;
export const transformAsync = transformRunner.async;

View File

@ -1,6 +1,6 @@
// @flow
import loadConfig from "../config";
import loadConfig, { type Plugin } from "../config";
import type { Plugin } from "../config";
let LOADED_PLUGIN: Plugin | void;

View File

@ -1,7 +1,6 @@
// @flow
import * as helpers from "@babel/helpers";
import { NodePath, Scope, type HubInterface } from "@babel/traverse";
import { NodePath, Scope } from "@babel/traverse";
import type { HubInterface } from "@babel/traverse";
import { codeFrameColumns } from "@babel/code-frame";
import traverse from "@babel/traverse";
import * as t from "@babel/types";
@ -22,27 +21,39 @@ const errorVisitor = {
export type NodeLocation = {
loc?: {
end?: { line: number, column: number },
start: { line: number, column: number },
},
end?: {
line: number;
column: number;
};
start: {
line: number;
column: number;
};
};
_loc?: {
end?: { line: number, column: number },
start: { line: number, column: number },
},
end?: {
line: number;
column: number;
};
start: {
line: number;
column: number;
};
};
};
export default class File {
_map: Map<any, any> = new Map();
opts: Object;
declarations: Object = {};
path: NodePath = null;
ast: Object = {};
opts: any;
declarations: any = {};
path: NodePath<t.Program> = null;
ast: any = {};
scope: Scope;
metadata: {} = {};
code: string = "";
inputMap: Object | null = null;
inputMap: any | null = null;
hub: HubInterface = {
hub: HubInterface & { file: File } = {
// keep it for the usage in babel-core, ex: path.hub.file.opts.filename
file: this,
getCode: () => this.code,
@ -63,7 +74,7 @@ export default class File {
parent: this.ast,
container: this.ast,
key: "program",
}).setContext();
}).setContext() as NodePath<t.Program>;
this.scope = this.path.scope;
}
@ -76,7 +87,7 @@ export default class File {
const { interpreter } = this.path.node;
return interpreter ? interpreter.value : "";
}
set shebang(value: string): void {
set shebang(value: string) {
if (value) {
this.path.get("interpreter").replaceWith(t.interpreterDirective(value));
} else {
@ -84,7 +95,7 @@ export default class File {
}
}
set(key: mixed, val: mixed) {
set(key: unknown, val: unknown) {
if (key === "helpersNamespace") {
throw new Error(
"Babel 7.0.0-beta.56 has dropped support for the 'helpersNamespace' utility." +
@ -98,15 +109,15 @@ export default class File {
this._map.set(key, val);
}
get(key: mixed): any {
get(key: unknown): any {
return this._map.get(key);
}
has(key: mixed): boolean {
has(key: unknown): boolean {
return this._map.has(key);
}
getModuleName(): ?string {
getModuleName(): string | undefined | null {
return getModuleName(this.opts, this.opts);
}
@ -126,7 +137,7 @@ export default class File {
* helper exists, but was not available for the full given range, it will be
* considered unavailable.
*/
availableHelper(name: string, versionRange: ?string): boolean {
availableHelper(name: string, versionRange?: string | null): boolean {
let minVersion;
try {
minVersion = helpers.minVersion(name);
@ -163,7 +174,7 @@ export default class File {
);
}
addHelper(name: string): Object {
addHelper(name: string): any {
const declar = this.declarations[name];
if (declar) return t.cloneNode(declar);
@ -220,9 +231,9 @@ export default class File {
}
buildCodeFrameError(
node: ?NodeLocation,
node: NodeLocation | undefined | null,
msg: string,
Error: typeof Error = SyntaxError,
_Error: typeof Error = SyntaxError,
): Error {
let loc = node && (node.loc || node._loc);
@ -230,7 +241,7 @@ export default class File {
const state = {
loc: null,
};
traverse(node, errorVisitor, this.scope, state);
traverse(node as t.Node, errorVisitor, this.scope, state);
loc = state.loc;
let txt =
@ -264,6 +275,6 @@ export default class File {
);
}
return new Error(msg);
return new _Error(msg);
}
}

View File

@ -1,7 +1,6 @@
// @flow
import type { PluginPasses } from "../../config";
import convertSourceMap, { typeof SourceMap } from "convert-source-map";
import convertSourceMap from "convert-source-map";
type SourceMap = any;
import generate from "@babel/generator";
import type File from "./file";
@ -11,8 +10,8 @@ export default function generateCode(
pluginPasses: PluginPasses,
file: File,
): {
outputCode: string,
outputMap: SourceMap | null,
outputCode: string;
outputMap: SourceMap | null;
} {
const { opts, ast, code, inputMap } = file;

View File

@ -1,6 +1,4 @@
// @flow
import typeof { SourceMap } from "convert-source-map";
type SourceMap = any;
import sourceMap from "source-map";
export default function mergeSourceMap(
@ -74,6 +72,7 @@ export default function mergeSourceMap(
// Insert mappings with no original position to terminate any mappings
// that were found above, so that they don't expand beyond their correct
// range.
// @ts-expect-error todo(flow->ts) original and source field are missing
mergedGenerator.addMapping({
generated: {
line: clearItem.line,
@ -93,14 +92,14 @@ export default function mergeSourceMap(
return result;
}
function makeMappingKey(item: { line: number, columnStart: number }) {
function makeMappingKey(item: { line: number; columnStart: number }) {
return `${item.line}/${item.columnStart}`;
}
function eachOverlappingGeneratedOutputRange(
outputFile: ResolvedFileMappings,
inputGeneratedRange: ResolvedGeneratedRange,
callback: ResolvedGeneratedRange => mixed,
callback: (range: ResolvedGeneratedRange) => unknown,
) {
// Find the Babel-generated mappings that overlap with this range in the
// input sourcemap. Generated locations within the input sourcemap
@ -137,10 +136,10 @@ function filterApplicableOriginalRanges(
function eachInputGeneratedRange(
map: ResolvedMappings,
callback: (
ResolvedGeneratedRange,
ResolvedOriginalRange,
ResolvedSource,
) => mixed,
c: ResolvedGeneratedRange,
b: ResolvedOriginalRange,
a: ResolvedSource,
) => unknown,
) {
for (const { source, mappings } of map.sources) {
for (const { original, generated } of mappings) {
@ -151,34 +150,39 @@ function eachInputGeneratedRange(
}
}
type ResolvedMappings = {|
file: ?string,
sourceRoot: ?string,
sources: Array<ResolvedFileMappings>,
|};
type ResolvedFileMappings = {|
source: ResolvedSource,
mappings: OriginalMappings,
|};
type OriginalMappings = Array<{|
original: ResolvedOriginalRange,
generated: Array<ResolvedGeneratedRange>,
|}>;
type ResolvedSource = {|
path: string,
content: string | null,
|};
type ResolvedOriginalRange = {|
line: number,
columnStart: number,
columnEnd: number,
name: string | null,
|};
type ResolvedGeneratedRange = {|
line: number,
columnStart: number,
columnEnd: number,
|};
type ResolvedMappings = {
file: string | undefined | null;
sourceRoot: string | undefined | null;
sources: Array<ResolvedFileMappings>;
};
type ResolvedFileMappings = {
source: ResolvedSource;
mappings: OriginalMappings;
};
type OriginalMappings = Array<{
original: ResolvedOriginalRange;
generated: Array<ResolvedGeneratedRange>;
}>;
type ResolvedSource = {
path: string;
content: string | null;
};
type ResolvedOriginalRange = {
line: number;
columnStart: number;
columnEnd: number;
name: string | null;
};
type ResolvedGeneratedRange = {
line: number;
columnStart: number;
columnEnd: number;
};
function buildMappingData(map: SourceMap): ResolvedMappings {
const consumer = new sourceMap.SourceMapConsumer({
@ -270,7 +274,7 @@ function buildMappingData(map: SourceMap): ResolvedMappings {
function findInsertionLocation<T>(
array: Array<T>,
callback: T => number,
callback: (item: T) => number,
): number {
let left = 0;
let right = array.length;
@ -304,7 +308,7 @@ function findInsertionLocation<T>(
function filterSortedArray<T>(
array: Array<T>,
callback: T => number,
callback: (item: T) => number,
): Array<T> {
const start = findInsertionLocation(array, callback);

View File

@ -1,6 +1,6 @@
// @flow
import traverse from "@babel/traverse";
import typeof { SourceMap } from "convert-source-map";
import type * as t from "@babel/types";
type SourceMap = any;
import type { Handler } from "gensync";
import type { ResolvedConfig, PluginPasses } from "../config";
@ -14,22 +14,23 @@ import generateCode from "./file/generate";
import type File from "./file/file";
export type FileResultCallback = {
(Error, null): any,
(null, FileResult | null): any,
(err: Error, file: null): any;
(err: null, file: FileResult | null): any;
};
export type FileResult = {
metadata: {},
options: {},
ast: {} | null,
code: string | null,
map: SourceMap | null,
metadata: {};
options: {};
ast: {} | null;
code: string | null;
map: SourceMap | null;
sourceType: "string" | "module";
};
export function* run(
config: ResolvedConfig,
code: string,
ast: ?(BabelNodeFile | BabelNodeProgram),
ast?: t.File | t.Program | null,
): Handler<FileResult> {
const file = yield* normalizeFile(
config.passes,
@ -91,7 +92,9 @@ function* transformFile(file: File, pluginPasses: PluginPasses): Handler<void> {
if (fn) {
const result = fn.call(pass, file);
// @ts-expect-error - If we want to support async .pre
yield* [];
if (isThenable(result)) {
throw new Error(
`You appear to be using an plugin with an async .pre, ` +
@ -116,7 +119,9 @@ function* transformFile(file: File, pluginPasses: PluginPasses): Handler<void> {
if (fn) {
const result = fn.call(pass, file);
// @ts-expect-error - If we want to support async .post
yield* [];
if (isThenable(result)) {
throw new Error(
`You appear to be using an plugin with an async .post, ` +
@ -130,7 +135,7 @@ function* transformFile(file: File, pluginPasses: PluginPasses): Handler<void> {
}
}
function isThenable(val: mixed): boolean {
function isThenable<T extends PromiseLike<any>>(val: any): val is T {
return (
!!val &&
(typeof val === "object" || typeof val === "function") &&

View File

@ -1,12 +1,11 @@
// @flow
import fs from "fs";
import path from "path";
import buildDebug from "debug";
import type { Handler } from "gensync";
import * as t from "@babel/types";
import type { PluginPasses } from "../config";
import convertSourceMap, { typeof Converter } from "convert-source-map";
import convertSourceMap from "convert-source-map";
import type { SourceMapConverter as Converter } from "convert-source-map";
import File from "./file/file";
import parser from "../parser";
import cloneDeep from "./util/clone-deep";
@ -15,16 +14,16 @@ const debug = buildDebug("babel:transform:file");
const LARGE_INPUT_SOURCEMAP_THRESHOLD = 1_000_000;
export type NormalizedFile = {
code: string,
ast: {},
inputMap: Converter | null,
code: string;
ast: {};
inputMap: Converter | null;
};
export default function* normalizeFile(
pluginPasses: PluginPasses,
options: Object,
options: any,
code: string,
ast: ?(BabelNodeFile | BabelNodeProgram),
ast?: t.File | t.Program | null,
): Handler<File> {
code = `${code || ""}`;
@ -66,16 +65,19 @@ export default function* normalizeFile(
if (typeof options.filename === "string" && lastComment) {
try {
// when `lastComment` is non-null, EXTERNAL_SOURCEMAP_REGEX must have matches
const match: [string, string] = (EXTERNAL_SOURCEMAP_REGEX.exec(
const match: [string, string] = EXTERNAL_SOURCEMAP_REGEX.exec(
lastComment,
): any);
const inputMapContent: Buffer = fs.readFileSync(
) as any;
const inputMapContent = fs.readFileSync(
path.resolve(path.dirname(options.filename), match[1]),
);
if (inputMapContent.length > LARGE_INPUT_SOURCEMAP_THRESHOLD) {
debug("skip merging input map > 1 MB");
} else {
inputMap = convertSourceMap.fromJSON(inputMapContent);
inputMap = convertSourceMap.fromJSON(
// todo:
(inputMapContent as unknown) as string,
);
}
} catch (err) {
debug("discarding unknown file input sourcemap", err);
@ -116,19 +118,16 @@ function extractCommentsFromList(regex, comments, lastComment) {
function extractComments(regex, ast) {
let lastComment = null;
t.traverseFast(ast, node => {
// $FlowIgnore destructuring with expressions is not supported
[node.leadingComments, lastComment] = extractCommentsFromList(
regex,
node.leadingComments,
lastComment,
);
// $FlowIgnore destructuring with expressions is not supported
[node.innerComments, lastComment] = extractCommentsFromList(
regex,
node.innerComments,
lastComment,
);
// $FlowIgnore destructuring with expressions is not supported
[node.trailingComments, lastComment] = extractCommentsFromList(
regex,
node.trailingComments,

View File

@ -1,5 +1,3 @@
// @flow
import path from "path";
import type { ResolvedConfig } from "../config";

View File

@ -1,13 +1,11 @@
// @flow
import type File from "./file/file";
import type NodeLocation from "./file/file";
import type { NodeLocation } from "./file/file";
export default class PluginPass {
_map: Map<mixed, mixed> = new Map();
key: ?string;
_map: Map<unknown, unknown> = new Map();
key: string | undefined | null;
file: File;
opts: Object;
opts: any;
// The working directory that Babel's programmatic options are loaded
// relative to.
@ -16,7 +14,7 @@ export default class PluginPass {
// The absolute path of the file being compiled.
filename: string | void;
constructor(file: File, key: ?string, options: ?Object) {
constructor(file: File, key?: string | null, options?: any | null) {
this.key = key;
this.file = file;
this.opts = options || {};
@ -24,15 +22,15 @@ export default class PluginPass {
this.filename = file.opts.filename;
}
set(key: mixed, val: mixed) {
set(key: unknown, val: unknown) {
this._map.set(key, val);
}
get(key: mixed): any {
get(key: unknown): any {
return this._map.get(key);
}
availableHelper(name: string, versionRange: ?string) {
availableHelper(name: string, versionRange?: string | null) {
return this.file.availableHelper(name, versionRange);
}
@ -44,14 +42,19 @@ export default class PluginPass {
return this.file.addImport();
}
buildCodeFrameError(node: ?NodeLocation, msg: string, Error?: typeof Error) {
return this.file.buildCodeFrameError(node, msg, Error);
buildCodeFrameError(
node: NodeLocation | undefined | null,
msg: string,
_Error?: typeof Error,
) {
return this.file.buildCodeFrameError(node, msg, _Error);
}
}
if (!process.env.BABEL_8_BREAKING) {
// $FlowIgnore
PluginPass.prototype.getModuleName = function getModuleName(): ?string {
(PluginPass as any).prototype.getModuleName = function getModuleName():
| string
| undefined {
return this.file.getModuleName();
};
}

View File

@ -0,0 +1,17 @@
{
"extends": "../../tsconfig.base.json",
"include": [
"./typings"
],
"references": [
{
"path": "../babel-code-frame"
},
{
"path": "../babel-helper-fixtures"
},
{
"path": "../babel-helper-validator-identifier"
}
]
}

View File

@ -167,3 +167,8 @@ export interface RecordAndTuplePluginOptions {
export interface FlowPluginOptions {
all?: boolean;
}
export const tokTypes: {
// todo(flow->ts) real token type
[name: string]: any;
};

View File

@ -211,6 +211,12 @@ __metadata:
"@babel/template": "workspace:^7.12.13"
"@babel/traverse": "workspace:^7.13.13"
"@babel/types": "workspace:^7.13.14"
"@types/convert-source-map": ^1.5.1
"@types/debug": ^4.1.0
"@types/lodash": ^4.14.150
"@types/resolve": ^1.3.2
"@types/semver": ^5.4.0
"@types/source-map": ^0.5.0
convert-source-map: ^1.7.0
debug: ^4.1.0
gensync: ^1.0.0-beta.2
@ -659,6 +665,7 @@ __metadata:
resolution: "@babel/helper-module-transforms@condition:BABEL_8_BREAKING?:workspace:^7.13.14#f57fb3"
dependencies:
"@babel/helper-module-transforms-BABEL_8_BREAKING-false": "npm:@babel/helper-module-transforms@workspace:^7.13.14"
checksum: 82d133091e69e2b2c742cfeb03c3f9acb3d0a00391d3ab2624154aa537dc714eedc5d8145c6c671bacd63d5314de09982a36b216b520c22466e4af3e375aff2d
languageName: node
linkType: hard
@ -3992,6 +3999,20 @@ __metadata:
languageName: node
linkType: hard
"@types/convert-source-map@npm:^1.5.1":
version: 1.5.1
resolution: "@types/convert-source-map@npm:1.5.1"
checksum: 36cd50ea42b5e5c41db2415e4f42bdbc426e6b963a7d0d0a511164b789d4140629fbc0b3c5a29306ad3731ab41708088bb63e95972060cd3983af1f22b33f414
languageName: node
linkType: hard
"@types/debug@npm:^4.1.0":
version: 4.1.5
resolution: "@types/debug@npm:4.1.5"
checksum: 416ad24bc589be0fb8c78bea972aa7d4ffdf6b136239701b1792674463b2dbf8c6707f6055ec484f79ec1f2b528ffef90c87e55df7e4a0f458184cad5bf0cfc8
languageName: node
linkType: hard
"@types/eslint-scope@npm:^3.7.0":
version: 3.7.0
resolution: "@types/eslint-scope@npm:3.7.0"
@ -4163,6 +4184,20 @@ __metadata:
languageName: node
linkType: hard
"@types/resolve@npm:^1.3.2":
version: 1.20.0
resolution: "@types/resolve@npm:1.20.0"
checksum: 3c75135d5cf3652453ef8f099b109f7fec5e82fe67bf38048226614dbcd11a943affee383e5d28c12c5f03b049281a3e486395326b9810297f9649c7b00f41fd
languageName: node
linkType: hard
"@types/semver@npm:^5.4.0":
version: 5.5.0
resolution: "@types/semver@npm:5.5.0"
checksum: df74589466e171c36dd868b760609e518830f212134c238674ddd6eb83653368c59f4510aa6523b7692ec99c5d8ab40b818e30f9d65e0df97c56bdbacef06661
languageName: node
linkType: hard
"@types/semver@npm:^7.3.4":
version: 7.3.4
resolution: "@types/semver@npm:7.3.4"