move compat method logic to core-js-compat/compat

This commit is contained in:
Denis Pushkarev
2019-12-05 00:16:04 +07:00
parent 07b0779898
commit a6d41a665b
4 changed files with 140 additions and 94 deletions
+24
View File
@@ -40,4 +40,28 @@ console.log(targets);
*/
```
Additional API:
```js
// full compat data:
require('core-js-compat/data'); // => { [ModuleName]: { [EngineName]: EngineVersion } }
// or
require('core-js-compat').data; // => { [ModuleName]: { [EngineName]: EngineVersion } }
// map of modules by `core-js` entry points:
require('core-js-compat/entries'); // => { [EntryPoint]: Array<ModuleName> }
// or
require('core-js-compat').entries; // => { [EntryPoint]: Array<ModuleName> }
// full list of modules:
require('core-js-compat/modules'); // => Array<ModuleName>
// or
require('core-js-compat').modules; // => Array<ModuleName>
// list of modules for passed `core-js` version:
require('core-js-compat/get-modules-list-for-target-version')('3.3'); // => Array<ModuleName>
// or
require('core-js-compat').getModulesListForTargetVersion('3.3'); // => Array<ModuleName>
```
If you want to add new / update data about modules required for target engines, [follow this instruction](https://github.com/zloirock/core-js/blob/master/CONTRIBUTING.md#updating-core-js-compat-data).
+102
View File
@@ -0,0 +1,102 @@
'use strict';
const browserslist = require('browserslist');
const { compare, has, intersection } = require('./helpers');
const data = require('./data');
const getModulesListForTargetVersion = require('./get-modules-list-for-target-version');
const modules = require('./modules');
const mapping = new Map([
['and_chr', 'chrome'],
['and_ff', 'firefox'],
['ie_mob', 'ie'],
['ios_saf', 'ios'],
]);
const validTargets = new Set([
'android',
'chrome',
'edge',
'electron',
'firefox',
'ie',
'ios',
'node',
'opera',
'phantom',
'safari',
'samsung',
]);
function normalizeBrowsersList(list) {
return list.map(it => {
let [engine, version] = it.split(' ');
if (mapping.has(engine)) {
engine = mapping.get(engine);
} else if (engine === 'android' && compare(version, '>', '4.4.4')) {
engine = 'chrome';
}
return [engine, version];
}).filter(([engine]) => validTargets.has(engine));
}
function reduceByMinVersion(list) {
const targets = new Map();
for (const [engine, version] of list) {
if (!targets.has(engine) || compare(version, '<=', targets.get(engine))) {
targets.set(engine, version);
}
}
return targets;
}
function checkModule(name, targets) {
if (!has(data, name)) throw new TypeError(`Incorrect module: ${ name }`);
const requirements = data[name];
const result = {
required: false,
targets: {},
};
for (const [engine, version] of targets) {
if (!has(requirements, engine) || compare(version, '<', requirements[engine])) {
result.required = true;
result.targets[engine] = version;
}
}
return result;
}
module.exports = function ({ targets, filter, version }) {
const list = browserslist(targets);
const engines = normalizeBrowsersList(list);
const reducedTargets = reduceByMinVersion(engines);
const result = {
list: [],
targets: {},
};
let $modules = Array.isArray(filter) ? filter : modules;
if (filter instanceof RegExp) {
$modules = $modules.filter(it => filter.test(it));
} else if (typeof filter == 'string') {
$modules = $modules.filter(it => it.startsWith(filter));
}
if (version) {
$modules = intersection($modules, getModulesListForTargetVersion(version));
}
for (const key of $modules) {
const check = checkModule(key, reducedTargets);
if (check.required) {
result.list.push(key);
result.targets[key] = check.targets;
}
}
return result;
};
+4 -1
View File
@@ -1,17 +1,20 @@
'use strict';
const { coerce: semver, cmp } = require('semver');
const has = Function.call.bind({}.hasOwnProperty);
function compare(a, operator, b) {
return cmp(semver(a), operator, semver(b));
}
function intersection(list, order) {
const set = new Set(list);
const set = list instanceof Set ? list : new Set(list);
return order.filter(name => set.has(name));
}
module.exports = {
compare,
has,
intersection,
semver,
};
+10 -93
View File
@@ -1,97 +1,14 @@
'use strict';
const browserslist = require('browserslist');
const { compare, intersection } = require('./helpers');
const compat = require('./compat');
const data = require('./data');
const entries = require('./entries');
const getModulesListForTargetVersion = require('./get-modules-list-for-target-version');
const has = Function.call.bind({}.hasOwnProperty);
const modules = require('./modules');
const mapping = new Map([
['and_chr', 'chrome'],
['and_ff', 'firefox'],
['ie_mob', 'ie'],
['ios_saf', 'ios'],
]);
const validTargets = new Set([
'android',
'chrome',
'edge',
'electron',
'firefox',
'ie',
'ios',
'node',
'opera',
'phantom',
'safari',
'samsung',
]);
function normalizeBrowsersList(list) {
return list.map(it => {
let [engine, version] = it.split(' ');
if (mapping.has(engine)) engine = mapping.get(engine);
else if (engine === 'android' && compare(version, '>', '4.4.4')) engine = 'chrome';
return [engine, version];
}).filter(([engine]) => validTargets.has(engine));
}
function reduceByMinVersion(list) {
const targets = new Map();
for (const [engine, version] of list) {
if (!targets.has(engine) || compare(version, '<=', targets.get(engine))) {
targets.set(engine, version);
}
}
return targets;
}
function checkModule(name, targets) {
if (!has(data, name)) throw new TypeError(`Incorrect module: ${ name }`);
const requirements = data[name];
const result = {
required: false,
targets: {},
};
for (const [engine, version] of targets) {
if (!has(requirements, engine) || compare(version, '<', requirements[engine])) {
result.required = true;
result.targets[engine] = version;
}
}
return result;
}
function compat({ targets, filter, version }) {
const list = browserslist(targets);
const engines = normalizeBrowsersList(list);
const reducedTargets = reduceByMinVersion(engines);
const result = {
list: [],
targets: {},
};
let modules = Array.isArray(filter) ? filter : Object.keys(data);
if (filter instanceof RegExp) modules = modules.filter(it => filter.test(it));
else if (typeof filter == 'string') modules = modules.filter(it => it.startsWith(filter));
if (version) {
modules = intersection(modules, getModulesListForTargetVersion(version));
}
modules.forEach(key => {
const check = checkModule(key, reducedTargets);
if (check.required) {
result.list.push(key);
result.targets[key] = check.targets;
}
});
return result;
}
module.exports = compat;
module.exports.compat = compat;
module.exports.getModulesListForTargetVersion = getModulesListForTargetVersion;
module.exports = Object.assign(compat, {
compat,
data,
entries,
getModulesListForTargetVersion,
modules,
});