Instantiate presets before plugins (#11689)
This commit is contained in:
parent
ce7b170ab7
commit
1b90d90fcc
@ -24,6 +24,7 @@ import {
|
|||||||
validate,
|
validate,
|
||||||
type CallerMetadata,
|
type CallerMetadata,
|
||||||
checkNoUnwrappedItemOptionPairs,
|
checkNoUnwrappedItemOptionPairs,
|
||||||
|
type PluginItem,
|
||||||
} from "./validation/options";
|
} from "./validation/options";
|
||||||
import { validatePluginObject } from "./validation/plugins";
|
import { validatePluginObject } from "./validation/plugins";
|
||||||
import makeAPI from "./helpers/config-api";
|
import makeAPI from "./helpers/config-api";
|
||||||
@ -70,58 +71,59 @@ export default gensync<[any], ResolvedConfig | null>(function* loadFullConfig(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const optionDefaults = {};
|
const optionDefaults = {};
|
||||||
const passes: Array<Array<Plugin>> = [[]];
|
|
||||||
try {
|
|
||||||
const { plugins, presets } = options;
|
|
||||||
|
|
||||||
if (!plugins || !presets) {
|
const { plugins, presets } = options;
|
||||||
throw new Error("Assertion failure - plugins and presets exist");
|
|
||||||
|
if (!plugins || !presets) {
|
||||||
|
throw new Error("Assertion failure - plugins and presets exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
const toDescriptor = (item: PluginItem) => {
|
||||||
|
const desc = getItemDescriptor(item);
|
||||||
|
if (!desc) {
|
||||||
|
throw new Error("Assertion failure - must be config item");
|
||||||
}
|
}
|
||||||
|
|
||||||
const ignored = yield* (function* recurseDescriptors(config, pass) {
|
return desc;
|
||||||
const plugins: Array<Plugin> = [];
|
};
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const presetsDescriptors = presets.map(toDescriptor);
|
||||||
|
const initialPluginsDescriptors = plugins.map(toDescriptor);
|
||||||
|
const pluginDescriptorsByPass: Array<Array<UnloadedDescriptor>> = [[]];
|
||||||
|
const passes: Array<Array<Plugin>> = [];
|
||||||
|
|
||||||
|
const ignored = yield* enhanceError(
|
||||||
|
context,
|
||||||
|
function* recursePresetDescriptors(
|
||||||
|
rawPresets: Array<UnloadedDescriptor>,
|
||||||
|
pluginDescriptorsPass: Array<UnloadedDescriptor>,
|
||||||
|
) {
|
||||||
const presets: Array<{|
|
const presets: Array<{|
|
||||||
preset: ConfigChain | null,
|
preset: ConfigChain | null,
|
||||||
pass: Array<Plugin>,
|
pass: Array<UnloadedDescriptor>,
|
||||||
|}> = [];
|
|}> = [];
|
||||||
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) {
|
if (descriptor.options !== false) {
|
||||||
try {
|
try {
|
||||||
presets.push({
|
// Presets normally run in reverse order, but if they
|
||||||
preset: yield* loadPresetDescriptor(descriptor, context),
|
// have their own pass they run after the presets
|
||||||
pass: descriptor.ownPass ? [] : pass,
|
// in the previous pass.
|
||||||
});
|
if (descriptor.ownPass) {
|
||||||
|
presets.push({
|
||||||
|
preset: yield* loadPresetDescriptor(descriptor, context),
|
||||||
|
pass: [],
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
presets.unshift({
|
||||||
|
preset: yield* loadPresetDescriptor(descriptor, context),
|
||||||
|
pass: pluginDescriptorsPass,
|
||||||
|
});
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (i > 0 && e.code === "BABEL_UNKNOWN_OPTION") {
|
if (e.code === "BABEL_UNKNOWN_OPTION") {
|
||||||
checkNoUnwrappedItemOptionPairs(
|
checkNoUnwrappedItemOptionPairs(rawPresets, i, "preset", e);
|
||||||
config.presets[i - 1],
|
|
||||||
descriptor,
|
|
||||||
"preset",
|
|
||||||
i,
|
|
||||||
e,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
@ -132,22 +134,18 @@ export default gensync<[any], ResolvedConfig | null>(function* loadFullConfig(
|
|||||||
if (presets.length > 0) {
|
if (presets.length > 0) {
|
||||||
// The passes are created in the same order as the preset list, but are inserted before any
|
// The passes are created in the same order as the preset list, but are inserted before any
|
||||||
// existing additional passes.
|
// existing additional passes.
|
||||||
passes.splice(
|
pluginDescriptorsByPass.splice(
|
||||||
1,
|
1,
|
||||||
0,
|
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) {
|
for (const { preset, pass } of presets) {
|
||||||
if (!preset) return true;
|
if (!preset) return true;
|
||||||
|
|
||||||
const ignored = yield* recurseDescriptors(
|
pass.push(...preset.plugins);
|
||||||
{
|
|
||||||
plugins: preset.plugins,
|
const ignored = yield* recursePresetDescriptors(preset.presets, pass);
|
||||||
presets: preset.presets,
|
|
||||||
},
|
|
||||||
pass,
|
|
||||||
);
|
|
||||||
if (ignored) return true;
|
if (ignored) return true;
|
||||||
|
|
||||||
preset.options.forEach(opts => {
|
preset.options.forEach(opts => {
|
||||||
@ -155,47 +153,38 @@ export default gensync<[any], ResolvedConfig | null>(function* loadFullConfig(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
)(presetsDescriptors, pluginDescriptorsByPass[0]);
|
||||||
|
|
||||||
// resolve plugins
|
if (ignored) return null;
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
return desc;
|
|
||||||
}),
|
|
||||||
presets: presets.map(item => {
|
|
||||||
const desc = getItemDescriptor(item);
|
|
||||||
if (!desc) {
|
|
||||||
throw new Error("Assertion failure - must be config item");
|
|
||||||
}
|
|
||||||
|
|
||||||
return desc;
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
passes[0],
|
|
||||||
);
|
|
||||||
|
|
||||||
if (ignored) return null;
|
|
||||||
} 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.
|
|
||||||
if (!/^\[BABEL\]/.test(e.message)) {
|
|
||||||
e.message = `[BABEL] ${context.filename || "unknown"}: ${e.message}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
const opts: Object = optionDefaults;
|
const opts: Object = optionDefaults;
|
||||||
mergeOptions(opts, options);
|
mergeOptions(opts, options);
|
||||||
|
|
||||||
|
yield* enhanceError(context, function* loadPluginDescriptors() {
|
||||||
|
pluginDescriptorsByPass[0].unshift(...initialPluginsDescriptors);
|
||||||
|
|
||||||
|
for (const descs of pluginDescriptorsByPass) {
|
||||||
|
const pass = [];
|
||||||
|
passes.push(pass);
|
||||||
|
|
||||||
|
for (let i = 0; i < descs.length; i++) {
|
||||||
|
const descriptor: UnloadedDescriptor = 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
opts.plugins = passes[0];
|
opts.plugins = passes[0];
|
||||||
opts.presets = passes
|
opts.presets = passes
|
||||||
.slice(1)
|
.slice(1)
|
||||||
@ -209,6 +198,22 @@ export default gensync<[any], ResolvedConfig | null>(function* loadFullConfig(
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function enhanceError<T: Function>(context, fn: T): T {
|
||||||
|
return (function* (arg1, arg2) {
|
||||||
|
try {
|
||||||
|
return yield* fn(arg1, arg2);
|
||||||
|
} 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.
|
||||||
|
if (!/^\[BABEL\]/.test(e.message)) {
|
||||||
|
e.message = `[BABEL] ${context.filename || "unknown"}: ${e.message}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}: any);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a generic plugin/preset from the given descriptor loaded from the config object.
|
* Load a generic plugin/preset from the given descriptor loaded from the config object.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -454,12 +454,16 @@ function assertOverridesList(loc: OptionPath, value: mixed): OverridesList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function checkNoUnwrappedItemOptionPairs(
|
export function checkNoUnwrappedItemOptionPairs(
|
||||||
lastItem: UnloadedDescriptor,
|
items: Array<UnloadedDescriptor>,
|
||||||
thisItem: UnloadedDescriptor,
|
|
||||||
type: "plugin" | "preset",
|
|
||||||
index: number,
|
index: number,
|
||||||
|
type: "plugin" | "preset",
|
||||||
e: Error,
|
e: Error,
|
||||||
): void {
|
): void {
|
||||||
|
if (index === 0) return;
|
||||||
|
|
||||||
|
const lastItem = items[index - 1];
|
||||||
|
const thisItem = items[index];
|
||||||
|
|
||||||
if (
|
if (
|
||||||
lastItem.file &&
|
lastItem.file &&
|
||||||
lastItem.options === undefined &&
|
lastItem.options === undefined &&
|
||||||
|
|||||||
@ -423,6 +423,8 @@ describe("api", function () {
|
|||||||
"argone;",
|
"argone;",
|
||||||
"five;",
|
"five;",
|
||||||
"six;",
|
"six;",
|
||||||
|
"twentyone;",
|
||||||
|
"twentytwo;",
|
||||||
"three;",
|
"three;",
|
||||||
"four;",
|
"four;",
|
||||||
"nineteen;",
|
"nineteen;",
|
||||||
|
|||||||
@ -14,6 +14,12 @@
|
|||||||
"./five",
|
"./five",
|
||||||
"./six",
|
"./six",
|
||||||
],
|
],
|
||||||
|
presets: [{
|
||||||
|
plugins: [
|
||||||
|
"./twentyone",
|
||||||
|
"./twentytwo",
|
||||||
|
]
|
||||||
|
}]
|
||||||
}, {
|
}, {
|
||||||
passPerPreset: true,
|
passPerPreset: true,
|
||||||
presets: [{
|
presets: [{
|
||||||
|
|||||||
1
packages/babel-core/test/fixtures/config/complex-plugin-config/twentyone.js
vendored
Normal file
1
packages/babel-core/test/fixtures/config/complex-plugin-config/twentyone.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
module.exports = require("./plugin")("twentyone");
|
||||||
1
packages/babel-core/test/fixtures/config/complex-plugin-config/twentytwo.js
vendored
Normal file
1
packages/babel-core/test/fixtures/config/complex-plugin-config/twentytwo.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
module.exports = require("./plugin")("twentytwo");
|
||||||
Loading…
x
Reference in New Issue
Block a user