diff --git a/package.json b/package.json index 24f8db36b6..2469771966 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "eslint-plugin-jest": "^23.8.2", "eslint-plugin-prettier": "^3.1.2", "fancy-log": "^1.3.3", - "flow-bin": "^0.108.0", + "flow-bin": "^0.123.0", "gulp": "^4.0.2", "gulp-babel": "^8.0.0", "gulp-filter": "^5.1.0", diff --git a/packages/babel-core/src/config/config-descriptors.js b/packages/babel-core/src/config/config-descriptors.js index fa60d47d71..c203dbc74c 100644 --- a/packages/babel-core/src/config/config-descriptors.js +++ b/packages/babel-core/src/config/config-descriptors.js @@ -268,7 +268,6 @@ export function createDescriptor( let value = pair; if (Array.isArray(value)) { if (value.length === 3) { - // $FlowIgnore - Flow doesn't like the multiple tuple types. [value, options, name] = value; } else { [value, options] = value; diff --git a/packages/babel-core/src/config/helpers/config-api.js b/packages/babel-core/src/config/helpers/config-api.js index a93756ae9f..f49e038f76 100644 --- a/packages/babel-core/src/config/helpers/config-api.js +++ b/packages/babel-core/src/config/helpers/config-api.js @@ -17,13 +17,14 @@ type EnvFunction = { (Array): boolean, }; -export type PluginAPI = { +export type PluginAPI = {| version: string, cache: SimpleCacheConfigurator, env: EnvFunction, async: () => boolean, assertVersion: typeof assertVersion, -}; + caller?: any, +|}; export default function makeAPI( cache: CacheConfigurator<{ envName: string, caller: CallerMetadata | void }>, @@ -55,7 +56,6 @@ export default function makeAPI( async: () => false, caller, assertVersion, - tokTypes: undefined, }; } diff --git a/packages/babel-helper-compilation-targets/src/index.js b/packages/babel-helper-compilation-targets/src/index.js index 1eca5be3ef..a53e927e9a 100644 --- a/packages/babel-helper-compilation-targets/src/index.js +++ b/packages/babel-helper-compilation-targets/src/index.js @@ -13,9 +13,9 @@ import { } from "./utils"; import { browserNameMap } from "./targets"; import { TargetNames } from "./options"; -import type { Targets } from "./types"; +import type { Target, Targets, InputTargets, Browsers } from "./types"; -export type { Targets }; +export type { Targets, InputTargets }; export { prettifyTargets } from "./pretty"; export { getInclusionReasons } from "./debug"; @@ -39,7 +39,7 @@ function objectToBrowserslist(object: Targets): Array { }, []); } -function validateTargetNames(targets: Targets): void { +function validateTargetNames(targets: InputTargets): Targets { const validTargets = Object.keys(TargetNames); for (const target in targets) { if (!TargetNames[target]) { @@ -49,32 +49,24 @@ function validateTargetNames(targets: Targets): void { ); } } + + // $FlowIgnore + return targets; } -export function isBrowsersQueryValid( - browsers: string | Array | Targets, -): boolean { +export function isBrowsersQueryValid(browsers: Browsers | Targets): boolean { return typeof browsers === "string" || Array.isArray(browsers); } -function validateBrowsers(browsers) { +function validateBrowsers(browsers: Browsers | void) { invariant( typeof browsers === "undefined" || isBrowsersQueryValid(browsers), - `Invalid Option: '${browsers}' is not a valid browserslist query`, + `Invalid Option: '${String(browsers)}' is not a valid browserslist query`, ); return browsers; } -function mergeBrowsers(fromQuery: Targets, fromTarget: Targets) { - return Object.keys(fromTarget).reduce((queryObj, targKey) => { - if (targKey !== TargetNames.browsers) { - queryObj[targKey] = fromTarget[targKey]; - } - return queryObj; - }, fromQuery); -} - function getLowestVersions(browsers: Array): Targets { return browsers.reduce((all: Object, browser: string): Object => { const [browserName, browserVersion] = browser.split(" "); @@ -170,30 +162,31 @@ type ParsedResult = { }; export default function getTargets( - targets: Object = {}, + inputTargets: InputTargets = {}, options: Object = {}, ): Targets { const targetOpts: Targets = {}; - validateTargetNames(targets); - // `esmodules` as a target indicates the specific set of browsers supporting ES Modules. // These values OVERRIDE the `browsers` field. - if (targets.esmodules) { + if (inputTargets.esmodules) { const supportsESModules = browserModulesData["es6.module"]; - targets.browsers = Object.keys(supportsESModules) + inputTargets.browsers = Object.keys(supportsESModules) .map(browser => `${browser} ${supportsESModules[browser]}`) .join(", "); } // Remove esmodules after being consumed to fix `hasTargets` below - delete targets.esmodules; + delete inputTargets.esmodules; // Parse browsers target via browserslist - const browsersquery = validateBrowsers(targets.browsers); + const browsersquery = validateBrowsers(inputTargets.browsers); + delete inputTargets.browsers; - const hasTargets = Object.keys(targets).length > 0; - const shouldParseBrowsers = !!targets.browsers; + let targets: Targets = validateTargetNames(inputTargets); + + const shouldParseBrowsers = !!browsersquery; + const hasTargets = shouldParseBrowsers || Object.keys(targets).length > 0; const shouldSearchForConfig = !options.ignoreBrowserslistConfig && !hasTargets; @@ -215,43 +208,39 @@ export default function getTargets( }); const queryBrowsers = getLowestVersions(browsers); - targets = mergeBrowsers(queryBrowsers, targets); + targets = Object.assign(queryBrowsers, targets); // Reset browserslist defaults browserslist.defaults = browserslistDefaults; } // Parse remaining targets - const parsed = Object.keys(targets) - .filter(value => value !== TargetNames.esmodules) - .sort() - .reduce( - (results: ParsedResult, target: string): ParsedResult => { - if (target !== TargetNames.browsers) { - const value = targets[target]; + const parsed = (Object.keys(targets): Array).sort().reduce( + (results: ParsedResult, target: $Keys): ParsedResult => { + const value = targets[target]; - // Warn when specifying minor/patch as a decimal - if (typeof value === "number" && value % 1 !== 0) { - results.decimalWarnings.push({ target, value }); - } + // Warn when specifying minor/patch as a decimal + if (typeof value === "number" && value % 1 !== 0) { + results.decimalWarnings.push({ target, value }); + } - // Check if we have a target parser? - const parser = targetParserMap[target] || targetParserMap.__default; - const [parsedTarget, parsedValue] = parser(target, value); + // Check if we have a target parser? + // $FlowIgnore - Flow doesn't like that some targetParserMap[target] might be missing + const parser = targetParserMap[target] ?? targetParserMap.__default; + const [parsedTarget, parsedValue] = parser(target, value); - if (parsedValue) { - // Merge (lowest wins) - results.targets[parsedTarget] = parsedValue; - } - } + if (parsedValue) { + // Merge (lowest wins) + results.targets[parsedTarget] = parsedValue; + } - return results; - }, - { - targets: targetOpts, - decimalWarnings: [], - }, - ); + return results; + }, + { + targets: targetOpts, + decimalWarnings: [], + }, + ); outputDecimalWarning(parsed.decimalWarnings); diff --git a/packages/babel-helper-compilation-targets/src/options.js b/packages/babel-helper-compilation-targets/src/options.js index eadc8dbd43..0c30e6113d 100644 --- a/packages/babel-helper-compilation-targets/src/options.js +++ b/packages/babel-helper-compilation-targets/src/options.js @@ -1,9 +1,7 @@ // @flow export const TargetNames = { - esmodules: "esmodules", node: "node", - browsers: "browsers", chrome: "chrome", opera: "opera", edge: "edge", @@ -14,7 +12,4 @@ export const TargetNames = { android: "android", electron: "electron", samsung: "samsung", - - // deprecated - uglify: "uglify", }; diff --git a/packages/babel-helper-compilation-targets/src/types.js b/packages/babel-helper-compilation-targets/src/types.js index 28b4c2b3f3..8d488052d6 100644 --- a/packages/babel-helper-compilation-targets/src/types.js +++ b/packages/babel-helper-compilation-targets/src/types.js @@ -17,3 +17,12 @@ export type Target = export type Targets = { [target: Target]: string, }; + +export type Browsers = string | Array; + +export type InputTargets = { + ...Targets, + + browsers?: Browsers, + esmodules?: boolean, +}; diff --git a/packages/babel-parser/src/plugins/estree.js b/packages/babel-parser/src/plugins/estree.js index 1f04b03e30..52010bbdd8 100644 --- a/packages/babel-parser/src/plugins/estree.js +++ b/packages/babel-parser/src/plugins/estree.js @@ -208,6 +208,7 @@ export default (superClass: Class): Class => this.directiveToStmt(d), ); node.body = directiveStatements.concat(node.body); + // $FlowIgnore - directives isn't optional in the type definition delete node.directives; } @@ -389,7 +390,9 @@ export default (superClass: Class): Class => if (node.callee.type === "Import") { ((node: N.Node): N.EstreeImportExpression).type = "ImportExpression"; ((node: N.Node): N.EstreeImportExpression).source = node.arguments[0]; + // $FlowIgnore - arguments isn't optional in the type definition delete node.arguments; + // $FlowIgnore - callee isn't optional in the type definition delete node.callee; } diff --git a/packages/babel-parser/src/tokenizer/index.js b/packages/babel-parser/src/tokenizer/index.js index 96ff0c2129..73c42eb118 100644 --- a/packages/babel-parser/src/tokenizer/index.js +++ b/packages/babel-parser/src/tokenizer/index.js @@ -1,5 +1,7 @@ // @flow +/*:: declare var invariant; */ + import type { Options } from "../options"; import * as N from "../types"; import type { Position } from "../util/location"; @@ -1360,10 +1362,14 @@ export default class Tokenizer extends LocationParser { default: if (ch >= charCodes.digit0 && ch <= charCodes.digit7) { const codePos = this.state.pos - 1; - // $FlowFixMe - let octalStr = this.input + const match = this.input .substr(this.state.pos - 1, 3) - .match(/^[0-7]+/)[0]; + .match(/^[0-7]+/); + + // This is never null, because of the if condition above. + /*:: invariant(match !== null) */ + let octalStr = match[0]; + let octal = parseInt(octalStr, 8); if (octal > 255) { octalStr = octalStr.slice(0, -1); diff --git a/packages/babel-preset-env/src/filter-items.js b/packages/babel-preset-env/src/filter-items.js index a0041b3f08..dacc2b25da 100644 --- a/packages/babel-preset-env/src/filter-items.js +++ b/packages/babel-preset-env/src/filter-items.js @@ -5,7 +5,6 @@ export function removeUnnecessaryItems( overlapping: { [name: string]: string[] }, ) { items.forEach(item => { - // $FlowIgnore Flow doesn't support calls in optional chains overlapping[item]?.forEach(name => items.delete(name)); }); } diff --git a/packages/babel-preset-env/src/index.js b/packages/babel-preset-env/src/index.js index 4aea6ea731..fe17cc9501 100644 --- a/packages/babel-preset-env/src/index.js +++ b/packages/babel-preset-env/src/index.js @@ -25,6 +25,7 @@ import getTargets, { filterItems, isRequired, type Targets, + type InputTargets, } from "@babel/helper-compilation-targets"; import availablePlugins from "./available-plugins"; import { filterStageFromList } from "./utils"; @@ -247,15 +248,17 @@ export default declare((api, opts) => { "@babel/preset-env: esmodules and browsers targets have been specified together.", ); console.log( + // $FlowIgnore `\`browsers\` target, \`${optionsTargets.browsers}\` will be ignored.`, ); console.log(""); } - const targets = getTargets(optionsTargets, { - ignoreBrowserslistConfig, - configPath, - }); + const targets = getTargets( + // $FlowIgnore optionsTargets doesn't have an "uglify" property anymore + (optionsTargets: InputTargets), + { ignoreBrowserslistConfig, configPath }, + ); const include = transformIncludesAndExcludes(optionsInclude); const exclude = transformIncludesAndExcludes(optionsExclude); diff --git a/packages/babel-preset-env/src/normalize-options.js b/packages/babel-preset-env/src/normalize-options.js index 1095880a3e..04e4d823ba 100644 --- a/packages/babel-preset-env/src/normalize-options.js +++ b/packages/babel-preset-env/src/normalize-options.js @@ -123,9 +123,7 @@ const normalizeTargets = targets => { if (typeof targets === "string" || Array.isArray(targets)) { return { browsers: targets }; } - return { - ...targets, - }; + return { ...targets }; }; export const validateConfigPathOption = ( diff --git a/packages/babel-preset-env/src/types.js b/packages/babel-preset-env/src/types.js index 4e81d5eef0..bcf25119e7 100644 --- a/packages/babel-preset-env/src/types.js +++ b/packages/babel-preset-env/src/types.js @@ -2,7 +2,7 @@ import { ModulesOption, UseBuiltInsOption } from "./options"; import type { NormalizedCorejsOption } from "./normalize-options"; -import type { Targets } from "@babel/helper-compilation-targets"; +import type { Targets, InputTargets } from "@babel/helper-compilation-targets"; // Options // Use explicit modules to prevent typo errors. @@ -32,7 +32,7 @@ export type Options = { modules: ModuleOption, shippedProposals: boolean, spec: boolean, - targets: Targets, + targets: { ...InputTargets, uglify?: boolean }, useBuiltIns: BuiltInsOption, }; diff --git a/packages/babel-types/src/modifications/removeProperties.js b/packages/babel-types/src/modifications/removeProperties.js index e0f2af6c1a..eb27fd7cbb 100644 --- a/packages/babel-types/src/modifications/removeProperties.js +++ b/packages/babel-types/src/modifications/removeProperties.js @@ -24,7 +24,7 @@ export default function removeProperties( if (key[0] === "_" && node[key] != null) node[key] = undefined; } - const symbols: Array = Object.getOwnPropertySymbols(node); + const symbols: Array = Object.getOwnPropertySymbols(node); for (const sym of symbols) { node[sym] = null; } diff --git a/yarn.lock b/yarn.lock index 55abcd7e0e..0cbc419aa1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4784,10 +4784,10 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== -flow-bin@^0.108.0: - version "0.108.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.108.0.tgz#6a42c85fd664d23dd937d925851e8e6ab5d71393" - integrity sha512-hPEyCP1J8rdhNDfCAA5w7bN6HUNBDcHVg/ABU5JVo0gUFMx+uRewpyEH8LlLBGjVQuIpbaPpaqpoaQhAVyaYww== +flow-bin@^0.123.0: + version "0.123.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.123.0.tgz#7ba61a0b8775928cf4943ccf78eed2b1b05f7b3a" + integrity sha512-Ylcf8YDIM/KrqtxkPuq+f8O+6sdYA2Nuz5f+sWHlp539DatZz3YMcsO1EiXaf1C11HJgpT/3YGYe7xZ9/UZmvQ== flush-write-stream@^1.0.0, flush-write-stream@^1.0.2: version "1.1.1"