diff --git a/packages/babel-core/src/config/full.ts b/packages/babel-core/src/config/full.ts index b56872791a9f..76ad6ebef63f 100644 --- a/packages/babel-core/src/config/full.ts +++ b/packages/babel-core/src/config/full.ts @@ -56,6 +56,88 @@ export type { Plugin }; export type PluginPassList = Array; export type PluginPasses = Array; +function sortPlugins(plugins: Plugin[]) { + function stableSort(plugins: Plugin[], orderMap: Map) { + const buckets = Object.create(null); + + // By collecting into buckets, we can guarantee a stable sort. + for (let i = 0; i < plugins.length; i++) { + const n = plugins[i]; + const p = 1000 - orderMap.get(n.key); + + // In case some plugin is setting an unexpected priority. + const bucket = buckets[p] || (buckets[p] = []); + bucket.push(n); + } + + // Sort our keys in descending order. Keys are unique, so we don't have to + // worry about stability. + const keys = Object.keys(buckets) + .map(k => +k) + .sort((a, b) => b - a); + + let index = 0; + for (const key of keys) { + const bucket = buckets[key]; + for (const n of bucket) { + plugins[index++] = n; + } + } + return plugins; + } + + const orderDataListMap: Map< + string, + { + version: number; + data: () => string[]; + plugins: Plugin[]; + } + > = new Map(); + + const pluginsWithPadding: (Plugin | string)[] = []; + + for (let i = plugins.length - 1; i >= 0; i--) { + const plugin = plugins[i]; + const { orderData } = plugin; + if (orderData) { + let orderData2 = orderDataListMap.get(orderData.id); + if ((orderData2?.version || 0) < orderData.version) { + if (orderData2 == null) { + pluginsWithPadding.unshift(orderData.id); + } + orderDataListMap.set( + orderData.id, + (orderData2 = { + version: orderData.version, + data: () => orderData.data(), + plugins: [], + }), + ); + } + orderData2.plugins.unshift(plugin); + } else { + pluginsWithPadding.unshift(plugin); + } + } + + const newPlugins: Plugin[] = []; + + for (const value of pluginsWithPadding) { + if (typeof value === "string") { + const orderData = orderDataListMap.get(value); + const map = new Map( + orderData.data().map((key, i) => [key, i]), + ); + newPlugins.push(...stableSort(orderData.plugins, map)); + } else { + newPlugins.push(value); + } + } + + return newPlugins; +} + export default gensync(function* loadFullConfig( inputOpts: unknown, ): Handler { @@ -168,7 +250,7 @@ export default gensync(function* loadFullConfig( if (ignored) return null; - const opts: any = optionDefaults; + const opts: ValidatedOptions = optionDefaults; mergeOptions(opts, options); const pluginContext: Context.FullPlugin = { @@ -211,6 +293,10 @@ export default gensync(function* loadFullConfig( .map(plugins => ({ plugins })); opts.passPerPreset = opts.presets.length > 0; + if (opts.sortPlugins && !opts.passPerPreset) { + opts.plugins = passes[0] = sortPlugins(opts.plugins as Plugin[]); + } + return { options: opts, passes: passes, diff --git a/packages/babel-core/src/config/partial.ts b/packages/babel-core/src/config/partial.ts index 68a541ea38ec..5eed58be517c 100644 --- a/packages/babel-core/src/config/partial.ts +++ b/packages/babel-core/src/config/partial.ts @@ -112,6 +112,9 @@ export default function* loadPrivatePartialConfig( const merged: ValidatedOptions = { assumptions: {}, }; + + if (process.env.BABEL_8_BREAKING) merged.sortPlugins = true; + configChain.options.forEach(opts => { mergeOptions(merged as any, opts); }); diff --git a/packages/babel-core/src/config/plugin.ts b/packages/babel-core/src/config/plugin.ts index 8ee23fc31226..bb24fa0dd84e 100644 --- a/packages/babel-core/src/config/plugin.ts +++ b/packages/babel-core/src/config/plugin.ts @@ -16,6 +16,8 @@ export default class Plugin { externalDependencies: ReadonlyDeepArray; + orderData?: PluginObject["orderData"]; + constructor( plugin: PluginObject, options: {}, @@ -30,6 +32,7 @@ export default class Plugin { this.visitor = plugin.visitor || {}; this.parserOverride = plugin.parserOverride; this.generatorOverride = plugin.generatorOverride; + this.orderData = plugin.orderData; this.options = options; this.externalDependencies = externalDependencies; diff --git a/packages/babel-core/src/config/validation/option-assertions.ts b/packages/babel-core/src/config/validation/option-assertions.ts index 9b47cbd98597..69cf254c7f01 100644 --- a/packages/babel-core/src/config/validation/option-assertions.ts +++ b/packages/babel-core/src/config/validation/option-assertions.ts @@ -219,7 +219,7 @@ export function assertBoolean( export function assertObject( loc: GeneralPath, value: unknown, -): { readonly [key: string]: unknown } | void { +): { readonly [key: string]: unknown } | undefined { if ( value !== undefined && (typeof value !== "object" || Array.isArray(value) || !value) diff --git a/packages/babel-core/src/config/validation/options.ts b/packages/babel-core/src/config/validation/options.ts index 3c554e06a6ca..bc9bdf24fda8 100644 --- a/packages/babel-core/src/config/validation/options.ts +++ b/packages/babel-core/src/config/validation/options.ts @@ -56,6 +56,8 @@ const ROOT_VALIDATORS: ValidatorSet = { cloneInputAst: assertBoolean as Validator, envName: assertString as Validator, + + sortPlugins: assertBoolean as Validator, }; const BABELRC_VALIDATORS: ValidatorSet = { @@ -192,6 +194,7 @@ export type ValidatedOptions = { parserOpts?: ParserOptions; // Deprecate top level generatorOpts generatorOpts?: GeneratorOptions; + sortPlugins?: boolean; }; export type NormalizedOptions = { diff --git a/packages/babel-core/src/config/validation/plugins.ts b/packages/babel-core/src/config/validation/plugins.ts index 08184364c20f..041eeb668215 100644 --- a/packages/babel-core/src/config/validation/plugins.ts +++ b/packages/babel-core/src/config/validation/plugins.ts @@ -33,8 +33,27 @@ const VALIDATORS: ValidatorSet = { generatorOverride: assertFunction as Validator< PluginObject["generatorOverride"] >, + + orderData: assertOrderData as Validator, }; +function assertOrderData(loc: OptionPath, value: unknown) { + const obj = assertObject(loc, value); + if (obj) { + if (typeof obj.id !== "string") { + throw new Error( + `${msg(loc)} must have an "id" property that is a string`, + ); + } + if (typeof obj.version !== "number") { + throw new Error( + `${msg(loc)} must have a "version" property that is a number`, + ); + } + } + return value as PluginObject["orderData"]; +} + function assertVisitorMap(loc: OptionPath, value: unknown): Visitor { const obj = assertObject(loc, value); if (obj) { @@ -95,6 +114,13 @@ export type PluginObject = { visitor?: Visitor; parserOverride?: Function; generatorOverride?: Function; + orderData?: { + id: string; + version: number; + } & { + type: "list"; + data: () => string[]; + }; }; export function validatePluginObject(obj: { diff --git a/packages/babel-core/src/transformation/index.ts b/packages/babel-core/src/transformation/index.ts index 6da480314311..d5f7dcbefe38 100644 --- a/packages/babel-core/src/transformation/index.ts +++ b/packages/babel-core/src/transformation/index.ts @@ -15,6 +15,7 @@ import generateCode from "./file/generate.ts"; import type File from "./file/file.ts"; import { flattenToSet } from "../config/helpers/deep-array.ts"; +import { isThenable } from "../gensync-utils/async.ts"; export type FileResultCallback = { (err: Error, file: null): void; @@ -145,12 +146,3 @@ function* transformFile(file: File, pluginPasses: PluginPasses): Handler { } } } - -function isThenable>(val: any): val is T { - return ( - !!val && - (typeof val === "object" || typeof val === "function") && - !!val.then && - typeof val.then === "function" - ); -} diff --git a/packages/babel-core/test/api.js b/packages/babel-core/test/api.js index 6aceceea0b62..55945ddba094 100644 --- a/packages/babel-core/test/api.js +++ b/packages/babel-core/test/api.js @@ -366,9 +366,11 @@ describe("api", function () { plugins: ["@babel/plugin-syntax-jsx"], }); - expect(result.options.plugins[0].manipulateOptions.toString()).toEqual( - expect.stringContaining("jsx"), - ); + expect( + result.options.plugins + .find(v => v.key === "syntax-jsx") + .manipulateOptions.toString(), + ).toEqual(expect.stringContaining("jsx")); }); it("option wrapPluginVisitorMethod", function () { diff --git a/packages/babel-core/test/config-chain.js b/packages/babel-core/test/config-chain.js index 770e732c83c7..8103a6146cb5 100644 --- a/packages/babel-core/test/config-chain.js +++ b/packages/babel-core/test/config-chain.js @@ -4,6 +4,7 @@ import path from "path"; import { fileURLToPath } from "url"; import * as babel from "../lib/index.js"; import rimraf from "rimraf"; +import { IS_BABEL_8 } from "$repo-utils"; import _getTargets from "@babel/helper-compilation-targets"; const getTargets = _getTargets.default || _getTargets; @@ -1128,6 +1129,7 @@ describe("buildConfigChain", function () { cloneInputAst: true, targets: defaultTargets, assumptions: {}, + ...(IS_BABEL_8() ? { sortPlugins: true } : {}), }); const realEnv = process.env.NODE_ENV; const realBabelEnv = process.env.BABEL_ENV; diff --git a/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/typescript-declare-class-property-babel-7/input.ts b/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/typescript-declare-class-property-babel-7/input.ts new file mode 100644 index 000000000000..4aec71c8add3 --- /dev/null +++ b/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/typescript-declare-class-property-babel-7/input.ts @@ -0,0 +1,3 @@ +declare class Foo { + static bar: string; +} diff --git a/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/typescript-declare-class-property-babel-7/options.json b/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/typescript-declare-class-property-babel-7/options.json new file mode 100644 index 000000000000..adf0406b4cb9 --- /dev/null +++ b/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/typescript-declare-class-property-babel-7/options.json @@ -0,0 +1,6 @@ +{ + "presets": ["typescript"], + "plugins": ["transform-class-properties"], + "throws": "TypeScript 'declare' fields must first be transformed by @babel/plugin-transform-typescript.", + "BABEL_8_BREAKING": false +} diff --git a/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/typescript-declare-class-property/options.json b/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/typescript-declare-class-property/options.json index 1b72952138ac..8a963360b433 100644 --- a/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/typescript-declare-class-property/options.json +++ b/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/typescript-declare-class-property/options.json @@ -1,5 +1,7 @@ { "presets": ["typescript"], "plugins": ["transform-class-properties"], - "throws": "TypeScript 'declare' fields must first be transformed by @babel/plugin-transform-typescript." + "throws": "TypeScript 'declare' fields must first be transformed by @babel/plugin-transform-typescript.", + "sortPlugins": false, + "BABEL_8_BREAKING": true } diff --git a/packages/babel-helper-plugin-utils/src/index.ts b/packages/babel-helper-plugin-utils/src/index.ts index 8dd3e762b066..5006f6d12265 100644 --- a/packages/babel-helper-plugin-utils/src/index.ts +++ b/packages/babel-helper-plugin-utils/src/index.ts @@ -58,8 +58,108 @@ export function declare( clonedApi[name] = apiPolyfills[name](clonedApi); } - // @ts-expect-error options || {} may not be assigned to Options - return builder(clonedApi ?? api, options || {}, dirname); + const pluginObject = builder( + clonedApi ?? api, + options || ({} as Option), + dirname, + ); + + const orderList = [ + "transform-modules-commonjs", + "transform-modules-amd", + "transform-modules-systemjs", + "transform-modules-umd", + + "transform-typescript", + "transform-flow", + + "proposal-async-do-expressions", + "proposal-decorators", + "proposal-destructuring-private", + "proposal-do-expressions", + "proposal-duplicate-named-capturing-groups-regex", + "proposal-explicit-resource-management", + "proposal-export-default-from", + "proposal-function-bind", + "proposal-function-sent", + "proposal-import-attributes-to-assertions", + "proposal-import-defer", + "proposal-import-wasm-source", + "proposal-json-modules", + "proposal-optional-chaining-assign", + "proposal-partial-application", + "proposal-pipeline-operator", + "proposal-record-and-tuple", + "proposal-regexp-modifiers", + "proposal-throw-expressions", + + "transform-unicode-sets-regex", + "bugfix/transform-v8-static-class-fields-redefine-readonly", + "bugfix/transform-firefox-class-in-computed-class-key", + "transform-class-static-block", + "transform-private-property-in-object", + "transform-class-properties", + "transform-private-methods", + "transform-numeric-separator", + "transform-logical-assignment-operators", + "transform-nullish-coalescing-operator", + "transform-optional-chaining", + "transform-json-strings", + "transform-optional-catch-binding", + "transform-parameters", + "transform-async-generator-functions", + "transform-object-rest-spread", + "transform-dotall-regex", + "transform-unicode-property-regex", + "transform-named-capturing-groups-regex", + "transform-async-to-generator", + "transform-exponentiation-operator", + "transform-template-literals", + "transform-literals", + "transform-function-name", + "transform-arrow-functions", + "transform-block-scoped-functions", + "transform-classes", + "transform-object-super", + "transform-shorthand-properties", + "transform-duplicate-keys", + "transform-computed-properties", + "transform-for-of", + "transform-sticky-regex", + "transform-unicode-escapes", + "transform-unicode-regex", + "transform-spread", + "transform-destructuring", + "transform-block-scoping", + "transform-typeof-symbol", + "transform-new-target", + "transform-regenerator", + "transform-member-expression-literals", + "transform-property-literals", + "transform-reserved-words", + "transform-export-namespace-from", + "bugfix/transform-async-arrows-in-class", + "bugfix/transform-edge-default-parameters", + "bugfix/transform-edge-function-name", + "bugfix/transform-safari-block-shadowing", + "bugfix/transform-safari-for-shadowing", + "bugfix/transform-safari-id-destructuring-collision-in-function-expression", + "bugfix/transform-tagged-template-caching", + "bugfix/transform-v8-spread-parameters-in-optional-chaining", + ]; + + if (process.env.BABEL_8_BREAKING && orderList.includes(pluginObject.name)) { + pluginObject.orderData = { + id: "@babel/helper-plugin-order-data", + version: 1, + type: "list", + data: () => { + return orderList; + }, + }; + } + + return pluginObject; }; } diff --git a/packages/babel-plugin-proposal-destructuring-private/test/fixtures/typescript/invalid-after-destructuring-private-babel-7/input.ts b/packages/babel-plugin-proposal-destructuring-private/test/fixtures/typescript/invalid-after-destructuring-private-babel-7/input.ts new file mode 100644 index 000000000000..e108eb0a6b7e --- /dev/null +++ b/packages/babel-plugin-proposal-destructuring-private/test/fixtures/typescript/invalid-after-destructuring-private-babel-7/input.ts @@ -0,0 +1,4 @@ +class C { + #x; + constructor(public foo, { #x: x}) {} +} diff --git a/packages/babel-plugin-proposal-destructuring-private/test/fixtures/typescript/invalid-after-destructuring-private-babel-7/options.json b/packages/babel-plugin-proposal-destructuring-private/test/fixtures/typescript/invalid-after-destructuring-private-babel-7/options.json new file mode 100644 index 000000000000..49e9e5f42f80 --- /dev/null +++ b/packages/babel-plugin-proposal-destructuring-private/test/fixtures/typescript/invalid-after-destructuring-private-babel-7/options.json @@ -0,0 +1,7 @@ +{ + "plugins": ["proposal-destructuring-private", "transform-typescript"], + "throws": [ + "TypeScript features must first be transformed by @babel/plugin-transform-typescript." + ], + "BABEL_8_BREAKING": false +} diff --git a/packages/babel-plugin-proposal-destructuring-private/test/fixtures/typescript/invalid-after-destructuring-private/options.json b/packages/babel-plugin-proposal-destructuring-private/test/fixtures/typescript/invalid-after-destructuring-private/options.json index c033e98f1b8e..bce69e3ab375 100644 --- a/packages/babel-plugin-proposal-destructuring-private/test/fixtures/typescript/invalid-after-destructuring-private/options.json +++ b/packages/babel-plugin-proposal-destructuring-private/test/fixtures/typescript/invalid-after-destructuring-private/options.json @@ -2,5 +2,7 @@ "plugins": ["proposal-destructuring-private", "transform-typescript"], "throws": [ "TypeScript features must first be transformed by @babel/plugin-transform-typescript." - ] + ], + "sortPlugins": false, + "BABEL_8_BREAKING": true } diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec-babel-7/input.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec-babel-7/input.js new file mode 100644 index 000000000000..21f2cd9050d4 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec-babel-7/input.js @@ -0,0 +1,4 @@ +(async function() { await 'ok' })(); +(async () => { await 'ok' })(); +(async function notIIFE() { await 'ok' }); +(async () => { await 'not iife' }); diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec-babel-7/options.json b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec-babel-7/options.json new file mode 100644 index 000000000000..74da06e29387 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec-babel-7/options.json @@ -0,0 +1,8 @@ +{ + "plugins": [ + ["transform-arrow-functions", { "spec": true }], + "transform-regenerator", + "transform-async-to-generator" + ], + "BABEL_8_BREAKING": false +} diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec-babel-7/output.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec-babel-7/output.js new file mode 100644 index 000000000000..22fae9825792 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec-babel-7/output.js @@ -0,0 +1,57 @@ +var _this = this; +babelHelpers.asyncToGenerator( /*#__PURE__*/babelHelpers.regeneratorRuntime().mark(function _callee() { + return babelHelpers.regeneratorRuntime().wrap(function _callee$(_context) { + while (1) switch (_context.prev = _context.next) { + case 0: + _context.next = 2; + return 'ok'; + case 2: + case "end": + return _context.stop(); + } + }, _callee); +}))(); +babelHelpers.asyncToGenerator( /*#__PURE__*/babelHelpers.regeneratorRuntime().mark(function _callee2() { + return babelHelpers.regeneratorRuntime().wrap(function _callee2$(_context2) { + while (1) switch (_context2.prev = _context2.next) { + case 0: + babelHelpers.newArrowCheck(this, _this); + _context2.next = 3; + return 'ok'; + case 3: + case "end": + return _context2.stop(); + } + }, _callee2, this); +})).bind(this)(); +/*#__PURE__*/(function () { + var _notIIFE = babelHelpers.asyncToGenerator( /*#__PURE__*/babelHelpers.regeneratorRuntime().mark(function _callee3() { + return babelHelpers.regeneratorRuntime().wrap(function _callee3$(_context3) { + while (1) switch (_context3.prev = _context3.next) { + case 0: + _context3.next = 2; + return 'ok'; + case 2: + case "end": + return _context3.stop(); + } + }, _callee3); + })); + function notIIFE() { + return _notIIFE.apply(this, arguments); + } + return notIIFE; +})(); +/*#__PURE__*/babelHelpers.asyncToGenerator( /*#__PURE__*/babelHelpers.regeneratorRuntime().mark(function _callee4() { + return babelHelpers.regeneratorRuntime().wrap(function _callee4$(_context4) { + while (1) switch (_context4.prev = _context4.next) { + case 0: + babelHelpers.newArrowCheck(this, _this); + _context4.next = 3; + return 'not iife'; + case 3: + case "end": + return _context4.stop(); + } + }, _callee4, this); +})).bind(this); diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/options.json b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/options.json index 7aa70e7c2b47..78c79b3c1465 100644 --- a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/options.json +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/options.json @@ -3,5 +3,6 @@ ["transform-arrow-functions", { "spec": true }], "transform-regenerator", "transform-async-to-generator" - ] + ], + "BABEL_8_BREAKING": true } diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/output.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/output.js index 22fae9825792..83445d5e0077 100644 --- a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/output.js +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-iife-with-regenerator-spec/output.js @@ -1,4 +1,3 @@ -var _this = this; babelHelpers.asyncToGenerator( /*#__PURE__*/babelHelpers.regeneratorRuntime().mark(function _callee() { return babelHelpers.regeneratorRuntime().wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { @@ -15,15 +14,14 @@ babelHelpers.asyncToGenerator( /*#__PURE__*/babelHelpers.regeneratorRuntime().ma return babelHelpers.regeneratorRuntime().wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: - babelHelpers.newArrowCheck(this, _this); - _context2.next = 3; + _context2.next = 2; return 'ok'; - case 3: + case 2: case "end": return _context2.stop(); } - }, _callee2, this); -})).bind(this)(); + }, _callee2); +}))(); /*#__PURE__*/(function () { var _notIIFE = babelHelpers.asyncToGenerator( /*#__PURE__*/babelHelpers.regeneratorRuntime().mark(function _callee3() { return babelHelpers.regeneratorRuntime().wrap(function _callee3$(_context3) { @@ -46,12 +44,11 @@ babelHelpers.asyncToGenerator( /*#__PURE__*/babelHelpers.regeneratorRuntime().ma return babelHelpers.regeneratorRuntime().wrap(function _callee4$(_context4) { while (1) switch (_context4.prev = _context4.next) { case 0: - babelHelpers.newArrowCheck(this, _this); - _context4.next = 3; + _context4.next = 2; return 'not iife'; - case 3: + case 2: case "end": return _context4.stop(); } - }, _callee4, this); -})).bind(this); + }, _callee4); +})); diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/regression/4943-babel-7/exec.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/regression/4943-babel-7/exec.js new file mode 100644 index 000000000000..c8839c7358f9 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/regression/4943-babel-7/exec.js @@ -0,0 +1,13 @@ +"use strict"; + +function mandatory(paramName) { + throw new Error(`Missing parameter: ${paramName}`); +} + +async function foo({ a, b = mandatory("b") } = {}) { + return Promise.resolve(b); +} + +return foo().then(() => { + throw new Error('should not occur'); +}, () => true); diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/regression/4943-babel-7/input.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/regression/4943-babel-7/input.js new file mode 100644 index 000000000000..a5d6442f4e78 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/regression/4943-babel-7/input.js @@ -0,0 +1,9 @@ +"use strict"; + +function mandatory(paramName) { + throw new Error(`Missing parameter: ${paramName}`); +} + +async function foo({ a, b = mandatory("b") }) { + return Promise.resolve(b); +} diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/regression/4943-babel-7/options.json b/packages/babel-plugin-transform-async-to-generator/test/fixtures/regression/4943-babel-7/options.json new file mode 100644 index 000000000000..b7871e189fd7 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/regression/4943-babel-7/options.json @@ -0,0 +1,11 @@ +{ + "plugins": [ + "transform-async-to-generator", + "transform-destructuring", + "transform-parameters" + ], + "parserOpts": { + "allowReturnOutsideFunction": true + }, + "BABEL_8_BREAKING": false +} diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/regression/4943-babel-7/output.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/regression/4943-babel-7/output.js new file mode 100644 index 000000000000..036d4585a2eb --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/regression/4943-babel-7/output.js @@ -0,0 +1,19 @@ +"use strict"; + +function mandatory(paramName) { + throw new Error(`Missing parameter: ${paramName}`); +} +function foo(_x) { + return _foo.apply(this, arguments); +} +function _foo() { + _foo = babelHelpers.asyncToGenerator(function (_ref) { + let a = _ref.a, + _ref$b = _ref.b, + b = _ref$b === void 0 ? mandatory("b") : _ref$b; + return function* () { + return Promise.resolve(b); + }(); + }); + return _foo.apply(this, arguments); +} diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/regression/4943/options.json b/packages/babel-plugin-transform-async-to-generator/test/fixtures/regression/4943/options.json index 5d0999606137..c2bc84e73d47 100644 --- a/packages/babel-plugin-transform-async-to-generator/test/fixtures/regression/4943/options.json +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/regression/4943/options.json @@ -6,5 +6,7 @@ ], "parserOpts": { "allowReturnOutsideFunction": true - } + }, + "sortPlugins": false, + "BABEL_8_BREAKING": true } diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/hoisting-babel-7/input.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/hoisting-babel-7/input.js new file mode 100644 index 000000000000..50a10043c570 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/hoisting-babel-7/input.js @@ -0,0 +1,7 @@ +for (let i of nums) { + var x = 5; + var { f } = { f: 2 }; + fns.push(function () { + return i * x; + }); +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/hoisting-babel-7/options.json b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/hoisting-babel-7/options.json new file mode 100644 index 000000000000..f764d9bc7a57 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/hoisting-babel-7/options.json @@ -0,0 +1,10 @@ +{ + "plugins": [ + "transform-block-scoping", + "syntax-jsx", + "transform-react-jsx", + "transform-block-scoped-functions", + "transform-for-of" + ], + "BABEL_8_BREAKING": false +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/hoisting-babel-7/output.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/hoisting-babel-7/output.js new file mode 100644 index 000000000000..5756895ddd6f --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/hoisting-babel-7/output.js @@ -0,0 +1,25 @@ +var _loop = function (i) { + x = 5; + ({ + f + } = { + f: 2 + }); + fns.push(function () { + return i * x; + }); + }, + x, + f; +var _iterator = babelHelpers.createForOfIteratorHelper(nums), + _step; +try { + for (_iterator.s(); !(_step = _iterator.n()).done;) { + var i = _step.value; + _loop(i); + } +} catch (err) { + _iterator.e(err); +} finally { + _iterator.f(); +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/hoisting/options.json b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/hoisting/options.json index c1b2fe494b7f..fa65e589dcb8 100644 --- a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/hoisting/options.json +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/hoisting/options.json @@ -5,5 +5,7 @@ "transform-react-jsx", "transform-block-scoped-functions", "transform-for-of" - ] + ], + "sortPlugins": false, + "BABEL_8_BREAKING": true } diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10339-babel-7/exec.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10339-babel-7/exec.js new file mode 100644 index 000000000000..a5d4e1b69153 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10339-babel-7/exec.js @@ -0,0 +1,38 @@ +const code = ` + for (const {foo, ...bar} of { bar: [] }) { + () => foo; + const [qux] = bar; + try {} catch (e) { + let quux = qux; + } + } +`; + +let programPath; +let forOfPath; +let functionPath; + +return transformAsync(code, { + configFile: false, + plugins: [ + __dirname + "/../../../../lib/index.js", + { + post({ path }) { + programPath = path; + path.traverse({ + ForOfStatement(path) { forOfPath = path }, + FunctionExpression(path) { functionPath = path } + }); + } + } + ] +}).then(() => { + expect(Object.keys(programPath.scope.bindings)).toEqual(["foo", "bar"]); + + // for declarations should be transformed to for bindings + expect(forOfPath.scope.bindings).toEqual({}); + // The body should be wrapped into closure + expect(forOfPath.get("body").scope.bindings).toEqual({}); + + expect(Object.keys(functionPath.scope.bindings)).toEqual(["foo", "qux", "quux"]); +}); diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10339-babel-7/input.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10339-babel-7/input.js new file mode 100644 index 000000000000..dcca3b6e2d97 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10339-babel-7/input.js @@ -0,0 +1,7 @@ +for (const {foo, ...bar} of {}) { + () => foo; + const [qux] = bar; + try {} catch (e) { + const quux = qux; + } +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10339-babel-7/options.json b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10339-babel-7/options.json new file mode 100644 index 000000000000..c7e08ae9e9c7 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10339-babel-7/options.json @@ -0,0 +1,8 @@ +{ + "plugins": [ + "transform-block-scoping", + ["transform-object-rest-spread", { "loose": true }] + ], + "parserOpts": { "allowReturnOutsideFunction": true }, + "BABEL_8_BREAKING": false +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10339-babel-7/output.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10339-babel-7/output.js new file mode 100644 index 000000000000..2b5c3ad548c4 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10339-babel-7/output.js @@ -0,0 +1,15 @@ +var _excluded = ["foo"]; +var _loop = function (foo) { + () => foo; + var [qux] = bar; + try {} catch (e) { + var quux = qux; + } +}; +for (var _ref of {}) { + var { + foo + } = _ref, + bar = babelHelpers.objectWithoutPropertiesLoose(_ref, _excluded); + _loop(foo); +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10339/options.json b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10339/options.json index 9167b2c5167f..f58e495c5812 100644 --- a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10339/options.json +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10339/options.json @@ -3,5 +3,7 @@ "transform-block-scoping", ["transform-object-rest-spread", { "loose": true }] ], - "parserOpts": { "allowReturnOutsideFunction": true } + "parserOpts": { "allowReturnOutsideFunction": true }, + "sortPlugins": false, + "BABEL_8_BREAKING": true } diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-after-babel-7/exec.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-after-babel-7/exec.js new file mode 100644 index 000000000000..18a3b07a8cb5 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-after-babel-7/exec.js @@ -0,0 +1,15 @@ +"use strict"; + +const results = [0, 1, 2]; +const fns = []; + +for (let result of results) { + result = result * 2; + fns.push(() => { + return result; + }); +} + +expect(fns[0]()).toBe(0); +expect(fns[1]()).toBe(2); +expect(fns[2]()).toBe(4); diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-after-babel-7/input.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-after-babel-7/input.js new file mode 100644 index 000000000000..bd369896a5c3 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-after-babel-7/input.js @@ -0,0 +1,6 @@ +for (let result of results) { + result = otherValue; + fn(() => { + result; + }); +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-after-babel-7/options.json b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-after-babel-7/options.json new file mode 100644 index 000000000000..7305a2641b81 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-after-babel-7/options.json @@ -0,0 +1,7 @@ +{ + "plugins": [ + ["transform-block-scoping", { "loose": true }], + "transform-for-of" + ], + "BABEL_8_BREAKING": false +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-after-babel-7/output.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-after-babel-7/output.js new file mode 100644 index 000000000000..68232a272bd7 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-after-babel-7/output.js @@ -0,0 +1,18 @@ +var _loop = function (result) { + result = otherValue; + fn(() => { + result; + }); +}; +var _iterator = babelHelpers.createForOfIteratorHelper(results), + _step; +try { + for (_iterator.s(); !(_step = _iterator.n()).done;) { + var result = _step.value; + _loop(result); + } +} catch (err) { + _iterator.e(err); +} finally { + _iterator.f(); +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-after/options.json b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-after/options.json index 4830b713117e..15378929942b 100644 --- a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-after/options.json +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-after/options.json @@ -2,5 +2,7 @@ "plugins": [ ["transform-block-scoping", { "loose": true }], "transform-for-of" - ] + ], + "sortPlugins": false, + "BABEL_8_BREAKING": true } diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-loose-after-babel-7/exec.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-loose-after-babel-7/exec.js new file mode 100644 index 000000000000..18a3b07a8cb5 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-loose-after-babel-7/exec.js @@ -0,0 +1,15 @@ +"use strict"; + +const results = [0, 1, 2]; +const fns = []; + +for (let result of results) { + result = result * 2; + fns.push(() => { + return result; + }); +} + +expect(fns[0]()).toBe(0); +expect(fns[1]()).toBe(2); +expect(fns[2]()).toBe(4); diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-loose-after-babel-7/input.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-loose-after-babel-7/input.js new file mode 100644 index 000000000000..bd369896a5c3 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-loose-after-babel-7/input.js @@ -0,0 +1,6 @@ +for (let result of results) { + result = otherValue; + fn(() => { + result; + }); +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-loose-after-babel-7/options.json b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-loose-after-babel-7/options.json new file mode 100644 index 000000000000..9491bb5a05aa --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-loose-after-babel-7/options.json @@ -0,0 +1,7 @@ +{ + "plugins": [ + ["transform-block-scoping", { "loose": true }], + ["transform-for-of", { "loose": true }] + ], + "BABEL_8_BREAKING": false +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-loose-after-babel-7/output.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-loose-after-babel-7/output.js new file mode 100644 index 000000000000..2ee87f99c1c4 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-loose-after-babel-7/output.js @@ -0,0 +1,10 @@ +var _loop = function (result) { + result = otherValue; + fn(() => { + result; + }); +}; +for (var _iterator = babelHelpers.createForOfIteratorHelperLoose(results), _step; !(_step = _iterator()).done;) { + var result = _step.value; + _loop(result); +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-loose-after/options.json b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-loose-after/options.json index fe50de04b18d..e7adea8f01ca 100644 --- a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-loose-after/options.json +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-8128-for-of-loose-after/options.json @@ -2,5 +2,7 @@ "plugins": [ ["transform-block-scoping", { "loose": true }], ["transform-for-of", { "loose": true }] - ] + ], + "sortPlugins": false, + "BABEL_8_BREAKING": true } diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/decorators-legacy-interop/wrong-order-babel-7/input.js b/packages/babel-plugin-transform-class-properties/test/fixtures/decorators-legacy-interop/wrong-order-babel-7/input.js new file mode 100644 index 000000000000..248eee836d59 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/decorators-legacy-interop/wrong-order-babel-7/input.js @@ -0,0 +1,2 @@ +@deco +class Foo {} \ No newline at end of file diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/decorators-legacy-interop/wrong-order-babel-7/options.json b/packages/babel-plugin-transform-class-properties/test/fixtures/decorators-legacy-interop/wrong-order-babel-7/options.json new file mode 100644 index 000000000000..564ecf8e66cb --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/decorators-legacy-interop/wrong-order-babel-7/options.json @@ -0,0 +1,8 @@ +{ + "plugins": [ + ["transform-class-properties", { "loose": true }], + ["proposal-decorators", { "version": "legacy" }] + ], + "throws": "Decorators are not enabled.", + "BABEL_8_BREAKING": false +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/decorators-legacy-interop/wrong-order/options.json b/packages/babel-plugin-transform-class-properties/test/fixtures/decorators-legacy-interop/wrong-order/options.json index 9666d1e262a7..272f04157cbe 100644 --- a/packages/babel-plugin-transform-class-properties/test/fixtures/decorators-legacy-interop/wrong-order/options.json +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/decorators-legacy-interop/wrong-order/options.json @@ -3,5 +3,7 @@ ["transform-class-properties", { "loose": true }], ["proposal-decorators", { "version": "legacy" }] ], - "throws": "Decorators are not enabled." + "throws": "Decorators are not enabled.", + "sortPlugins": false, + "BABEL_8_BREAKING": true } diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/class/transform-properties-declare-wrong-order-babel-7/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/class/transform-properties-declare-wrong-order-babel-7/input.ts new file mode 100644 index 000000000000..afc220470140 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/class/transform-properties-declare-wrong-order-babel-7/input.ts @@ -0,0 +1,4 @@ +class A { + declare x; + y; +} \ No newline at end of file diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/class/transform-properties-declare-wrong-order-babel-7/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/class/transform-properties-declare-wrong-order-babel-7/options.json new file mode 100644 index 000000000000..17ef050bf309 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/class/transform-properties-declare-wrong-order-babel-7/options.json @@ -0,0 +1,5 @@ +{ + "plugins": ["transform-class-properties", "transform-typescript"], + "throws": "TypeScript 'declare' fields must first be transformed by @babel/plugin-transform-typescript.\nIf you have already enabled that plugin (or '@babel/preset-typescript'), make sure that it runs before any plugin related to additional class features:\n - @babel/plugin-transform-class-properties\n - @babel/plugin-transform-private-methods\n - @babel/plugin-proposal-decorators", + "BABEL_8_BREAKING": false +} diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/class/transform-properties-declare-wrong-order/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/class/transform-properties-declare-wrong-order/options.json index aa7fe5f44910..cb063df08ef9 100644 --- a/packages/babel-plugin-transform-typescript/test/fixtures/class/transform-properties-declare-wrong-order/options.json +++ b/packages/babel-plugin-transform-typescript/test/fixtures/class/transform-properties-declare-wrong-order/options.json @@ -1,7 +1,6 @@ { - "plugins": [ - "transform-class-properties", - "transform-typescript" - ], - "throws": "TypeScript 'declare' fields must first be transformed by @babel/plugin-transform-typescript.\nIf you have already enabled that plugin (or '@babel/preset-typescript'), make sure that it runs before any plugin related to additional class features:\n - @babel/plugin-transform-class-properties\n - @babel/plugin-transform-private-methods\n - @babel/plugin-proposal-decorators" + "plugins": ["transform-class-properties", "transform-typescript"], + "throws": "TypeScript 'declare' fields must first be transformed by @babel/plugin-transform-typescript.\nIf you have already enabled that plugin (or '@babel/preset-typescript'), make sure that it runs before any plugin related to additional class features:\n - @babel/plugin-transform-class-properties\n - @babel/plugin-transform-private-methods\n - @babel/plugin-proposal-decorators", + "sortPlugins": false, + "BABEL_8_BREAKING": true }