Skip to content

Commit

Permalink
Refine babel core types (#11544)
Browse files Browse the repository at this point in the history
Co-authored-by: Nicol貌 Ribaudo <nicolo.ribaudo@gmail.com>
  • Loading branch information
JLHwung and nicolo-ribaudo committed Jun 21, 2020
1 parent 30835f1 commit 601c824
Show file tree
Hide file tree
Showing 16 changed files with 97 additions and 50 deletions.
1 change: 1 addition & 0 deletions .flowconfig
Expand Up @@ -28,3 +28,4 @@ esproposal.export_star_as=enable
esproposal.optional_chaining=enable
esproposal.nullish_coalescing=enable
module.name_mapper='^@babel\/\([a-zA-Z0-9_\-]+\)$' -> '<PROJECT_ROOT>/packages/babel-\1/src/index'
module.ignore_non_literal_requires=true
8 changes: 8 additions & 0 deletions lib/third-party-libs.js.flow
Expand Up @@ -2,6 +2,10 @@
* Basic declarations for the npm modules we use.
*/

declare module "debug" {
declare export default (namespace: string) => (formatter: string, ...args: any[]) => void;
}

declare module "resolve" {
declare export default {
(string, {| basedir: string |}, (err: ?Error, res: string) => void): void;
Expand All @@ -27,6 +31,10 @@ declare module "lodash/merge" {
declare export default <T: Object>(T, Object) => T;
}

declare module "lodash/escapeRegExp" {
declare export default (toEscape?: string) => string;
}

declare module "semver" {
declare class SemVer {
build: Array<string>;
Expand Down
14 changes: 10 additions & 4 deletions packages/babel-core/src/config/caching.js
Expand Up @@ -108,7 +108,7 @@ function makeCachedFunction<ArgT, ResultT, SideChannel, Cache: *>(
const asyncContext = yield* isAsync();
const callCache = asyncContext ? callCacheAsync : callCacheSync;

const cached = yield* getCachedValueOrWait(
const cached = yield* getCachedValueOrWait<ArgT, ResultT, SideChannel>(
asyncContext,
callCache,
futureCache,
Expand All @@ -119,7 +119,7 @@ function makeCachedFunction<ArgT, ResultT, SideChannel, Cache: *>(

const cache = new CacheConfigurator(data);

const handlerResult = handler(arg, cache);
const handlerResult: Handler<ResultT> | ResultT = handler(arg, cache);

let finishLock: ?Lock<ResultT>;
let value: ResultT;
Expand Down Expand Up @@ -313,7 +313,7 @@ class CacheConfigurator<SideChannel = void> {
);

if (isThenable(key)) {
return key.then(key => {
return key.then((key: mixed) => {
this._pairs.push([key, fn]);
return key;
});
Expand Down Expand Up @@ -369,7 +369,13 @@ function makeSimpleConfigurator(

// Types are limited here so that in the future these values can be used
// as part of Babel's caching logic.
type SimpleType = string | boolean | number | null | void | Promise<SimpleType>;
export type SimpleType =
| string
| boolean
| number
| null
| void
| Promise<SimpleType>;
export function assertSimpleType(value: mixed): SimpleType {
if (isThenable(value)) {
throw new Error(
Expand Down
5 changes: 2 additions & 3 deletions packages/babel-core/src/config/config-chain.js
Expand Up @@ -76,7 +76,6 @@ export const buildPresetChainWalker: (
arg: PresetInstance,
context: *,
) => * = makeChainWalker({
init: arg => arg,
root: preset => loadPresetDescriptors(preset),
env: (preset, envName) => loadPresetEnvDescriptors(preset)(envName),
overrides: (preset, index) => loadPresetOverridesDescriptors(preset)(index),
Expand Down Expand Up @@ -419,12 +418,12 @@ function makeChainWalker<ArgT: { options: ValidatedOptions, dirname: string }>({
env,
overrides,
overridesEnv,
}: {
}: {|
root: ArgT => OptionsAndDescriptors,
env: (ArgT, string) => OptionsAndDescriptors | null,
overrides: (ArgT, number) => OptionsAndDescriptors,
overridesEnv: (ArgT, number, string) => OptionsAndDescriptors | null,
}): (
|}): (
ArgT,
ConfigContext,
Set<ConfigFile> | void,
Expand Down
10 changes: 5 additions & 5 deletions packages/babel-core/src/config/files/configuration.js
Expand Up @@ -151,7 +151,7 @@ export function* loadConfig(
* Read the given config file, returning the result. Returns null if no config was found, but will
* throw if there are parsing errors while loading a config.
*/
function readConfig(filepath, envName, caller) {
function readConfig(filepath, envName, caller): Handler<ConfigFile | null> {
const ext = path.extname(filepath);
return ext === ".js" || ext === ".cjs" || ext === ".mjs"
? readConfigJS(filepath, { envName, caller })
Expand Down Expand Up @@ -236,7 +236,7 @@ const readConfigJS = makeStrongCache(function* readConfigJS(

const packageToBabelConfig = makeWeakCacheSync(
(file: ConfigFile): ConfigFile | null => {
const babel = file.options[("babel": string)];
const babel: mixed = file.options[("babel": string)];

if (typeof babel === "undefined") return null;

Expand All @@ -252,7 +252,7 @@ const packageToBabelConfig = makeWeakCacheSync(
},
);

const readConfigJSON5 = makeStaticFileCache((filepath, content) => {
const readConfigJSON5 = makeStaticFileCache((filepath, content): ConfigFile => {
let options;
try {
options = json5.parse(content);
Expand Down Expand Up @@ -281,7 +281,7 @@ const readIgnoreConfig = makeStaticFileCache((filepath, content) => {
const ignoreDir = path.dirname(filepath);
const ignorePatterns = content
.split("\n")
.map(line => line.replace(/#(.*?)$/, "").trim())
.map<string>(line => line.replace(/#(.*?)$/, "").trim())
.filter(line => !!line);

for (const pattern of ignorePatterns) {
Expand All @@ -299,7 +299,7 @@ const readIgnoreConfig = makeStaticFileCache((filepath, content) => {
};
});

function throwConfigError() {
function throwConfigError(): empty {
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:
Expand Down
1 change: 1 addition & 0 deletions packages/babel-core/src/config/files/import.js
@@ -1,3 +1,4 @@
// @flow
// We keep this in a seprate file so that in older node versions, where
// import() isn't supported, we can try/catch around the require() call
// when loading this file.
Expand Down
4 changes: 3 additions & 1 deletion packages/babel-core/src/config/files/package.js
Expand Up @@ -39,12 +39,14 @@ const readConfigPackage = makeStaticFileCache(
(filepath, content): ConfigFile => {
let options;
try {
options = JSON.parse(content);
options = (JSON.parse(content): mixed);
} catch (err) {
err.message = `${filepath}: Error while parsing JSON - ${err.message}`;
throw err;
}

if (!options) throw new Error(`${filepath}: No config detected`);

if (typeof options !== "object") {
throw new Error(`${filepath}: Config returned typeof ${typeof options}`);
}
Expand Down
7 changes: 3 additions & 4 deletions packages/babel-core/src/config/files/plugins.js
Expand Up @@ -105,7 +105,7 @@ function resolveStandardizedName(
try {
resolve.sync(name, { basedir: dirname });
resolvedOriginal = true;
} catch (e2) {}
} catch {}

if (resolvedOriginal) {
e.message += `\n- If you want to resolve "${name}", use "module:${name}"`;
Expand All @@ -118,7 +118,7 @@ function resolveStandardizedName(
basedir: dirname,
});
resolvedBabel = true;
} catch (e2) {}
} catch {}

if (resolvedBabel) {
e.message += `\n- Did you mean "@babel/${name}"?`;
Expand All @@ -129,7 +129,7 @@ function resolveStandardizedName(
try {
resolve.sync(standardizeName(oppositeType, name), { basedir: dirname });
resolvedOppositeType = true;
} catch (e2) {}
} catch {}

if (resolvedOppositeType) {
e.message += `\n- Did you accidentally pass a ${oppositeType} as a ${type}?`;
Expand All @@ -151,7 +151,6 @@ function requireModule(type: string, name: string): mixed {

try {
LOADING_MODULES.add(name);
// $FlowIssue
return require(name);
} finally {
LOADING_MODULES.delete(name);
Expand Down
17 changes: 7 additions & 10 deletions packages/babel-core/src/config/full.js
Expand Up @@ -66,22 +66,16 @@ export default gensync<[any], ResolvedConfig | null>(function* loadFullConfig(
const { options, context } = result;

const optionDefaults = {};
const passes = [[]];
const passes: Array<Array<Plugin>> = [[]];
try {
const { plugins, presets } = options;

if (!plugins || !presets) {
throw new Error("Assertion failure - plugins and presets exist");
}

const ignored = yield* (function* recurseDescriptors(
config: {
plugins: Array<UnloadedDescriptor>,
presets: Array<UnloadedDescriptor>,
},
pass: Array<Plugin>,
) {
const plugins = [];
const ignored = yield* (function* recurseDescriptors(config, pass) {
const plugins: Array<Plugin> = [];
for (let i = 0; i < config.plugins.length; i++) {
const descriptor = config.plugins[i];
if (descriptor.options !== false) {
Expand All @@ -103,7 +97,10 @@ export default gensync<[any], ResolvedConfig | null>(function* loadFullConfig(
}
}

const presets = [];
const presets: Array<{|
preset: ConfigChain | null,
pass: Array<Plugin>,
|}> = [];
for (let i = 0; i < config.presets.length; i++) {
const descriptor = config.presets[i];
if (descriptor.options !== false) {
Expand Down
10 changes: 6 additions & 4 deletions packages/babel-core/src/config/helpers/config-api.js
Expand Up @@ -6,6 +6,7 @@ import {
assertSimpleType,
type CacheConfigurator,
type SimpleCacheConfigurator,
type SimpleType,
} from "../caching";

import type { CallerMetadata } from "../validation/options";
Expand All @@ -17,13 +18,15 @@ type EnvFunction = {
(Array<string>): boolean,
};

type CallerFactory = ((CallerMetadata | void) => mixed) => SimpleType;

export type PluginAPI = {|
version: string,
cache: SimpleCacheConfigurator,
env: EnvFunction,
async: () => boolean,
assertVersion: typeof assertVersion,
caller?: any,
caller?: CallerFactory,
|};

export default function makeAPI(
Expand All @@ -37,16 +40,15 @@ export default function makeAPI(
}
if (!Array.isArray(value)) value = [value];

return value.some(entry => {
return value.some((entry: mixed) => {
if (typeof entry !== "string") {
throw new Error("Unexpected non-string value");
}
return entry === data.envName;
});
});

const caller: any = cb =>
cache.using(data => assertSimpleType(cb(data.caller)));
const caller = cb => cache.using(data => assertSimpleType(cb(data.caller)));

return {
version: coreVersion,
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-core/src/config/item.js
Expand Up @@ -103,7 +103,7 @@ class ConfigItem {
// programmatically, and also make sure that if people happen to
// pass the item through JSON.stringify, it doesn't show up.
this._descriptor = descriptor;
Object.defineProperty(this, "_descriptor", ({ enumerable: false }: any));
Object.defineProperty(this, "_descriptor", { enumerable: false });

this.value = this._descriptor.value;
this.options = this._descriptor.options;
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-core/src/config/plugin.js
Expand Up @@ -4,7 +4,7 @@ import type { PluginObject } from "./validation/plugins";

export default class Plugin {
key: ?string;
manipulateOptions: Function | void;
manipulateOptions: ((options: mixed, parserOpts: mixed) => void) | void;
post: Function | void;
pre: Function | void;
visitor: {};
Expand Down
Expand Up @@ -18,6 +18,8 @@ import type {
RootMode,
} from "./options";

export type { RootPath } from "./options";

export type ValidatorSet = {
[string]: Validator<any>,
};
Expand Down Expand Up @@ -192,7 +194,10 @@ export function assertBoolean(loc: GeneralPath, value: mixed): boolean | void {
return value;
}

export function assertObject(loc: GeneralPath, value: mixed): {} | void {
export function assertObject(
loc: GeneralPath,
value: mixed,
): { +[string]: mixed } | void {
if (
value !== undefined &&
(typeof value !== "object" || Array.isArray(value) || !value)
Expand Down
9 changes: 6 additions & 3 deletions packages/babel-core/src/config/validation/options.js
Expand Up @@ -276,7 +276,7 @@ export type OptionsSource =
| "preset"
| "plugin";

type RootPath = $ReadOnly<{
export type RootPath = $ReadOnly<{
type: "root",
source: OptionsSource,
}>;
Expand Down Expand Up @@ -311,7 +311,7 @@ function validateNested(loc: NestingPath, opts: {}) {

assertNoDuplicateSourcemap(opts);

Object.keys(opts).forEach(key => {
Object.keys(opts).forEach((key: string) => {
const optLoc = {
type: "option",
name: key,
Expand Down Expand Up @@ -364,7 +364,10 @@ function throwUnknownError(loc: OptionPath) {
const key = loc.name;

if (removed[key]) {
const { message, version = 5 } = removed[key];
const {
message,
version = 5,
}: { message: string, version?: number } = removed[key];

throw new Error(
`Using removed Babel ${version} option: ${msg(loc)} - ${message}`,
Expand Down

0 comments on commit 601c824

Please sign in to comment.