webpack/lib/config/browserslistTargetHandler.js

98 lines
2.3 KiB
JavaScript
Raw Normal View History

2020-09-24 19:33:09 +08:00
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Sergey Melyukov @smelukov
*/
2020-09-24 19:42:27 +08:00
"use strict";
2020-09-24 19:33:09 +08:00
const browserslist = require("browserslist");
// ?query|[///path/to/config][:env]
const inputRx = /^(?:\?(.+?)|(?:\/\/(.+?))?(?::(.+?))?)$/;
2020-09-24 19:33:09 +08:00
/**
* @typedef {Object} BrowserslistHandlerConfig
* @property {string} [configPath]
* @property {string} [env]
* @property {string} [query]
*/
/**
* @param {BrowserslistHandlerConfig|null} handlerConfig config
* @returns {import("./target").EcmaTargetProperties} es features
*/
const resolve = handlerConfig => {
const { configPath, env, query } = handlerConfig || {};
2020-09-24 19:33:09 +08:00
// if a query is specified, then use it, else
// if a path to a config is specified then load it, else
// find a nearest config
const config = query
? query
: configPath
? browserslist.loadConfig({
2020-09-24 19:33:09 +08:00
config: configPath,
env
})
: browserslist.loadConfig({ path: process.cwd(), env });
2020-09-24 19:33:09 +08:00
const browsers = browserslist(config);
const checker = createChecker(browsers);
2020-09-24 19:33:09 +08:00
return resolveESFeatures(checker);
};
/**
* @param {string} input input string
* @returns {BrowserslistHandlerConfig|null} config
*/
const parse = input => {
if (!input) {
return null;
}
const [, query, configPath, env] = inputRx.exec(input) || [];
2020-09-24 19:33:09 +08:00
return { query, configPath, env };
2020-09-24 19:33:09 +08:00
};
/**
* @param {function(string): boolean} checker checker function
* @returns {import("./target").EcmaTargetProperties} es features
*/
const resolveESFeatures = checker => {
return {
const: checker("es6"),
arrowFunction: checker("es6"),
forOf: checker("es6"),
destructuring: checker("es6"),
bigIntLiteral: checker("bigint"),
module: checker("es6-module"),
dynamicImport: checker("es6-module-dynamic-import"),
dynamicImportInWorker: checker("es6-module-dynamic-import"),
// browserslist does not have info about globalThis
globalThis: undefined
};
};
/**
* Create browserslist checker
* @param {string[]} browsers supported browsers list
* @returns {function(string):boolean} checker
*/
const createChecker = browsers => {
2020-09-24 19:33:09 +08:00
/**
* @param {string} feature an ES feature to test
* @returns {boolean} true if supports
*/
return feature => {
const supportsFeature = browserslist(`supports ${feature}`);
return browsers.every(v => supportsFeature.includes(v));
};
};
module.exports = {
resolve,
parse
};