Use Sets for polyfills and transformations (#274)

This commit is contained in:
Brian Ng 2017-04-14 13:07:05 -05:00 committed by GitHub
parent 64cfc43883
commit 2c5ff923d1
4 changed files with 81 additions and 64 deletions

View File

@ -69,15 +69,6 @@ const logPlugin = (plugin, targets, list) => {
console.log(logStr);
};
const filterItem = (targets, exclusions, list, item) => {
const isDefault = defaultWebIncludes.indexOf(item) >= 0;
const notExcluded = exclusions.indexOf(item) === -1;
if (isDefault) return notExcluded;
const isRequired = isPluginRequired(targets, list[item]);
return isRequired && notExcluded;
};
const getBuiltInTargets = targets => {
const builtInTargets = Object.assign({}, targets);
if (builtInTargets.uglify != null) {
@ -86,19 +77,48 @@ const getBuiltInTargets = targets => {
return builtInTargets;
};
export const transformIncludesAndExcludes = opts => ({
all: opts,
plugins: opts.filter(opt => !opt.match(/^(es\d+|web)\./)),
builtIns: opts.filter(opt => opt.match(/^(es\d+|web)\./)),
});
export const transformIncludesAndExcludes = opts => {
return opts.reduce(
(result, opt) => {
const target = opt.match(/^(es\d+|web)\./) ? "builtIns" : "plugins";
result[target].add(opt);
return result;
},
{
all: opts,
plugins: new Set(),
builtIns: new Set(),
},
);
};
function getPlatformSpecificDefaultFor(targets) {
const getPlatformSpecificDefaultFor = targets => {
const targetNames = Object.keys(targets);
const isAnyTarget = !targetNames.length;
const isWebTarget = targetNames.some(name => name !== "node");
return isAnyTarget || isWebTarget ? defaultWebIncludes : [];
}
return isAnyTarget || isWebTarget ? defaultWebIncludes : null;
};
const filterItems = (list, includes, excludes, targets, defaultItems) => {
const result = new Set();
for (const item in list) {
const excluded = excludes.has(item);
if (!excluded && isPluginRequired(targets, list[item])) {
result.add(item);
}
}
if (defaultItems) {
defaultItems.forEach(item => !excludes.has(item) && result.add(item));
}
includes.forEach(item => result.add(item));
return result;
};
export default function buildPreset(context, opts = {}) {
const validatedOptions = normalizeOptions(opts);
@ -108,30 +128,26 @@ export default function buildPreset(context, opts = {}) {
const include = transformIncludesAndExcludes(validatedOptions.include);
const exclude = transformIncludesAndExcludes(validatedOptions.exclude);
const filterPlugins = filterItem.bind(
null,
targets,
exclude.plugins,
const transformations = filterItems(
pluginList,
include.plugins,
exclude.plugins,
targets,
);
const transformations = Object.keys(pluginList)
.filter(filterPlugins)
.concat(include.plugins);
let polyfills;
let polyfillTargets;
if (useBuiltIns) {
polyfillTargets = getBuiltInTargets(targets);
const filterBuiltIns = filterItem.bind(
null,
polyfillTargets,
exclude.builtIns,
polyfills = filterItems(
builtInsList,
include.builtIns,
exclude.builtIns,
polyfillTargets,
getPlatformSpecificDefaultFor(polyfillTargets),
);
polyfills = Object.keys(builtInsList)
.concat(getPlatformSpecificDefaultFor(polyfillTargets))
.filter(filterBuiltIns)
.concat(include.builtIns);
}
if (debug && !hasBeenLogged) {
@ -146,20 +162,19 @@ export default function buildPreset(context, opts = {}) {
});
}
const regenerator = transformations.indexOf("transform-regenerator") >= 0;
const modulePlugin = moduleType !== false &&
moduleTransformations[moduleType];
const plugins = [];
modulePlugin &&
plugins.push([require(`babel-plugin-${modulePlugin}`), { loose }]);
plugins.push(
...transformations.map(pluginName => [
require(`babel-plugin-${pluginName}`),
if (moduleType !== false && moduleTransformations[moduleType]) {
plugins.push([
require(`babel-plugin-${moduleTransformations[moduleType]}`),
{ loose },
]),
);
]);
}
transformations.forEach(pluginName =>
plugins.push([require(`babel-plugin-${pluginName}`), { loose }]));
const regenerator = transformations.has("transform-regenerator");
if (debug) {
console.log("");
@ -171,7 +186,11 @@ export default function buildPreset(context, opts = {}) {
if (useBuiltIns === "usage") {
plugins.push([
addUsedBuiltInsPlugin,
{ polyfills: new Set(polyfills), regenerator, debug },
{
debug,
polyfills,
regenerator,
},
]);
} else if (useBuiltIns === "entry") {
plugins.push([

View File

@ -4,12 +4,12 @@ import { defaultWebIncludes } from "./default-includes";
import moduleTransformations from "./module-transformations";
import pluginFeatures from "../data/plugin-features";
const validIncludesAndExcludes = [
const validIncludesAndExcludes = new Set([
...Object.keys(pluginFeatures),
...Object.keys(moduleTransformations).map(m => moduleTransformations[m]),
...Object.keys(builtInsList),
...defaultWebIncludes,
];
]);
export const validateIncludesAndExcludes = (opts = [], type) => {
invariant(
@ -17,12 +17,7 @@ export const validateIncludesAndExcludes = (opts = [], type) => {
`Invalid Option: The '${type}' option must be an Array<String> of plugins/built-ins`,
);
const unknownOpts = [];
opts.forEach(opt => {
if (validIncludesAndExcludes.indexOf(opt) === -1) {
unknownOpts.push(opt);
}
});
const unknownOpts = opts.filter(opt => !validIncludesAndExcludes.has(opt));
invariant(
unknownOpts.length === 0,

View File

@ -38,18 +38,21 @@ export default function({ types: t }) {
}
function createImports(polyfills, requireType, regenerator) {
const imports = polyfills
.filter((el, i, arr) => arr.indexOf(el) === i)
.map(polyfill => createImport(polyfill, requireType, true));
const items = Array.isArray(polyfills) ? new Set(polyfills) : polyfills;
const imports = [];
return [
...imports,
regenerator &&
items.forEach(p => imports.push(createImport(p, requireType, true)));
if (regenerator) {
imports.push(
createImport(
"babel-polyfill/lib/regenerator-runtime/runtime",
requireType,
),
].filter(Boolean);
);
}
return imports;
}
const isPolyfillImport = {
@ -88,7 +91,7 @@ export default function({ types: t }) {
const { debug, onDebug, polyfills } = this.opts;
if (debug) {
if (!polyfills.length) {
if (!polyfills.size) {
console.log("Based on your targets, none were added.");
return;
}

View File

@ -123,8 +123,8 @@ describe("babel-preset-env", () => {
]),
{
all: ["transform-es2015-arrow-functions"],
plugins: ["transform-es2015-arrow-functions"],
builtIns: [],
plugins: new Set(["transform-es2015-arrow-functions"]),
builtIns: new Set(),
},
);
});
@ -134,8 +134,8 @@ describe("babel-preset-env", () => {
babelPresetEnv.transformIncludesAndExcludes(["es6.map"]),
{
all: ["es6.map"],
plugins: [],
builtIns: ["es6.map"],
plugins: new Set(),
builtIns: new Set(["es6.map"]),
},
);
});