From 75847306fd10075713fe917e31d057d8e407f897 Mon Sep 17 00:00:00 2001 From: Logan Smyth Date: Wed, 5 Apr 2017 15:59:53 -0700 Subject: [PATCH] Expose passes as a first-class output of OptionManager. --- packages/babel-core/src/config/index.js | 18 +---- .../babel-core/src/config/option-manager.js | 70 +++++++++++-------- packages/babel-core/test/option-manager.js | 4 +- 3 files changed, 44 insertions(+), 48 deletions(-) diff --git a/packages/babel-core/src/config/index.js b/packages/babel-core/src/config/index.js index 238bc81cdf..a37b7bc55b 100644 --- a/packages/babel-core/src/config/index.js +++ b/packages/babel-core/src/config/index.js @@ -10,21 +10,5 @@ export type ResolvedConfig = { * Standard API for loading Babel configuration data. Not for public consumption. */ export default function loadConfig(opts: Object): ResolvedConfig|null { - const mergedOpts = manageOptions(opts); - if (!mergedOpts) return null; - - let passes = []; - if (mergedOpts.plugins) { - passes.push(mergedOpts.plugins); - } - - // With "passPerPreset" enabled there may still be presets in the options. - if (mergedOpts.presets) { - passes = passes.concat(mergedOpts.presets.map((preset) => preset.plugins).filter(Boolean)); - } - - return { - options: mergedOpts, - passes, - }; + return manageOptions(opts); } diff --git a/packages/babel-core/src/config/option-manager.js b/packages/babel-core/src/config/option-manager.js index 585c9db281..ba313cb1fb 100644 --- a/packages/babel-core/src/config/option-manager.js +++ b/packages/babel-core/src/config/option-manager.js @@ -92,14 +92,15 @@ export default function manageOptions(opts?: Object) { class OptionManager { constructor() { this.options = createBareOptions(); + this.passes = [[]]; } options: Object; + passes: Array>; /** * This is called when we want to merge the input `opts` into the - * base options (passed as the `extendingOpts`: at top-level it's the - * main options, at presets level it's presets options). + * base options. * * - `alias` is used to output pretty traces back to the original source. * - `loc` is used to point to the original config. @@ -109,13 +110,14 @@ class OptionManager { mergeOptions({ type, options: rawOpts, - extending: extendingOpts, alias, loc, dirname, - }: MergeOptions) { + }: MergeOptions, pass?: Array) { alias = alias || "foreign"; + if (!pass) pass = this.passes[0]; + // if (typeof rawOpts !== "object" || Array.isArray(rawOpts)) { throw new TypeError(`Invalid options type for ${alias}`); @@ -176,45 +178,43 @@ class OptionManager { opts.generatorOpts.generator = loadGenerator(opts.generatorOpts.generator, dirname).generator; } - // resolve plugins - if (opts.plugins) { - if (!Array.isArray(rawOpts.plugins)) throw new Error(`${alias}.plugins should be an array`); - - opts.plugins = normalisePlugins(loc, dirname, opts.plugins); - } - // resolve presets if (opts.presets) { if (!Array.isArray(rawOpts.presets)) throw new Error(`${alias}.presets should be an array`); - opts.presets = resolvePresets(opts.presets, dirname).map(([preset, presetLoc]) => { + const presets = resolvePresets(opts.presets, dirname); + + let presetPasses = null; + if (opts.passPerPreset) { + presetPasses = presets.map(() => []); + // The passes are created in the same order as the preset list, but are inserted before any + // existing additional passes. + this.passes.splice(1, 0, ...presetPasses); + } + + presets.forEach(([preset, presetLoc], i) => { this.mergeOptions({ type: "preset", options: preset, - - // For `passPerPreset` we merge child options back into the preset object instead of the root. - extending: opts.passPerPreset ? preset : null, alias: presetLoc, loc: presetLoc, dirname: dirname, - }); - - return preset; + }, presetPasses ? presetPasses[i] : pass); }); - - // If not passPerPreset, the plugins have all been merged into the parent config so the presets - // list is not needed. - if (!opts.passPerPreset) delete opts.presets; } - // Merge them into current extending options in case of top-level - // options. In case of presets, just re-assign options which are got - // normalized during the `mergeOptions`. - if (rawOpts === extendingOpts) { - Object.assign(extendingOpts, opts); - } else { - merge(extendingOpts || this.options, opts); + // resolve plugins + if (opts.plugins) { + if (!Array.isArray(rawOpts.plugins)) throw new Error(`${alias}.plugins should be an array`); + + pass.unshift(...normalisePlugins(loc, dirname, opts.plugins)); } + + delete opts.passPerPreset; + delete opts.plugins; + delete opts.presets; + + merge(this.options, opts); } init(opts: Object = {}): Object { @@ -237,6 +237,13 @@ class OptionManager { opts = this.options; + // Tack the passes onto the object itself so that, if this object is passed back to Babel a second time, + // it will be in the right structure to not change behavior. + opts.plugins = this.passes[0]; + opts.presets = this.passes.slice(1) + .filter((plugins) => plugins.length > 0) + .map((plugins) => ({ plugins })); + if (opts.inputSourceMap) { opts.sourceMaps = true; } @@ -264,7 +271,10 @@ class OptionManager { sourceMapTarget: basenameRelative, }); - return opts; + return { + options: opts, + passes: this.passes, + }; } } diff --git a/packages/babel-core/test/option-manager.js b/packages/babel-core/test/option-manager.js index b0bbd18fea..d9caef2cdf 100644 --- a/packages/babel-core/test/option-manager.js +++ b/packages/babel-core/test/option-manager.js @@ -53,12 +53,14 @@ describe("option-manager", () => { describe("presets", function () { function presetTest(name) { it(name, function () { - const options = manageOptions({ + const { options, passes } = manageOptions({ "presets": [path.join(__dirname, "fixtures/option-manager/presets", name)], }); assert.equal(true, Array.isArray(options.plugins)); assert.equal(1, options.plugins.length); + assert.equal(1, passes.length); + assert.equal(1, passes[0].length); }); }