mirror of
https://github.com/swc-project/swc.git
synced 2025-01-08 23:10:13 +03:00
feat(es/preset_env): Use browserslist-rs
(#2845)
swc_ecma_preset_env: - Fix `default_path`. - Use `browserslist-rs` for query. (Closes #2781)
This commit is contained in:
parent
e99c4d26ae
commit
2c099bfd2c
63
Cargo.lock
generated
63
Cargo.lock
generated
@ -256,6 +256,24 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "browserslist-rs"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa428c5a7369965603314e5fbfa5ae1755159bce2c35880d80ea84a866213b20"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"itertools",
|
||||
"js-sys",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build_const"
|
||||
version = "0.2.2"
|
||||
@ -298,10 +316,12 @@ version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"libc",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"time",
|
||||
"wasm-bindgen",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
@ -944,6 +964,15 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.8"
|
||||
@ -2193,6 +2222,18 @@ dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-wasm-bindgen"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "618365e8e586c22123d692b72a7d791d5ee697817b65a218cdf12a98870af0f7"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"js-sys",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.130"
|
||||
@ -2829,6 +2870,8 @@ name = "swc_ecma_preset_env"
|
||||
version = "0.66.0"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
"browserslist-rs",
|
||||
"dashmap",
|
||||
"indexmap",
|
||||
"once_cell",
|
||||
@ -3390,6 +3433,26 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.3"
|
||||
|
@ -11,6 +11,8 @@ version = "0.66.0"
|
||||
|
||||
[dependencies]
|
||||
ahash = "0.7.4"
|
||||
anyhow = "1"
|
||||
browserslist-rs = "=0.2.0"
|
||||
dashmap = "4.0.2"
|
||||
indexmap = "1.6.2"
|
||||
once_cell = "1.2.0"
|
||||
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"browserslist": ">=4.16.5"
|
||||
},
|
||||
"browserslist": [
|
||||
"defaults"
|
||||
]
|
||||
}
|
@ -2,14 +2,12 @@
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
pub use self::{transform_data::Feature, version::Version};
|
||||
use anyhow::{Context, Error};
|
||||
use dashmap::DashMap;
|
||||
use once_cell::sync::Lazy;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::Deserialize;
|
||||
use st_map::StaticMap;
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
};
|
||||
use std::path::PathBuf;
|
||||
use swc_atoms::{js_word, JsWord};
|
||||
use swc_common::{
|
||||
chain,
|
||||
@ -38,8 +36,7 @@ where
|
||||
C: Comments,
|
||||
{
|
||||
let loose = c.loose;
|
||||
let targets: Versions =
|
||||
targets_to_versions(c.targets, &c.path).expect("failed to parse targets");
|
||||
let targets: Versions = targets_to_versions(c.targets).expect("failed to parse targets");
|
||||
let is_any_target = targets.is_any_target();
|
||||
|
||||
let (include, included_modules) = FeatureOrModule::split(c.include);
|
||||
@ -425,12 +422,12 @@ pub enum Mode {
|
||||
pub type Versions = BrowserData<Option<Version>>;
|
||||
|
||||
impl BrowserData<Option<Version>> {
|
||||
pub fn is_any_target(&self) -> bool {
|
||||
pub(crate) fn is_any_target(&self) -> bool {
|
||||
self.iter().all(|(_, v)| v.is_none())
|
||||
}
|
||||
|
||||
pub fn parse_versions<'a>(lines: impl Iterator<Item = &'a str>) -> Result<Self, &'a str> {
|
||||
fn remap(key: &str) -> String {
|
||||
pub(crate) fn parse_versions(distribs: Vec<browserslist::Distrib>) -> Result<Self, Error> {
|
||||
fn remap(key: &str) -> &str {
|
||||
match key {
|
||||
"and_chr" => "chrome".into(),
|
||||
"and_ff" => "firefox".into(),
|
||||
@ -441,13 +438,11 @@ impl BrowserData<Option<Version>> {
|
||||
}
|
||||
}
|
||||
|
||||
let browsers = lines.map(|v| {
|
||||
let mut v = v.split(' ');
|
||||
(remap(v.next().unwrap()), v.next().unwrap().to_string())
|
||||
});
|
||||
|
||||
let mut data: Versions = BrowserData::default();
|
||||
for (browser, version) in browsers {
|
||||
for dist in distribs {
|
||||
let browser = dist.name();
|
||||
let browser = remap(browser);
|
||||
let version = dist.version();
|
||||
match &*browser {
|
||||
"and_qq" | "and_uc" | "baidu" | "bb" | "kaios" | "op_mini" => continue,
|
||||
|
||||
@ -527,7 +522,11 @@ fn default_targets() -> Option<Targets> {
|
||||
}
|
||||
|
||||
fn default_path() -> PathBuf {
|
||||
std::env::current_dir().unwrap()
|
||||
if cfg!(target_arch = "wasm32") {
|
||||
Default::default()
|
||||
} else {
|
||||
std::env::current_dir().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, FromVariant)]
|
||||
@ -583,72 +582,69 @@ pub enum Query {
|
||||
Multiple(Vec<String>),
|
||||
}
|
||||
|
||||
type QueryResult = Result<Versions, ()>;
|
||||
type QueryResult = Result<Versions, Error>;
|
||||
|
||||
impl Query {
|
||||
fn exec(&self, path: &Path) -> QueryResult {
|
||||
fn query<T>(s: &[T], path: &Path) -> QueryResult
|
||||
fn exec(&self) -> QueryResult {
|
||||
fn query<T>(s: &[T]) -> QueryResult
|
||||
where
|
||||
T: AsRef<str> + Serialize,
|
||||
T: AsRef<str>,
|
||||
{
|
||||
let output = {
|
||||
let output = Command::new("node")
|
||||
.current_dir(path)
|
||||
.arg("-e")
|
||||
.arg(include_str!("query.js"))
|
||||
.arg(serde_json::to_string(&s).expect("failed to serialize with serde"))
|
||||
.output()
|
||||
.expect("failed to collect output");
|
||||
if !output.status.success() {
|
||||
println!("query.js: Status {:?}", output.status,);
|
||||
println!(
|
||||
"{}\n{}",
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr),
|
||||
);
|
||||
return Err(());
|
||||
}
|
||||
let distribs = browserslist::resolve(
|
||||
s,
|
||||
&browserslist::Opts {
|
||||
mobile_to_desktop: false,
|
||||
ignore_unknown_versions: true,
|
||||
},
|
||||
)
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"failed to resolve browserslist query: {:?}",
|
||||
s.iter().map(|v| v.as_ref()).collect::<Vec<_>>()
|
||||
)
|
||||
})?;
|
||||
|
||||
output.stdout
|
||||
};
|
||||
|
||||
let browsers: Vec<String> =
|
||||
serde_json::from_slice(&output).expect("failed to read browser data output");
|
||||
let versions = BrowserData::parse_versions(browsers.iter().map(|s| &**s))
|
||||
.expect("failed to parse browser version");
|
||||
let versions =
|
||||
BrowserData::parse_versions(distribs).expect("failed to parse browser version");
|
||||
|
||||
Ok(versions)
|
||||
}
|
||||
|
||||
static CACHE: Lazy<DashMap<Query, QueryResult, ahash::RandomState>> =
|
||||
static CACHE: Lazy<DashMap<Query, Versions, ahash::RandomState>> =
|
||||
Lazy::new(Default::default);
|
||||
|
||||
if let Some(v) = CACHE.get(self) {
|
||||
return match &*v {
|
||||
Ok(v) => Ok(*v),
|
||||
Err(err) => Err(*err),
|
||||
};
|
||||
return Ok(v.clone());
|
||||
}
|
||||
|
||||
let result = match *self {
|
||||
Query::Single(ref s) => query(&[s], path),
|
||||
Query::Multiple(ref s) => query(&s, path),
|
||||
};
|
||||
Query::Single(ref s) => {
|
||||
if s == "" {
|
||||
query(&["defaults"])
|
||||
} else {
|
||||
query(&[s])
|
||||
}
|
||||
}
|
||||
Query::Multiple(ref s) => query(&s),
|
||||
}
|
||||
.context("failed to execute query")?;
|
||||
|
||||
CACHE.insert(self.clone(), result);
|
||||
|
||||
result
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
fn targets_to_versions(v: Option<Targets>, path: &Path) -> Result<Versions, ()> {
|
||||
fn targets_to_versions(v: Option<Targets>) -> Result<Versions, Error> {
|
||||
match v {
|
||||
None => Ok(Default::default()),
|
||||
Some(Targets::Versions(v)) => Ok(v),
|
||||
Some(Targets::Query(q)) => q.exec(path),
|
||||
Some(Targets::Query(q)) => q
|
||||
.exec()
|
||||
.context("failed to convert target query to version data"),
|
||||
Some(Targets::HashMap(mut map)) => {
|
||||
let q = map.remove("browsers").map(|q| match q {
|
||||
QueryOrVersion::Query(q) => q.exec(path).expect("failed to run query"),
|
||||
QueryOrVersion::Query(q) => q.exec().expect("failed to run query"),
|
||||
_ => unreachable!(),
|
||||
});
|
||||
|
||||
@ -676,8 +672,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_empty() {
|
||||
let path = std::env::current_dir().unwrap();
|
||||
let res = Query::Single("".into()).exec(&path).unwrap();
|
||||
let res = Query::Single("".into()).exec().unwrap();
|
||||
assert!(
|
||||
!res.is_any_target(),
|
||||
"empty query should return non-empty result"
|
||||
|
@ -1,27 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
var browserslist;
|
||||
try{
|
||||
browserslist = require('browserslist');
|
||||
} catch (e){
|
||||
console.error('swc: You have to install `browserslist` to use `env`');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
||||
var target = JSON.parse(process.argv[1]);
|
||||
target = target.browsers ? target.browsers : target;
|
||||
target = Array.isArray(target) ? target : typeof target === 'string' ? [target] : Object.keys(target).map(function (k) {
|
||||
return k + " " + target[k];
|
||||
});
|
||||
target = target.filter(function (v) {
|
||||
return !v.startsWith('esmodules') && !!v;
|
||||
}); // console.log('Target: ', target);
|
||||
|
||||
var browsers = browserslist(target && target.length ? target : undefined, {
|
||||
mobileToDesktop: true
|
||||
});
|
||||
browsers = browsers.filter(function (v) {
|
||||
return !v.includes("TP");
|
||||
});
|
||||
console.log(JSON.stringify(browsers));
|
@ -1,13 +1,3 @@
|
||||
import "core-js/modules/es6.array.sort";
|
||||
import "core-js/modules/es7.array.flat-map";
|
||||
import "core-js/modules/es7.object.define-getter";
|
||||
import "core-js/modules/es7.object.define-setter";
|
||||
import "core-js/modules/es7.object.lookup-getter";
|
||||
import "core-js/modules/es7.object.lookup-setter";
|
||||
import "core-js/modules/es7.promise.finally";
|
||||
import "core-js/modules/es7.string.trim-left";
|
||||
import "core-js/modules/es7.string.trim-right";
|
||||
import "core-js/modules/es7.symbol.async-iterator";
|
||||
import "core-js/modules/web.dom.iterable";
|
||||
import "core-js/modules/web.immediate";
|
||||
import "core-js/modules/web.timers";
|
||||
|
@ -1,28 +1,2 @@
|
||||
import "core-js/modules/es.array.flat";
|
||||
import "core-js/modules/es.array.flat-map";
|
||||
import "core-js/modules/es.array.iterator";
|
||||
import "core-js/modules/es.array.reduce";
|
||||
import "core-js/modules/es.array.reduce-right";
|
||||
import "core-js/modules/es.array.sort";
|
||||
import "core-js/modules/es.array.unscopables.flat";
|
||||
import "core-js/modules/es.array.unscopables.flat-map";
|
||||
import "core-js/modules/es.math.hypot";
|
||||
import "core-js/modules/es.object.define-getter";
|
||||
import "core-js/modules/es.object.define-setter";
|
||||
import "core-js/modules/es.object.from-entries";
|
||||
import "core-js/modules/es.object.lookup-getter";
|
||||
import "core-js/modules/es.object.lookup-setter";
|
||||
import "core-js/modules/es.promise";
|
||||
import "core-js/modules/es.promise.finally";
|
||||
import "core-js/modules/es.string.replace";
|
||||
import "core-js/modules/es.string.trim-end";
|
||||
import "core-js/modules/es.string.trim-start";
|
||||
import "core-js/modules/es.symbol.async-iterator";
|
||||
import "core-js/modules/es.symbol.description";
|
||||
import "core-js/modules/web.dom-collections.iterator";
|
||||
import "core-js/modules/web.immediate";
|
||||
import "core-js/modules/web.queue-microtask";
|
||||
import "core-js/modules/web.url";
|
||||
import "core-js/modules/web.url-search-params";
|
||||
import "core-js/modules/web.url.to-json";
|
||||
1 ** 2;
|
||||
|
@ -43,6 +43,7 @@
|
||||
"Deser",
|
||||
"dont",
|
||||
"DWORD",
|
||||
"ecma",
|
||||
"ecmascript",
|
||||
"eddyb",
|
||||
"elems",
|
||||
@ -125,5 +126,7 @@
|
||||
"unimpl",
|
||||
"untrusted"
|
||||
],
|
||||
"flagWords": ["actally"]
|
||||
}
|
||||
"flagWords": [
|
||||
"actally"
|
||||
]
|
||||
}
|
@ -49,9 +49,7 @@
|
||||
"dependencies": {
|
||||
"@node-rs/helper": "^1.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"browserslist": "^4.16.6"
|
||||
},
|
||||
"optionalDependencies": {},
|
||||
"types": "./index.d.ts",
|
||||
"scripts": {
|
||||
"prepare": "husky install && git config feature.manyFiles true",
|
||||
@ -78,7 +76,6 @@
|
||||
"@types/node": "^14.14.41",
|
||||
"axios": "^0.21.1",
|
||||
"babel-plugin-transform-node-env-inline": "^0.4.3",
|
||||
"browserslist": "^4.16.6",
|
||||
"class-validator": "^0.13.1",
|
||||
"core-js": "^2.6.11",
|
||||
"cross-env": "^7.0.3",
|
||||
|
Loading…
Reference in New Issue
Block a user