From d2139813a65e4a79ba240dc5bb2ba79d2720bf5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Sun, 12 Apr 2020 17:21:06 +0200 Subject: [PATCH] Resolve all the presets before instantiating plugins --- packages/babel-core/src/config/full.js | 131 ++++++++---------- .../src/config/validation/options.js | 10 +- 2 files changed, 61 insertions(+), 80 deletions(-) diff --git a/packages/babel-core/src/config/full.js b/packages/babel-core/src/config/full.js index c9fb038a3074..7f9050d4ad95 100644 --- a/packages/babel-core/src/config/full.js +++ b/packages/babel-core/src/config/full.js @@ -66,61 +66,45 @@ export default gensync<[any], ResolvedConfig | null>(function* loadFullConfig( const { options, context } = result; const optionDefaults = {}; - const passes = [[]]; - try { - const { plugins, presets } = options; - if (!plugins || !presets) { - throw new Error("Assertion failure - plugins and presets exist"); + const { plugins, presets } = options; + + if (!plugins || !presets) { + throw new Error("Assertion failure - plugins and presets exist"); + } + + const toDescriptor = item => { + const desc = getItemDescriptor(item); + if (!desc) { + throw new Error("Assertion failure - must be config item"); } - const ignored = yield* (function* recurseDescriptors( - config: { - plugins: Array, - presets: Array, - }, - pass: Array, - ) { - const plugins = []; - for (let i = 0; i < config.plugins.length; i++) { - const descriptor = config.plugins[i]; - if (descriptor.options !== false) { - try { - plugins.push(yield* loadPluginDescriptor(descriptor, context)); - } catch (e) { - // print special message for `plugins: ["@babel/foo", { foo: "option" }]` - if (i > 0 && e.code === "BABEL_UNKNOWN_PLUGIN_PROPERTY") { - checkNoUnwrappedItemOptionPairs( - config.plugins[i - 1], - descriptor, - "plugin", - i, - e, - ); - } - throw e; - } - } - } + return desc; + }; + + const presetsDescriptors = presets.map(toDescriptor); + const initialPluginsDescriptors = plugins.map(toDescriptor); + const pluginDescriptorsByPass = [[]]; + const passes = []; + try { + const ignored = yield* (function* recursePresetDescriptors( + rawPresets: Array, + pluginDescriptorsPass: Array, + ) { const presets = []; - for (let i = 0; i < config.presets.length; i++) { - const descriptor = config.presets[i]; + + for (let i = 0; i < rawPresets.length; i++) { + const descriptor = rawPresets[i]; if (descriptor.options !== false) { try { presets.push({ preset: yield* loadPresetDescriptor(descriptor, context), - pass: descriptor.ownPass ? [] : pass, + pass: descriptor.ownPass ? [] : pluginDescriptorsPass, }); } catch (e) { - if (i > 0 && e.code === "BABEL_UNKNOWN_OPTION") { - checkNoUnwrappedItemOptionPairs( - config.presets[i - 1], - descriptor, - "preset", - i, - e, - ); + if (e.code === "BABEL_UNKNOWN_OPTION") { + checkNoUnwrappedItemOptionPairs(rawPresets, i, "preset", e); } throw e; } @@ -131,22 +115,18 @@ export default gensync<[any], ResolvedConfig | null>(function* loadFullConfig( if (presets.length > 0) { // The passes are created in the same order as the preset list, but are inserted before any // existing additional passes. - passes.splice( + pluginDescriptorsByPass.splice( 1, 0, - ...presets.map(o => o.pass).filter(p => p !== pass), + ...presets.map(o => o.pass).filter(p => p !== pluginDescriptorsPass), ); for (const { preset, pass } of presets) { if (!preset) return true; - const ignored = yield* recurseDescriptors( - { - plugins: preset.plugins, - presets: preset.presets, - }, - pass, - ); + pass.unshift(...preset.plugins); + + const ignored = yield* recursePresetDescriptors(preset.presets, pass); if (ignored) return true; preset.options.forEach(opts => { @@ -154,34 +134,31 @@ export default gensync<[any], ResolvedConfig | null>(function* loadFullConfig( }); } } + })(presetsDescriptors, pluginDescriptorsByPass[0]); - // resolve plugins - if (plugins.length > 0) { - pass.unshift(...plugins); - } - })( - { - plugins: plugins.map(item => { - const desc = getItemDescriptor(item); - if (!desc) { - throw new Error("Assertion failure - must be config item"); - } + if (ignored) return null; - return desc; - }), - presets: presets.map(item => { - const desc = getItemDescriptor(item); - if (!desc) { - throw new Error("Assertion failure - must be config item"); - } + pluginDescriptorsByPass[0].unshift(...initialPluginsDescriptors); - return desc; - }), - }, - passes[0], - ); + for (const descs of pluginDescriptorsByPass) { + const pass = []; + passes.push(pass); - if (ignored) return null; + for (let i = 0; i < descs.length; i++) { + const descriptor = descs[i]; + if (descriptor.options !== false) { + try { + pass.push(yield* loadPluginDescriptor(descriptor, context)); + } catch (e) { + if (e.code === "BABEL_UNKNOWN_PLUGIN_PROPERTY") { + // print special message for `plugins: ["@babel/foo", { foo: "option" }]` + checkNoUnwrappedItemOptionPairs(descs, i, "plugin", e); + } + throw e; + } + } + } + } } catch (e) { // There are a few case where thrown errors will try to annotate themselves multiple times, so // to keep things simple we just bail out if re-wrapping the message. diff --git a/packages/babel-core/src/config/validation/options.js b/packages/babel-core/src/config/validation/options.js index c3e7f359cd90..6e5c6c0537cc 100644 --- a/packages/babel-core/src/config/validation/options.js +++ b/packages/babel-core/src/config/validation/options.js @@ -446,12 +446,16 @@ function assertOverridesList(loc: OptionPath, value: mixed): OverridesList { } export function checkNoUnwrappedItemOptionPairs( - lastItem: UnloadedDescriptor, - thisItem: UnloadedDescriptor, - type: "plugin" | "preset", + items: Array, index: number, + type: "plugin" | "preset", e: Error, ): void { + if (index === 0) return; + + const lastItem = items[index - 1]; + const thisItem = items[index]; + if ( lastItem.file && lastItem.options === undefined &&