Skip to content

Commit

Permalink
Improve preset-env typings (#14606)
Browse files Browse the repository at this point in the history
* refactor: move shipped-proposals to ts

* preset-env

* address review comments
  • Loading branch information
JLHwung committed Jun 1, 2022
1 parent 735b001 commit 9ae7852
Show file tree
Hide file tree
Showing 16 changed files with 134 additions and 66 deletions.
2 changes: 1 addition & 1 deletion packages/babel-core/src/config/cache-contexts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export type FullPlugin = {
// process 'ignore'/'only' and other filename-based logic.
export type SimpleConfig = {
envName: string;
caller: CallerMetadata | void;
caller: CallerMetadata | undefined;
};
export type SimplePreset = {
targets: Targets;
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-core/src/config/config-chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export type ConfigContext = {
cwd: string;
root: string;
envName: string;
caller: CallerMetadata | void;
caller: CallerMetadata | undefined;
showConfig: boolean;
};

Expand Down
10 changes: 5 additions & 5 deletions packages/babel-core/src/config/files/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function findConfigUpwards(rootDir: string): string | null {
export function* findRelativeConfig(
packageData: FilePackageData,
envName: string,
caller: CallerMetadata | void,
caller: CallerMetadata | undefined,
): Handler<RelativeConfig> {
let config = null;
let ignore = null;
Expand Down Expand Up @@ -93,7 +93,7 @@ export function* findRelativeConfig(
export function findRootConfig(
dirname: string,
envName: string,
caller: CallerMetadata | void,
caller: CallerMetadata | undefined,
): Handler<ConfigFile | null> {
return loadOneConfig(ROOT_CONFIG_FILENAMES, dirname, envName, caller);
}
Expand All @@ -102,7 +102,7 @@ function* loadOneConfig(
names: string[],
dirname: string,
envName: string,
caller: CallerMetadata | void,
caller: CallerMetadata | undefined,
previousConfig: ConfigFile | null = null,
): Handler<ConfigFile | null> {
const configs = yield* gensync.all(
Expand Down Expand Up @@ -133,7 +133,7 @@ export function* loadConfig(
name: string,
dirname: string,
envName: string,
caller: CallerMetadata | void,
caller: CallerMetadata | undefined,
): Handler<ConfigFile> {
const filepath = require.resolve(name, { paths: [dirname] });

Expand Down Expand Up @@ -163,7 +163,7 @@ const readConfigJS = makeStrongCache(function* readConfigJS(
filepath: string,
cache: CacheConfigurator<{
envName: string;
caller: CallerMetadata | void;
caller: CallerMetadata | undefined;
}>,
): Handler<ConfigFile | null> {
if (!nodeFs.existsSync(filepath)) {
Expand Down
6 changes: 3 additions & 3 deletions packages/babel-core/src/config/files/index-browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function* findRelativeConfig(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
envName: string,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
caller: CallerMetadata | void,
caller: CallerMetadata | undefined,
): Handler<RelativeConfig> {
return { config: null, ignore: null };
}
Expand All @@ -47,7 +47,7 @@ export function* findRootConfig(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
envName: string,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
caller: CallerMetadata | void,
caller: CallerMetadata | undefined,
): Handler<ConfigFile | null> {
return null;
}
Expand All @@ -59,7 +59,7 @@ export function* loadConfig(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
envName: string,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
caller: CallerMetadata | void,
caller: CallerMetadata | undefined,
): Handler<ConfigFile> {
throw new Error(`Cannot load ${name} relative to ${dirname} in a browser`);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-core/src/config/helpers/config-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type EnvFunction = {
};

type CallerFactory = (
extractor: (callerMetadata: CallerMetadata | void) => unknown,
extractor: (callerMetadata: CallerMetadata | undefined) => unknown,
) => SimpleType;
type TargetsFunction = () => Targets;
type AssumptionFunction = (name: AssumptionName) => boolean | void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export function assertSourceType(
export function assertCallerMetadata(
loc: OptionPath,
value: unknown,
): CallerMetadata | void {
): CallerMetadata | undefined {
const obj = assertObject(loc, value);
if (obj) {
if (typeof obj.name !== "string") {
Expand Down
44 changes: 41 additions & 3 deletions packages/babel-plugin-transform-parameters/src/rest.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,39 @@
import { template, types as t } from "@babel/core";
import type { NodePath, Visitor } from "@babel/traverse";

type Candidate = {
cause: "indexGetter" | "lengthGetter" | "argSpread";
path: NodePath<t.Identifier | t.JSXIdentifier>;
};

type State = {
references: [];
offset: number;

argumentsNode: t.Identifier;
outerBinding: t.Identifier;

// candidate member expressions we could optimise if there are no other references
candidates: Candidate[];

// local rest binding name
name: string;

/*
It may be possible to optimize the output code in certain ways, such as
not generating code to initialize an array (perhaps substituting direct
references to arguments[i] or arguments.length for reads of the
corresponding rest parameter property) or positioning the initialization
code so that it may not have to execute depending on runtime conditions.
This property tracks eligibility for optimization. "deopted" means give up
and don't perform optimization. For example, when any of rest's elements /
properties is assigned to at the top level, or referenced at all in a
nested function.
*/
deopted: boolean;
noOptimise: boolean;
};

const buildRest = template(`
for (var LEN = ARGUMENTS.length,
Expand All @@ -22,7 +57,10 @@ const restLength = template(`
ARGUMENTS.length <= OFFSET ? 0 : ARGUMENTS.length - OFFSET
`);

function referencesRest(path, state) {
function referencesRest(
path: NodePath<t.Identifier | t.JSXIdentifier>,
state: State,
) {
if (path.node.name === state.name) {
// Check rest parameter is not shadowed by a binding in another scope.
return path.scope.bindingIdentifierEquals(state.name, state.outerBinding);
Expand All @@ -31,15 +69,15 @@ function referencesRest(path, state) {
return false;
}

const memberExpressionOptimisationVisitor = {
const memberExpressionOptimisationVisitor: Visitor<State> = {
Scope(path, state) {
// check if this scope has a local binding that will shadow the rest parameter
if (!path.scope.bindingIdentifierEquals(state.name, state.outerBinding)) {
path.skip();
}
},

Flow(path) {
Flow(path: NodePath<t.Flow>) {
// Do not skip TypeCastExpressions as the contain valid non flow code
if (path.isTypeCastExpression()) return;
// don't touch reference in type annotations
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-plugin-transform-runtime/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const pluginRegenerator = (_pluginRegenerator.default ||

const pluginsCompat = "#__secret_key__@babel/runtime__compatibility";

function supportsStaticESM(caller: CallerMetadata | void) {
function supportsStaticESM(caller: CallerMetadata | undefined) {
// @ts-ignore TS does not narrow down optional chaining
return !!caller?.supportsStaticESM;
}
Expand Down
36 changes: 1 addition & 35 deletions packages/babel-preset-env/data/shipped-proposals.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,2 @@
/* eslint sort-keys: "error" */
// These mappings represent the transform plugins that have been
// shipped by browsers, and are enabled by the `shippedProposals` option.

const proposalPlugins = new Set();

// proposal syntax plugins enabled by the `shippedProposals` option.
// Unlike proposalPlugins above, they are independent of compiler targets.
const proposalSyntaxPlugins = [
"syntax-import-assertions"
]

// use intermediary object to enforce alphabetical key order
const pluginSyntaxObject = {
"proposal-async-generator-functions": "syntax-async-generators",
"proposal-class-properties": "syntax-class-properties",
"proposal-class-static-block": "syntax-class-static-block",
"proposal-json-strings": "syntax-json-strings",
"proposal-nullish-coalescing-operator": "syntax-nullish-coalescing-operator",
"proposal-numeric-separator": "syntax-numeric-separator",
"proposal-object-rest-spread": "syntax-object-rest-spread",
"proposal-optional-catch-binding": "syntax-optional-catch-binding",
"proposal-optional-chaining": "syntax-optional-chaining",
// note: we don't have syntax-private-methods
"proposal-private-methods": "syntax-class-properties",
"proposal-private-property-in-object": "syntax-private-property-in-object",
"proposal-unicode-property-regex": null,
};

const pluginSyntaxEntries = Object.keys(pluginSyntaxObject).map(function (key) {
return [key, pluginSyntaxObject[key]];
});

const pluginSyntaxMap = new Map(pluginSyntaxEntries);

const { pluginSyntaxMap, proposalPlugins, proposalSyntaxPlugins } = require("../lib/shipped-proposals");
module.exports = { pluginSyntaxMap, proposalPlugins, proposalSyntaxPlugins };
1 change: 1 addition & 0 deletions packages/babel-preset-env/src/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const logPlugin = (
if (!first) formattedTargets += `,`;
first = false;
formattedTargets += ` ${target}`;
// @ts-ignore
if (support[target]) formattedTargets += ` < ${support[target]}`;
}
formattedTargets += ` }`;
Expand Down
11 changes: 9 additions & 2 deletions packages/babel-preset-env/src/filter-items.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const has = Function.call.bind(Object.hasOwnProperty);

export function addProposalSyntaxPlugins(
items: Set<string>,
proposalSyntaxPlugins: string[],
proposalSyntaxPlugins: readonly string[],
) {
proposalSyntaxPlugins.forEach(plugin => {
items.add(plugin);
Expand All @@ -25,7 +25,14 @@ export function removeUnsupportedItems(
babelVersion: string,
) {
items.forEach(item => {
if (has(minVersions, item) && lt(babelVersion, minVersions[item])) {
if (
has(minVersions, item) &&
lt(
babelVersion,
// @ts-ignore we have checked minVersions[item] in has call
minVersions[item],
)
) {
items.delete(item);
}
});
Expand Down
29 changes: 19 additions & 10 deletions packages/babel-preset-env/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
pluginSyntaxMap,
proposalPlugins,
proposalSyntaxPlugins,
} from "../data/shipped-proposals";
} from "./shipped-proposals";
import {
plugins as pluginsList,
pluginsBugfixes as pluginsBugfixesList,
Expand All @@ -23,6 +23,8 @@ import overlappingPlugins from "@babel/compat-data/overlapping-plugins";
import removeRegeneratorEntryPlugin from "./polyfills/regenerator";
import legacyBabelPolyfillPlugin from "./polyfills/babel-polyfill";

import type { CallerMetadata } from "@babel/core";

import _pluginCoreJS2 from "babel-plugin-polyfill-corejs2";
import _pluginCoreJS3 from "babel-plugin-polyfill-corejs3";
import _pluginRegenerator from "babel-plugin-polyfill-regenerator";
Expand Down Expand Up @@ -56,6 +58,7 @@ function filterStageFromList(
) {
return Object.keys(list).reduce((result, item) => {
if (!stageList.has(item)) {
// @ts-ignore
result[item] = list[item];
}

Expand Down Expand Up @@ -88,7 +91,9 @@ function getPluginList(proposals: boolean, bugfixes: boolean) {
}

const getPlugin = (pluginName: string) => {
const plugin = availablePlugins[pluginName]();
const plugin =
// @ts-ignore plugin name is constructed from available plugin list
availablePlugins[pluginName]();

if (!plugin) {
throw new Error(
Expand Down Expand Up @@ -244,10 +249,10 @@ export const getPolyfillPlugins = ({
};

function getLocalTargets(
optionsTargets,
ignoreBrowserslistConfig,
configPath,
browserslistEnv,
optionsTargets: Options["targets"],
ignoreBrowserslistConfig: boolean,
configPath: string,
browserslistEnv: string,
) {
if (optionsTargets?.esmodules && optionsTargets.browsers) {
console.warn(`
Expand All @@ -263,19 +268,23 @@ function getLocalTargets(
});
}

function supportsStaticESM(caller) {
function supportsStaticESM(caller: CallerMetadata | undefined) {
// @ts-expect-error supportsStaticESM is not defined in CallerMetadata
return !!caller?.supportsStaticESM;
}

function supportsDynamicImport(caller) {
function supportsDynamicImport(caller: CallerMetadata | undefined) {
// @ts-expect-error supportsDynamicImport is not defined in CallerMetadata
return !!caller?.supportsDynamicImport;
}

function supportsExportNamespaceFrom(caller) {
function supportsExportNamespaceFrom(caller: CallerMetadata | undefined) {
// @ts-expect-error supportsExportNamespaceFrom is not defined in CallerMetadata
return !!caller?.supportsExportNamespaceFrom;
}

function supportsTopLevelAwait(caller) {
function supportsTopLevelAwait(caller: CallerMetadata | undefined) {
// @ts-expect-error supportsTopLevelAwait is not defined in CallerMetadata
return !!caller?.supportsTopLevelAwait;
}

Expand Down
8 changes: 6 additions & 2 deletions packages/babel-preset-env/src/normalize-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ export const checkDuplicateIncludeExcludes = (
);
};

const normalizeTargets = (targets): Options["targets"] => {
const normalizeTargets = (
targets: string | string[] | Options["targets"],
): Options["targets"] => {
// TODO: Allow to use only query or strings as a targets from next breaking change.
if (typeof targets === "string" || Array.isArray(targets)) {
return { browsers: targets };
Expand All @@ -125,6 +127,7 @@ export const validateModulesOption = (
modulesOpt: ModuleOption = ModulesOption.auto,
) => {
v.invariant(
// @ts-ignore we have provided fallback for undefined keys
ModulesOption[modulesOpt.toString()] || modulesOpt === ModulesOption.false,
`The 'modules' option must be one of \n` +
` - 'false' to indicate no module processing\n` +
Expand All @@ -140,6 +143,7 @@ export const validateUseBuiltInsOption = (
builtInsOpt: BuiltInsOption = false,
) => {
v.invariant(
// @ts-ignore we have provided fallback for undefined keys
UseBuiltInsOption[builtInsOpt.toString()] ||
builtInsOpt === UseBuiltInsOption.false,
`The 'useBuiltIns' option must be either
Expand Down Expand Up @@ -261,7 +265,7 @@ export default function normalizeOptions(opts: Options) {
spec: v.validateBooleanOption(TopLevelOptions.spec, opts.spec, false),
targets: normalizeTargets(opts.targets),
useBuiltIns: useBuiltIns,
browserslistEnv: v.validateStringOption(
browserslistEnv: v.validateStringOption<string>(
TopLevelOptions.browserslistEnv,
opts.browserslistEnv,
),
Expand Down
2 changes: 2 additions & 0 deletions packages/babel-preset-env/src/plugins-compat-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ const bugfixPluginsFiltered = {};

for (const plugin of Object.keys(plugins)) {
if (Object.hasOwnProperty.call(availablePlugins, plugin)) {
// @ts-ignore
pluginsFiltered[plugin] = plugins[plugin];
}
}

for (const plugin of Object.keys(bugfixPlugins)) {
if (Object.hasOwnProperty.call(availablePlugins, plugin)) {
// @ts-ignore
bugfixPluginsFiltered[plugin] = bugfixPlugins[plugin];
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-preset-env/src/polyfills/regenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { getImportSource, getRequireSource } from "./utils";
import type { Visitor } from "@babel/traverse";
import type { PluginObject, PluginPass } from "@babel/core";

function isRegeneratorSource(source) {
function isRegeneratorSource(source: string) {
return (
source === "regenerator-runtime/runtime" ||
source === "regenerator-runtime/runtime.js"
Expand Down

0 comments on commit 9ae7852

Please sign in to comment.