Skip to content

Commit

Permalink
align modules filters of core-js-builder and core-js-compat
Browse files Browse the repository at this point in the history
  • Loading branch information
zloirock committed Apr 11, 2022
1 parent 3cad08a commit 551a129
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 66 deletions.
6 changes: 3 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
- `null` and `undefined` allowed as the second argument of `structuredClone`, [#1056](https://github.com/zloirock/core-js/issues/1056)
- Tooling:
- Stabilized proposals are filtered out from the `core-js-compat` -> `core-js-builder` -> `core-js-bundle` output. That mean that if the output contains, for example, `es.object.has-own`, the legacy reference to it, `esnext.object.has-own`, no longer added.
- `modules` option of `core-js-compat` replaces `filter` for consistency with `core-js-builder`
- Added support of entry points, arrays of them and arrays of regex to modules filter of `core-js-compat`, [see the docs](https://github.com/zloirock/core-js/tree/master/packages/core-js-builder)
- Missed `targets` option in `core-js-compat` means that the `targets` filter just will not be applied, so the result will contain modules required for all possible engines
- Aligned modules filters of [`core-js-builder`](https://github.com/zloirock/core-js/tree/master/packages/core-js-builder) and [`core-js-compat`](https://github.com/zloirock/core-js/tree/master/packages/core-js-compat), now it's `modules` and `exclude` options
- Added support of entry points, modules, regexes and arrays of them to those filters
- Missed `targets` option of `core-js-compat` means that the `targets` filter just will not be applied, so the result will contain modules required for all possible engines
- Compat data:
- `.stack` property on `DOMException` marked as supported from Deno [1.15](https://github.com/denoland/deno/releases/tag/v1.15.0)
- Added Deno 1.21 compat data mapping
Expand Down
16 changes: 8 additions & 8 deletions packages/core-js-builder/README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
![logo](https://user-images.githubusercontent.com/2213682/146607186-8e13ddef-26a4-4ebf-befd-5aac9d77c090.png)

For some cases could be useful to exclude some `core-js` features or generate a polyfill for target engines. This API helps conditionally include or exclude certain parts of [`core-js`](https://github.com/zloirock/core-js), build for targets [specified in `core-js-compat` format](https://github.com/zloirock/core-js/tree/master/packages/core-js-compat#targets-option).
For some cases could be useful to exclude some `core-js` features or generate a polyfill for target engines. This API helps conditionally include or exclude certain parts of [`core-js`](https://github.com/zloirock/core-js) and build for targets. `modules`, `exclude` and `targets` options are specified in [the `core-js-compat` format](https://github.com/zloirock/core-js/tree/master/packages/core-js-compat).

```js
const builder = require('core-js-builder');

const bundle = await builder({
modules: ['es', 'esnext.reflect', 'web'], // modules / namespaces, by default - all `core-js` modules
exclude: ['es.math', 'es.number.constructor'], // a blacklist of modules / namespaces, by default - empty list
targets: '> 0.5%, not dead, ie 9-11', // optional browserslist or core-js-compat format query
summary: { // shows summary for the bundle, disabled by default:
console: { size: true, modules: false }, // in the console, you could specify required parts or set `true` for enable all of them
comment: { size: false, modules: true }, // in the comment in the target file, similarly to `summary.console`
modules: ['core-js/actual', 'esnext.reflect'], // entries / modules / namespaces, by default - all `core-js` modules
exclude: [/^es\.math\./, 'es.number.constructor'], // a blacklist of entries / modules / namespaces, by default - empty list
targets: '> 0.5%, not dead, ie 9-11', // optional browserslist or core-js-compat format query
summary: { // shows summary for the bundle, disabled by default:
console: { size: true, modules: false }, // in the console, you could specify required parts or set `true` for enable all of them
comment: { size: false, modules: true }, // in the comment in the target file, similarly to `summary.console`
},
filename: './my-core-js-bundle.js', // optional target filename, if it's missed a file will not be created
filename: PATH_TO_MY_COREJS_BUNDLE, // optional target filename, if it's missed a file will not be created
});
```
43 changes: 9 additions & 34 deletions packages/core-js-builder/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use strict';
/* eslint-disable no-console -- output */
const { promisify } = require('util');
const fs = require('fs');
// TODO: replace by `fs.promises` after dropping NodeJS < 10 support
Expand All @@ -11,8 +12,6 @@ const tmpdir = require('os').tmpdir();
const mkdirp = promisify(require('mkdirp'));
const webpack = promisify(require('webpack'));
const compat = require('core-js-compat/compat');
const modulesList = require('core-js-compat/modules');
const { filterOutStabilizedProposals } = require('core-js-compat/helpers');
const { banner } = require('./config');

function normalizeSummary(unit = {}) {
Expand All @@ -26,7 +25,7 @@ function normalizeSummary(unit = {}) {
}

module.exports = async function ({
modules = modulesList.slice(),
modules = null,
blacklist = null, // TODO: Obsolete, remove from `core-js@4`
exclude = [],
targets = null,
Expand All @@ -36,35 +35,12 @@ module.exports = async function ({
summary = { comment: normalizeSummary(summary.comment), console: normalizeSummary(summary.console) };

const TITLE = filename != null ? filename : '`core-js`';
const set = new Set();
let script = banner;
let code = '';
let modulesWithTargets;

function filter(method, list) {
for (const ns of list) {
for (const name of modulesList) {
if (name === ns || name.startsWith(`${ ns }.`)) {
// eslint-disable-next-line sonarjs/no-empty-collection -- false positive
set[method](name);
}
}
}
}

filter('add', modules);
filter('delete', exclude == null ? blacklist : exclude);

// eslint-disable-next-line sonarjs/no-empty-collection -- false positive
modules = filterOutStabilizedProposals(modulesList.filter(it => set.has(it)));
const { list, targets: compatTargets } = compat({ targets, modules, exclude: exclude || blacklist });

if (targets) {
const compatResult = compat({ targets, modules });
modules = compatResult.list;
modulesWithTargets = compatResult.targets;
}

if (modules.length) {
if (list.length) {
const tempFileName = `core-js-${ Math.random().toString(36).slice(2) }.js`;
const tempFile = join(tmpdir, tempFileName);

Expand All @@ -75,7 +51,7 @@ module.exports = async function ({
process: false,
setImmediate: false,
},
entry: modules.map(it => require.resolve(`core-js/modules/${ it }`)),
entry: list.map(it => require.resolve(`core-js/modules/${ it }`)),
output: {
filename: tempFileName,
hashFunction: 'md5',
Expand All @@ -94,21 +70,20 @@ module.exports = async function ({
}

if (summary.comment.size) script += `/*\n * size: ${ (code.length / 1024).toFixed(2) }KB w/o comments\n */`;
if (summary.comment.modules) script += `/*\n * modules:\n${ modules.map(it => ` * ${ it }\n`).join('') } */`;
if (summary.comment.modules) script += `/*\n * modules:\n${ list.map(it => ` * ${ it }\n`).join('') } */`;
if (code) script += `\n${ code }`;

if (summary.console.size) {
// eslint-disable-next-line no-console -- output
console.log(`\u001B[32mbundling \u001B[36m${ TITLE }\u001B[32m, size: \u001B[36m${
(script.length / 1024).toFixed(2)
}KB\u001B[0m`);
}

if (summary.console.modules) {
// eslint-disable-next-line no-console -- output
console.log(`\u001B[32mbundling \u001B[36m${ TITLE }\u001B[32m, modules:\u001B[0m`);
// eslint-disable-next-line no-console -- output
console.log(JSON.stringify(modulesWithTargets || modules, null, ' '));
for (const it of list) {
console.log(`\u001B[36m${ it + (targets ? ` \u001B[32mfor \u001B[36m${ JSON.stringify(compatTargets[it]) }` : '') }\u001B[0m`);
}
}

if (filename != null) {
Expand Down
7 changes: 4 additions & 3 deletions packages/core-js-compat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ const {
targets, // object with targets for each module
} = require('core-js-compat')({
targets: '> 1%', // browserslist query or object of minimum environment versions to support, see below
modules: [ // optional modules list / filter - regex, sting or an array of them:
modules: [ // optional list / filter of modules - regex, sting or an array of them:
'core-js/actual', // - an entry point
'esnext.array.unique-by', // - a module name (or just a start of a module name)
/^web\./, // - regex that a module name must satisfy
],
exclude: [ // optional list / filter of modules to exclude, the signature is similar to `modules` option
'web.atob',
],
version: '3.21', // used `core-js` version, by default - the latest
});

Expand All @@ -35,10 +38,8 @@ console.log(targets);
'esnext.array.to-spliced': { chrome: '98', edge: '99', firefox: '98', ios: '14.5-14.8', samsung: '16.0' },
'esnext.array.unique-by': { chrome: '98', edge: '99', firefox: '98', ios: '14.5-14.8', samsung: '16.0' },
'esnext.array.with': { chrome: '98', edge: '99', firefox: '98', ios: '14.5-14.8', samsung: '16.0' },
'esnext.symbol.replace-all': { chrome: '98', edge: '99', firefox: '98', ios: '14.5-14.8', samsung: '16.0' },
'esnext.typed-array.find-last': { firefox: '98', ios: '14.5-14.8', samsung: '16.0' },
'esnext.typed-array.find-last-index': { firefox: '98', ios: '14.5-14.8', samsung: '16.0' },
'esnext.typed-array.group-by': { chrome: '98', edge: '99', firefox: '98', ios: '14.5-14.8', samsung: '16.0' },
'esnext.typed-array.to-reversed': { chrome: '98', edge: '99', firefox: '98', ios: '14.5-14.8', samsung: '16.0' },
'esnext.typed-array.to-sorted': { chrome: '98', edge: '99', firefox: '98', ios: '14.5-14.8', samsung: '16.0' },
'esnext.typed-array.to-spliced': { chrome: '98', edge: '99', firefox: '98', ios: '14.5-14.8', samsung: '16.0' },
Expand Down
38 changes: 20 additions & 18 deletions packages/core-js-compat/compat.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,21 @@ function getModules(filter) {
throw TypeError('Wrong filter!');
}

function checkModule(name, targets) {
if (!has(data, name)) throw new TypeError(`Incorrect module: ${ name }`);
function normalizeModules(option) {
// TODO: use `.flatMap` in core-js@4
return new Set(Array.isArray(option) ? [].concat.apply([], option.map(getModules)) : getModules(option));
}

const requirements = data[name];
function checkModule(name, targets) {
const result = {
required: false,
required: !targets,
targets: {},
};

if (!targets) return result;

const requirements = data[name];

for (const [engine, version] of targets) {
if (!has(requirements, engine) || compare(version, '<', requirements[engine])) {
result.required = true;
Expand All @@ -36,6 +42,7 @@ function checkModule(name, targets) {
module.exports = function ({
filter = null, // TODO: Obsolete, remove from `core-js@4`
modules = null,
exclude = [],
targets = null,
version = null,
} = {}) {
Expand All @@ -48,23 +55,18 @@ module.exports = function ({
targets: {},
};

let $modules;
if (modules) {
const list = Array.isArray(modules) ? modules : [modules];
$modules = [...new Set([].concat.apply([], list.map(getModules)))];
} else $modules = allModules;
exclude = normalizeModules(exclude);

if (version) {
$modules = intersection($modules, getModulesListForTargetVersion(version));
}
modules = modules ? [...normalizeModules(modules)] : allModules;

if (exclude.size) modules = modules.filter(it => !exclude.has(it));

modules = intersection(modules, version ? getModulesListForTargetVersion(version) : allModules);

$modules = filterOutStabilizedProposals($modules);
modules = filterOutStabilizedProposals(modules);

for (const key of $modules) {
const check = parsedTargets ? checkModule(key, parsedTargets) : {
required: true,
targets: {},
};
for (const key of modules) {
const check = checkModule(key, parsedTargets);

if (check.required) {
result.list.push(key);
Expand Down

0 comments on commit 551a129

Please sign in to comment.