mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
refactor(transformer): add Engine enum for EngineTargets (#7161)
This commit is contained in:
parent
fd9b44cf13
commit
a981cafd1f
2 changed files with 80 additions and 77 deletions
|
|
@ -1,3 +1,5 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use rustc_hash::FxHashMap;
|
||||
use serde::Deserialize;
|
||||
|
||||
|
|
@ -5,7 +7,7 @@ use oxc_diagnostics::Error;
|
|||
|
||||
pub use browserslist::Version;
|
||||
|
||||
use crate::options::{BrowserslistQuery, EngineTargets};
|
||||
use crate::options::{engine_targets::Engine, BrowserslistQuery, EngineTargets};
|
||||
|
||||
/// <https://babel.dev/docs/babel-preset-env#targets>
|
||||
#[derive(Debug, Deserialize)]
|
||||
|
|
@ -39,7 +41,7 @@ impl TryFrom<BabelTargets> for EngineTargets {
|
|||
BabelTargets::String(s) => BrowserslistQuery::Single(s).exec(),
|
||||
BabelTargets::Array(v) => BrowserslistQuery::Multiple(v).exec(),
|
||||
BabelTargets::Map(map) => {
|
||||
let mut targets = Self::default();
|
||||
let mut engine_targets = Self::default();
|
||||
for (key, value) in map {
|
||||
// TODO: Implement these targets.
|
||||
if matches!(key.as_str(), "esmodules" | "browsers") {
|
||||
|
|
@ -63,12 +65,12 @@ impl TryFrom<BabelTargets> for EngineTargets {
|
|||
// TODO: Some keys are not implemented yet.
|
||||
// <https://babel.dev/docs/options#targets>:
|
||||
// Supported environments: android, chrome, deno, edge, electron, firefox, ie, ios, node, opera, rhino, safari, samsung.
|
||||
let Ok(target) = targets.get_version_mut(&key) else {
|
||||
continue;
|
||||
let Ok(engine) = Engine::from_str(&key) else {
|
||||
return Err(Error::msg(format!("engine '{key}' is not supported.")));
|
||||
};
|
||||
match Version::parse(&v) {
|
||||
Ok(version) => {
|
||||
target.replace(version);
|
||||
engine_targets.targets.insert(engine, version);
|
||||
}
|
||||
Err(err) => {
|
||||
return Err(oxc_diagnostics::Error::msg(format!(
|
||||
|
|
@ -77,7 +79,7 @@ impl TryFrom<BabelTargets> for EngineTargets {
|
|||
}
|
||||
}
|
||||
}
|
||||
Ok(targets)
|
||||
Ok(engine_targets)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,63 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use browserslist::Version;
|
||||
use rustc_hash::FxHashMap;
|
||||
use serde::Deserialize;
|
||||
|
||||
use oxc_diagnostics::Error;
|
||||
|
||||
use super::{babel::BabelTargets, BrowserslistQuery};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Engine {
|
||||
Chrome,
|
||||
Deno,
|
||||
Edge,
|
||||
Firefox,
|
||||
Hermes,
|
||||
Ie,
|
||||
Ios,
|
||||
Node,
|
||||
Opera,
|
||||
Rhino,
|
||||
Safari,
|
||||
Samsung,
|
||||
// TODO: electron to chromium
|
||||
Electron,
|
||||
// TODO: how to handle? There is a `op_mob` key below.
|
||||
OperaMobile,
|
||||
}
|
||||
|
||||
impl FromStr for Engine {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"chrome" | "and_chr" => Ok(Self::Chrome),
|
||||
"deno" => Ok(Self::Deno),
|
||||
"edge" => Ok(Self::Edge),
|
||||
"firefox" | "and_ff" => Ok(Self::Firefox),
|
||||
"hermes" => Ok(Self::Hermes),
|
||||
"ie" | "ie_mob" => Ok(Self::Ie),
|
||||
"ios" | "ios_saf" => Ok(Self::Ios),
|
||||
"node" => Ok(Self::Node),
|
||||
"opera" | "op_mob" => Ok(Self::Opera),
|
||||
"rhino" => Ok(Self::Rhino),
|
||||
"safari" => Ok(Self::Safari),
|
||||
"samsung" => Ok(Self::Samsung),
|
||||
"electron" => Ok(Self::Electron),
|
||||
"opera_mobile" => Ok(Self::OperaMobile),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A map of engine names to minimum supported versions.
|
||||
#[derive(Debug, Default, Clone, Eq, PartialEq, Deserialize)]
|
||||
#[derive(Debug, Default, Clone, Deserialize)]
|
||||
#[serde(try_from = "BabelTargets")]
|
||||
pub struct EngineTargets {
|
||||
chrome: Option<Version>,
|
||||
deno: Option<Version>,
|
||||
edge: Option<Version>,
|
||||
firefox: Option<Version>,
|
||||
hermes: Option<Version>,
|
||||
ie: Option<Version>,
|
||||
ios: Option<Version>,
|
||||
node: Option<Version>,
|
||||
opera: Option<Version>,
|
||||
rhino: Option<Version>,
|
||||
safari: Option<Version>,
|
||||
pub(crate) targets: FxHashMap<Engine, Version>,
|
||||
}
|
||||
|
||||
impl EngineTargets {
|
||||
|
|
@ -32,77 +70,40 @@ impl EngineTargets {
|
|||
|
||||
/// Returns true if all fields are [None].
|
||||
pub fn is_any_target(&self) -> bool {
|
||||
*self == Self::default()
|
||||
self.targets.is_empty()
|
||||
}
|
||||
|
||||
pub fn should_enable(&self, targets: &EngineTargets) -> bool {
|
||||
if let (Some(v1), Some(v2)) = (&self.chrome, &targets.chrome) {
|
||||
return v1 < v2;
|
||||
}
|
||||
if let (Some(v1), Some(v2)) = (&self.deno, &targets.deno) {
|
||||
return v1 < v2;
|
||||
}
|
||||
if let (Some(v1), Some(v2)) = (&self.edge, &targets.edge) {
|
||||
return v1 < v2;
|
||||
}
|
||||
if let (Some(v1), Some(v2)) = (&self.firefox, &targets.firefox) {
|
||||
return v1 < v2;
|
||||
}
|
||||
if let (Some(v1), Some(v2)) = (&self.hermes, &targets.hermes) {
|
||||
return v1 < v2;
|
||||
}
|
||||
if let (Some(v1), Some(v2)) = (&self.ie, &targets.ie) {
|
||||
return v1 < v2;
|
||||
}
|
||||
if let (Some(v1), Some(v2)) = (&self.ios, &targets.ios) {
|
||||
return v1 < v2;
|
||||
}
|
||||
if let (Some(v1), Some(v2)) = (&self.node, &targets.node) {
|
||||
return v1 < v2;
|
||||
}
|
||||
if let (Some(v1), Some(v2)) = (&self.opera, &targets.opera) {
|
||||
return v1 < v2;
|
||||
}
|
||||
if let (Some(v1), Some(v2)) = (&self.rhino, &targets.rhino) {
|
||||
return v1 < v2;
|
||||
}
|
||||
if let (Some(v1), Some(v2)) = (&self.safari, &targets.safari) {
|
||||
return v1 < v2;
|
||||
pub fn should_enable(&self, engine_targets: &EngineTargets) -> bool {
|
||||
for (engine, version) in &engine_targets.targets {
|
||||
if let Some(v) = self.targets.get(engine) {
|
||||
if v < version {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Parses the value returned from `browserslist`.
|
||||
pub fn parse_versions(versions: Vec<(String, String)>) -> Self {
|
||||
let mut targets = Self::default();
|
||||
for (name, version) in versions {
|
||||
let Ok(browser) = targets.get_version_mut(&name) else {
|
||||
let mut engine_targets = Self::default();
|
||||
for (engine, version) in versions {
|
||||
let Ok(engine) = Engine::from_str(&engine) else {
|
||||
continue;
|
||||
};
|
||||
let Ok(version) = version.parse::<Version>() else {
|
||||
let Ok(version) = Version::from_str(&version) else {
|
||||
continue;
|
||||
};
|
||||
if browser.is_none() || browser.is_some_and(|v| version < v) {
|
||||
browser.replace(version);
|
||||
}
|
||||
}
|
||||
targets
|
||||
}
|
||||
|
||||
pub(crate) fn get_version_mut(&mut self, key: &str) -> Result<&mut Option<Version>, ()> {
|
||||
match key {
|
||||
"chrome" | "and_chr" => Ok(&mut self.chrome),
|
||||
"deno" => Ok(&mut self.deno),
|
||||
"edge" => Ok(&mut self.edge),
|
||||
"firefox" | "and_ff" => Ok(&mut self.firefox),
|
||||
"hermes" => Ok(&mut self.hermes),
|
||||
"ie" | "ie_mob" => Ok(&mut self.ie),
|
||||
"ios" | "ios_saf" => Ok(&mut self.ios),
|
||||
"node" => Ok(&mut self.node),
|
||||
"opera" | "op_mob" => Ok(&mut self.opera),
|
||||
"rhino" => Ok(&mut self.rhino),
|
||||
"safari" => Ok(&mut self.safari),
|
||||
_ => Err(()),
|
||||
engine_targets
|
||||
.targets
|
||||
.entry(engine)
|
||||
.and_modify(|v| {
|
||||
if version < *v {
|
||||
*v = version;
|
||||
}
|
||||
})
|
||||
.or_insert(version);
|
||||
}
|
||||
engine_targets
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue