Add safari technology preview for babel-preset-env. (#6791)

This commit is contained in:
Artem Yavorsky 2017-11-16 01:14:54 +02:00 committed by Brian Ng
parent 0f2ab2fe20
commit 48906604f2
15 changed files with 152 additions and 15 deletions

View File

@ -181,7 +181,7 @@ For more information on setting options for a preset, refer to the [plugin/prese
Takes an object of environment versions to support. Takes an object of environment versions to support.
Each target environment takes a number or a string (we recommend using a string when specifying minor versions like `node: "6.10"`). Each target environment takes a number or a string (we recommend using a string when specifying minor versions like `node: "6.10"`). You can also specify `tp` (technology preview) version for Safari.
Example environments: `chrome`, `opera`, `edge`, `firefox`, `safari`, `ie`, `ios`, `android`, `node`, `electron`. Example environments: `chrome`, `opera`, `edge`, `firefox`, `safari`, `ie`, `ios`, `android`, `node`, `electron`.
@ -197,7 +197,7 @@ If you want to compile against the current node version, you can specify `"node"
`Array<string> | string` `Array<string> | string`
A query to select browsers (ex: last 2 versions, > 5%) using [browserslist](https://github.com/ai/browserslist). A query to select browsers (ex: last 2 versions, > 5%, safari tp) using [browserslist](https://github.com/ai/browserslist).
Note, browsers' results are overridden by explicit items from `targets`. Note, browsers' results are overridden by explicit items from `targets`.

View File

@ -948,6 +948,7 @@
}, },
"es7.promise.finally": { "es7.promise.finally": {
"chrome": "63", "chrome": "63",
"safari": "tp",
"opera": "50" "opera": "50"
} }
} }

View File

@ -231,14 +231,18 @@
"proposal-async-generator-functions": { "proposal-async-generator-functions": {
"chrome": "63", "chrome": "63",
"firefox": "57", "firefox": "57",
"safari": "tp",
"opera": "50" "opera": "50"
}, },
"proposal-object-rest-spread": { "proposal-object-rest-spread": {
"chrome": "60", "chrome": "60",
"firefox": "55", "firefox": "55",
"safari": "tp",
"node": "8.3", "node": "8.3",
"opera": "47" "opera": "47"
}, },
"proposal-optional-catch-binding": {}, "proposal-optional-catch-binding": {
"safari": "tp"
},
"proposal-unicode-property-regex": {} "proposal-unicode-property-regex": {}
} }

View File

@ -0,0 +1,3 @@
module.exports = {
safari: "tp",
};

View File

@ -7,6 +7,7 @@ const flattenDeep = require("lodash/flattenDeep");
const isEqual = require("lodash/isEqual"); const isEqual = require("lodash/isEqual");
const mapValues = require("lodash/mapValues"); const mapValues = require("lodash/mapValues");
const pickBy = require("lodash/pickBy"); const pickBy = require("lodash/pickBy");
const unreleasedLabels = require("../data/unreleased-labels");
const electronToChromiumVersions = require("electron-to-chromium").versions; const electronToChromiumVersions = require("electron-to-chromium").versions;
const electronToChromiumKeys = Object.keys( const electronToChromiumKeys = Object.keys(
@ -185,6 +186,7 @@ const getLowestImplementedVersion = ({ features }, env) => {
return result; return result;
}, []); }, []);
const unreleasedLabelForEnv = unreleasedLabels[env];
const envTests = tests.map(({ res: test, isBuiltIn }, i) => { const envTests = tests.map(({ res: test, isBuiltIn }, i) => {
// Babel itself doesn't implement the feature correctly, // Babel itself doesn't implement the feature correctly,
// don't count against it // don't count against it
@ -200,9 +202,15 @@ const getLowestImplementedVersion = ({ features }, env) => {
.filter( .filter(
test => tests[i].res[test] === true || tests[i].res[test] === "strict" test => tests[i].res[test] === true || tests[i].res[test] === "strict"
) )
// normalize some keys // normalize some keys and get version from full string.
.map(test => test.replace("_", ".")) .map(test => {
.filter(test => !isNaN(parseFloat(test.replace(env, "")))) return test.replace("_", ".").replace(env, "");
})
// version must be label from the unreleasedLabels (like tp) or number.
.filter(
version =>
unreleasedLabelForEnv === version || !isNaN(parseFloat(version))
)
.shift() .shift()
); );
}); });
@ -220,9 +228,14 @@ const getLowestImplementedVersion = ({ features }, env) => {
return null; return null;
} }
return envTests.map(str => Number(str.replace(env, ""))).reduce((a, b) => { return envTests
return a < b ? b : a; .map(str => {
}); const version = str.replace(env, "");
return version === unreleasedLabelForEnv ? version : parseFloat(version);
})
.reduce((a, b) => {
return b === unreleasedLabelForEnv || a < b ? b : a;
});
}; };
const generateData = (environments, features) => { const generateData = (environments, features) => {

View File

@ -16,7 +16,12 @@ import useBuiltInsEntryPlugin from "./use-built-ins-entry-plugin";
import addUsedBuiltInsPlugin from "./use-built-ins-plugin"; import addUsedBuiltInsPlugin from "./use-built-ins-plugin";
import getTargets from "./targets-parser"; import getTargets from "./targets-parser";
import availablePlugins from "./available-plugins"; import availablePlugins from "./available-plugins";
import { filterStageFromList, prettifyTargets, semverify } from "./utils"; import {
filterStageFromList,
prettifyTargets,
semverify,
isUnreleasedVersion,
} from "./utils";
import type { Plugin, Targets } from "./types"; import type { Plugin, Targets } from "./types";
const getPlugin = (pluginName: string) => { const getPlugin = (pluginName: string) => {
@ -61,6 +66,13 @@ export const isPluginRequired = (
const lowestImplementedVersion: string = plugin[environment]; const lowestImplementedVersion: string = plugin[environment];
const lowestTargetedVersion: string = supportedEnvironments[environment]; const lowestTargetedVersion: string = supportedEnvironments[environment];
// If targets has unreleased value as a lowest version, then don't require a plugin.
if (isUnreleasedVersion(lowestTargetedVersion, environment)) {
return false;
// Include plugin if it is supported in the unreleased environment, which wasn't specified in targets
} else if (isUnreleasedVersion(lowestImplementedVersion, environment)) {
return true;
}
if (!semver.valid(lowestTargetedVersion)) { if (!semver.valid(lowestTargetedVersion)) {
throw new Error( throw new Error(

View File

@ -2,7 +2,7 @@
import browserslist from "browserslist"; import browserslist from "browserslist";
import semver from "semver"; import semver from "semver";
import { semverify } from "./utils"; import { semverify, isUnreleasedVersion, getLowestUnreleased } from "./utils";
import { objectToBrowserslist } from "./normalize-options"; import { objectToBrowserslist } from "./normalize-options";
import type { Targets } from "./types"; import type { Targets } from "./types";
@ -20,7 +20,7 @@ const browserNameMap = {
const isBrowsersQueryValid = (browsers: string | Array<string>): boolean => const isBrowsersQueryValid = (browsers: string | Array<string>): boolean =>
typeof browsers === "string" || Array.isArray(browsers); typeof browsers === "string" || Array.isArray(browsers);
const semverMin = (first: ?string, second: string): string => { export const semverMin = (first: ?string, second: string): string => {
return first && semver.lt(first, second) ? first : second; return first && semver.lt(first, second) ? first : second;
}; };
@ -44,7 +44,16 @@ const getLowestVersions = (browsers: Array<string>): Targets => {
try { try {
// Browser version can return as "10.0-10.2" // Browser version can return as "10.0-10.2"
const splitVersion = browserVersion.split("-")[0]; const splitVersion = browserVersion.split("-")[0].toLowerCase();
if (isUnreleasedVersion(splitVersion, browserName)) {
all[normalizedBrowserName] = getLowestUnreleased(
all[normalizedBrowserName],
splitVersion,
browserName,
);
}
const parsedBrowserVersion = semverify(splitVersion); const parsedBrowserVersion = semverify(splitVersion);
all[normalizedBrowserName] = semverMin( all[normalizedBrowserName] = semverMin(
@ -76,7 +85,12 @@ const outputDecimalWarning = (decimalTargets: Array<Object>): void => {
}; };
const targetParserMap = { const targetParserMap = {
__default: (target, value) => [target, semverify(value)], __default: (target, value) => {
const version = isUnreleasedVersion(value, target)
? value.toLowerCase()
: semverify(value);
return [target, version];
},
// Parse `node: true` and `node: "current"` to version // Parse `node: true` and `node: "current"` to version
node: (target, value) => { node: (target, value) => {

View File

@ -1,6 +1,8 @@
// @flow // @flow
import semver from "semver"; import semver from "semver";
import unreleasedLabels from "../data/unreleased-labels";
import { semverMin } from "./targets-parser";
import type { Targets } from "./types"; import type { Targets } from "./types";
// Convert version to a semver value. // Convert version to a semver value.
@ -43,7 +45,8 @@ export const prettifyTargets = (targets: Targets): Object => {
return Object.keys(targets).reduce((results, target) => { return Object.keys(targets).reduce((results, target) => {
let value = targets[target]; let value = targets[target];
if (typeof value === "string") { const unreleasedLabel = unreleasedLabels[target];
if (typeof value === "string" && unreleasedLabel !== value) {
value = prettifyVersion(value); value = prettifyVersion(value);
} }
@ -52,6 +55,26 @@ export const prettifyTargets = (targets: Targets): Object => {
}, {}); }, {});
}; };
export const isUnreleasedVersion = (version: string, env: string): boolean => {
const unreleasedLabel = unreleasedLabels[env];
return (
unreleasedLabel && unreleasedLabel === version.toString().toLowerCase()
);
};
export const getLowestUnreleased = (
a: string,
b: string,
env: string,
): string => {
const unreleasedLabel = unreleasedLabels[env];
const hasUnreleased = [a, b].some(item => item === unreleasedLabel);
if (hasUnreleased) {
return a === hasUnreleased ? b : a || b;
}
return semverMin(a, b);
};
export const filterStageFromList = (list: any, stageList: any) => { export const filterStageFromList = (list: any, stageList: any) => {
return Object.keys(list).reduce((result, item) => { return Object.keys(list).reduce((result, item) => {
if (!stageList[item]) { if (!stageList[item]) {

View File

@ -0,0 +1,4 @@
let n = { x, y, ...z };
try {
throw 0;
} catch {}

View File

@ -0,0 +1,9 @@
let n = {
x,
y,
...z
};
try {
throw 0;
} catch {}

View File

@ -0,0 +1,11 @@
{
"presets": [
["../../../../lib", {
"targets": {
"browsers": "safari tp"
},
"shippedProposals": true
}
]
]
}

View File

@ -0,0 +1 @@
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };

View File

@ -0,0 +1,10 @@
let {
x,
y,
...z
} = {
x: 1,
y: 2,
a: 3,
b: 4
};

View File

@ -0,0 +1,10 @@
{
"presets": [
["../../../../lib", {
"targets": {
"safari": "tp"
},
"shippedProposals": true
}]
]
}

View File

@ -39,6 +39,28 @@ describe("getTargets", () => {
); );
}); });
it("works with TP versions", () => {
assert.deepEqual(
getTargets({
browsers: "safari tp",
}),
{
safari: "tp",
},
);
});
it("returns TP version in lower case", () => {
assert.deepEqual(
getTargets({
safari: "TP",
}),
{
safari: "tp",
},
);
});
it("ignores invalid", () => { it("ignores invalid", () => {
assert.deepEqual( assert.deepEqual(
getTargets({ getTargets({