diff --git a/experimental/babel-preset-env/data/pluginFeatures.js b/experimental/babel-preset-env/data/pluginFeatures.js new file mode 100644 index 000000000000..b5037d9888dc --- /dev/null +++ b/experimental/babel-preset-env/data/pluginFeatures.js @@ -0,0 +1,126 @@ +/* eslint-disable quotes */ +module.exports = { + // es2015 + "transform-es2015-arrow-functions": { + features: [ + "arrow functions", + ], + }, + "transform-es2015-block-scoped-functions": { + features: [ + "block-level function declaration" + ], + }, + "transform-es2015-block-scoping": { + features: [ + "const", + "let", + ], + }, + "transform-es2015-classes": { + features: [ + "class", + "super", + ], + }, + "transform-es2015-computed-properties": { + features: [ + "object literal extensions / computed properties", + ], + }, + "check-es2015-constants": { + features: [ + "const", + ], + }, + "transform-es2015-destructuring": { + features: [ + "destructuring, assignment", + "destructuring, declarations", + "destructuring, parameters", + ], + }, + "transform-es2015-for-of": { + features: [ + "for..of loops", + ], + }, + "transform-es2015-function-name": { + features: [ + 'function "name" property', + ] + }, + "transform-es2015-literals": { + features: [ + "Unicode code point escapes", + ], + }, + "transform-es2015-object-super": { + features: [ + "super", + ], + }, + "transform-es2015-parameters": { + features: [ + "default function parameters", + "rest parameters", + ], + }, + "transform-es2015-shorthand-properties": { + features: [ + "object literal extensions / shorthand properties", + ], + }, + "transform-es2015-spread": { + features: [ + "spread (...) operator", + ], + }, + "transform-es2015-sticky-regex": { + features: [ + 'RegExp "y" and "u" flags / "y" flag, lastIndex', + 'RegExp "y" and "u" flags / "y" flag', + ], + }, + "transform-es2015-template-literals": { + features: [ + "template literals", + ], + }, + "transform-es2015-typeof-symbol": { + features: [ + "Symbol / typeof support" + ], + }, + "transform-es2015-unicode-regex": { + features: [ + 'RegExp "y" and "u" flags / "u" flag, case folding', + 'RegExp "y" and "u" flags / "u" flag, Unicode code point escapes', + 'RegExp "y" and "u" flags / "u" flag', + ], + }, + "transform-regenerator": { + features: [ + "generators", + ], + }, + + // es2016 + "transform-exponentiation-operator": { + features: [ + "exponentiation (**) operator", + ], + }, + + // es2017 + "transform-async-to-generator": { + features: [ + "async functions", + ], + }, + "syntax-trailing-function-commas": { + features: [ + "trailing commas in function syntax", + ], + } +}; diff --git a/experimental/babel-preset-env/data/plugins.json b/experimental/babel-preset-env/data/plugins.json new file mode 100644 index 000000000000..5dd10b0ffa3c --- /dev/null +++ b/experimental/babel-preset-env/data/plugins.json @@ -0,0 +1,117 @@ +{ + "transform-es2015-arrow-functions": { + "chrome": 47, + "edge": 13, + "firefox": 45, + "safari": 10 + }, + "transform-es2015-block-scoped-functions": { + "chrome": 41, + "firefox": 46, + "safari": 10 + }, + "transform-es2015-block-scoping": { + "chrome": 49, + "firefox": 51, + "safari": 10 + }, + "transform-es2015-classes": { + "chrome": 46, + "edge": 13, + "firefox": 45, + "safari": 10 + }, + "transform-es2015-computed-properties": { + "chrome": 44, + "edge": 12, + "firefox": 34, + "safari": 10 + }, + "check-es2015-constants": { + "chrome": 49, + "firefox": 51, + "safari": 10 + }, + "transform-es2015-destructuring": { + "chrome": 51, + "edge": 14, + "safari": 10 + }, + "transform-es2015-for-of": { + "chrome": 51, + "edge": 14, + "safari": 10 + }, + "transform-es2015-function-name": { + "chrome": 51, + "safari": 10 + }, + "transform-es2015-literals": { + "chrome": 44, + "edge": 12, + "safari": 9 + }, + "transform-es2015-object-super": { + "chrome": 46, + "edge": 13, + "firefox": 45, + "safari": 10 + }, + "transform-es2015-parameters": { + "chrome": 49, + "edge": 14, + "safari": 10 + }, + "transform-es2015-shorthand-properties": { + "chrome": 43, + "edge": 12, + "firefox": 33, + "safari": 9 + }, + "transform-es2015-spread": { + "chrome": 46, + "edge": 13, + "firefox": 36, + "safari": 10 + }, + "transform-es2015-sticky-regex": { + "chrome": 49, + "edge": 13, + "firefox": 3, + "safari": 10 + }, + "transform-es2015-template-literals": { + "chrome": 41, + "edge": 13, + "firefox": 34, + "safari": 9 + }, + "transform-es2015-typeof-symbol": { + "chrome": 38, + "edge": 12, + "firefox": 36, + "safari": 9 + }, + "transform-es2015-unicode-regex": { + "chrome": 50, + "edge": 13, + "firefox": 46, + "safari": 10 + }, + "transform-regenerator": { + "chrome": 50, + "edge": 13, + "safari": 10 + }, + "transform-exponentiation-operator": { + "chrome": 52, + "edge": 14 + }, + "transform-async-to-generator": { + "edge": 14 + }, + "syntax-trailing-function-commas": { + "edge": 14, + "safari": 10 + } +} diff --git a/experimental/babel-preset-env/package.json b/experimental/babel-preset-env/package.json index 00614bef27fa..57cda730c7ce 100644 --- a/experimental/babel-preset-env/package.json +++ b/experimental/babel-preset-env/package.json @@ -8,10 +8,11 @@ "repository": "https://github.com/babel/babel-preset-env", "main": "lib/index.js", "scripts": { - "build": "babel src -d lib", + "build": "npm run build-data && babel src -d lib", + "build-data": "node ./scripts/build-data.js", "dev": "babel -w src -d lib", - "lint": "eslint src test", - "fix": "eslint src test --fix", + "lint": "eslint scripts src test", + "fix": "eslint scripts src test --fix", "ci": "npm run lint && npm run test", "prepublish": "npm run build", "test": "mocha ./test --compilers js:babel-register" @@ -61,11 +62,14 @@ "babel-plugin-transform-flow-strip-types": "^6.8.0", "babel-preset-es2015": "^6.14.0", "babel-register": "^6.14.0", + "compat-table": "github:kangax/compat-table#gh-pages", "eslint": "^3.3.1", "eslint-config-babel": "^1.0.1", "eslint-plugin-babel": "^3.3.0", "eslint-plugin-flow-vars": "^0.5.0", - "mocha": "^3.0.2" + "lodash": "^4.15.0", + "mocha": "^3.0.2", + "natural-compare": "^1.4.0" }, "babel": { "presets": [ @@ -81,7 +85,7 @@ "transform-flow-strip-types" ] }, - "eslint": { + "eslintConfig": { "extends": "babel", "parserOptions": { "ecmaVersion": 7, diff --git a/experimental/babel-preset-env/scripts/build-data.js b/experimental/babel-preset-env/scripts/build-data.js new file mode 100644 index 000000000000..28d79edc7465 --- /dev/null +++ b/experimental/babel-preset-env/scripts/build-data.js @@ -0,0 +1,77 @@ +const fs = require("fs"); +const path = require("path"); + +const flatten = require("lodash/flatten"); +const flattenDeep = require("lodash/flattenDeep"); +const naturalCompare = require("natural-compare"); +const pluginFeatures = require("../data/pluginFeatures"); + +const renameTests = (tests, getName) => + tests.map((test) => Object.assign({}, test, { name: getName(test.name) })); + +const compatibilityTests = flattenDeep([ + require("compat-table/data-es6"), + require("compat-table/data-es2016plus"), +].map((data) => + data.tests.map((test) => { + return test.subtests ? + [test, renameTests(test.subtests, (name) => test.name + " / " + name)] : + test; + }) +)); + +const versions = Object.keys(require("compat-table/data-es6").browsers) + .sort(naturalCompare); + +const environments = [ + "chrome", + "edge", + "firefox", + "safari", +]; + +const getLowestImplementedVersion = ({ features }, env) => { + let tests = flatten(compatibilityTests + .filter((test) => features.indexOf(test.name) >= 0) + .map((test) => { + return test.subtests ? + test.subtests.map((subtest) => subtest.res) : + test.res; + }) + ); + + const envVersions = versions.filter((version) => version.startsWith(env)); + + for (let i = 0; i < envVersions.length; i++) { + const version = envVersions[i]; + tests = tests.filter((test) => + test[version] !== true && + test[version] !== "strict" + ); + if (tests.length === 0) { + const number = parseInt(version.replace(env, ""), 10); + return isFinite(number) ? number : null; + } + } + return null; +}; + +const data = {}; +for (const pluginName in pluginFeatures) { + const options = pluginFeatures[pluginName]; + const plugin = {}; + environments.forEach((env) => { + if (Array.isArray(options.features)) { + const version = getLowestImplementedVersion(options, env); + if (version !== null) { + plugin[env] = version; + } + } + }); + data[pluginName] = plugin; +} + +fs.writeFileSync( + path.join(__dirname, "../data/plugins.json"), + JSON.stringify(data, null, 2) + "\n" +); diff --git a/experimental/babel-preset-env/src/index.js b/experimental/babel-preset-env/src/index.js index f9828c308a30..d061ffc31bf2 100644 --- a/experimental/babel-preset-env/src/index.js +++ b/experimental/babel-preset-env/src/index.js @@ -4,7 +4,7 @@ // "proto-to-assign", // "es5-property-mutators", -import pluginList from "./plugins.js"; +import pluginList from "../data/plugins.json"; export const plugins = [ "es3-member-expression-literals", diff --git a/experimental/babel-preset-env/src/plugins.js b/experimental/babel-preset-env/src/plugins.js deleted file mode 100644 index 377f8196cf2f..000000000000 --- a/experimental/babel-preset-env/src/plugins.js +++ /dev/null @@ -1,131 +0,0 @@ -export default { - // es2015 - "transform-es2015-arrow-functions": { - edge: 13, - firefox: 45, - chrome: 49, - opera: 36, - }, - "transform-es2015-block-scoped-functions": { - edge: 11, - firefox: 46, - chrome: 41, - opera: 28, - }, - "transform-es2015-block-scoping": { - edge: 11, - firefox: 36, - chrome: 49, - opera: 36, - }, - "transform-es2015-classes": { - edge: 13, - firefox: 45, - chrome: 49, - opera: 36, - }, - "transform-es2015-computed-properties": { - edge: 12, - firefox: 34, - chrome: 44, - opera: 31 - }, - "check-es2015-constants": { - edge: 11, - firefox: 36, - chrome: 49, - opera: 36, - }, - "transform-es2015-destructuring": { - edge: 14, - firefox: Number.NEGATIVE_INFINITY, - chrome: 52, - opera: 39, - }, - "transform-es2015-for-of": { - edge: Number.NEGATIVE_INFINITY, - firefox: Number.NEGATIVE_INFINITY, - chrome: 51, - opera: 38, - }, - "transform-es2015-function-name": { - edge: Number.NEGATIVE_INFINITY, - firefox: Number.NEGATIVE_INFINITY, - chrome: 52, - opera: 39, - }, - "transform-es2015-literals": { - edge: 12, - firefox: 36, - chrome: 41, - opera: 28 - }, - "transform-es2015-object-super": { - edge: 13, - firefox: 45, - chrome: 49, - opera: 36, - }, - "transform-es2015-parameters": { - edge: 14, - firefox: Number.NEGATIVE_INFINITY, - chrome: 49, - opera: 36, - }, - "transform-es2015-shorthand-properties": { - edge: 12, - firefox: 33, - chrome: 43, - opera: 30 - }, - "transform-es2015-spread": { - edge: 13, - firefox: 36, - chrome: 46, - opera: 33, - }, - "transform-es2015-sticky-regex": { - edge: 13, - firefox: 31, - chrome: 49, - opera: 36 - }, - "transform-es2015-template-literals": { - edge: 13, - firefox: 34, - chrome: 41, - opera: 28, - }, - "transform-es2015-typeof-symbol": { - edge: 12, - firefox: 36, - chrome: 38, - opera: 25, - }, - "transform-es2015-unicode-regex": { - edge: 12, - firefox: 46, - chrome: 51, - opera: 38, - }, - "transform-regenerator": { - edge: 13, - firefox: 45, - chrome: 49, - opera: 36, - }, - - // es2016 - "transform-exponentiation-operator": { - edge: 14, - chrome: 52, - }, - - // es2017 - "transform-async-to-generator": { - edge: 14, - }, - "syntax-trailing-function-commas": { - edge: 14, - } -};