Skip to content

Commit

Permalink
feat(transformer): add EnvOptions::from_browerslist_query API
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Nov 3, 2024
1 parent 8bdf23c commit fd28a55
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 45 deletions.
15 changes: 6 additions & 9 deletions crates/oxc_transformer/examples/transformer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use oxc_codegen::CodeGenerator;
use oxc_parser::Parser;
use oxc_semantic::SemanticBuilder;
use oxc_span::SourceType;
use oxc_transformer::{ESTarget, TransformOptions, Transformer};
use oxc_transformer::{ESTarget, EnvOptions, TransformOptions, Transformer};
use pico_args::Arguments;

// Instruction:
Expand Down Expand Up @@ -55,14 +55,11 @@ fn main() {

let (symbols, scopes) = ret.semantic.into_symbol_table_and_scope_tree();

let transform_options = if let Some(_targets) = &targets {
// FIXME
TransformOptions::enable_all()
// TransformOptions::try_from(&BabelEnvOptions {
// targets: Targets::try_from_query(targets).unwrap(),
// ..BabelEnvOptions::default()
// })
// .unwrap()
let transform_options = if let Some(query) = &targets {
TransformOptions {
env: EnvOptions::from_browerslist_query(query).unwrap(),
..TransformOptions::default()
}
} else if let Some(target) = &target {
TransformOptions::from(ESTarget::from_str(target).unwrap())
} else {
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_transformer/src/options/babel/env/targets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl Targets {
/// # Errors
///
/// * Query is invalid.
pub fn try_from_query(query: &str) -> Result<Self, oxc_diagnostics::Error> {
pub fn try_from_query(query: &str) -> Result<Self, Error> {
Query::Single(query.to_string()).exec().map(|v| v.0).map(Self)
}

Expand Down
16 changes: 16 additions & 0 deletions crates/oxc_transformer/src/options/env.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::str::FromStr;

use cow_utils::CowUtils;
use oxc_diagnostics::Error;
use serde::Deserialize;

use crate::{
Expand All @@ -13,6 +14,7 @@ use crate::{
es2021::ES2021Options,
es2022::{ClassPropertiesOptions, ES2022Options},
regexp::RegExpOptions,
Targets,
};

use super::babel::BabelEnvOptions;
Expand Down Expand Up @@ -131,6 +133,20 @@ impl EnvOptions {
},
}
}

/// # Errors
///
/// * When the query failed to parse.
pub fn from_browerslist_query(query: &str) -> Result<Self, Error> {
Self::try_from(BabelEnvOptions {
targets: Targets::try_from_query(query)?,
// This option will be enabled by default in Babel 8.
// <https://babel.dev/docs/babel-preset-env#bugfixes>
bugfixes: true,
..BabelEnvOptions::default()
})
.map_err(|err| Error::msg(err))
}
}

impl From<ESTarget> for EnvOptions {
Expand Down
38 changes: 8 additions & 30 deletions crates/oxc_transformer/tests/es_target/mod.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,11 @@
use std::{path::Path, str::FromStr};
use std::str::FromStr;

use oxc_allocator::Allocator;
use oxc_codegen::{CodeGenerator, CodegenOptions};
use oxc_parser::Parser;
use oxc_semantic::SemanticBuilder;
use crate::{codegen, test};
use oxc_span::SourceType;
use oxc_transformer::{ESTarget, TransformOptions, Transformer};

use crate::run;

pub(crate) fn test(source_text: &str, target: &str) -> String {
let source_type = SourceType::default();
let allocator = Allocator::default();
let ret = Parser::new(&allocator, source_text, source_type).parse();
let mut program = ret.program;
let (symbols, scopes) =
SemanticBuilder::new().build(&program).semantic.into_symbol_table_and_scope_tree();
let options = TransformOptions::from(ESTarget::from_str(target).unwrap());
Transformer::new(&allocator, Path::new(""), options).build_with_symbols_and_scopes(
symbols,
scopes,
&mut program,
);
CodeGenerator::new()
.with_options(CodegenOptions { single_quote: true, ..CodegenOptions::default() })
.build(&program)
.code
}
use oxc_transformer::{ESTarget, TransformOptions};

#[test]
fn es2015() {
fn es_target() {
use std::fmt::Write;

let cases = [
Expand All @@ -45,11 +21,13 @@ fn es2015() {

// Test no transformation for esnext.
for (_, case) in cases {
assert_eq!(run(case, SourceType::mjs()), test(case, "esnext"));
let options = TransformOptions::from(ESTarget::from_str("esnext").unwrap());
assert_eq!(codegen(case, SourceType::mjs()), test(case, options));
}

let snapshot = cases.iter().enumerate().fold(String::new(), |mut w, (i, (target, case))| {
let result = test(case, target);
let options = TransformOptions::from(ESTarget::from_str(target).unwrap());
let result = test(case, options);
write!(w, "########## {i} {target}\n{case}\n----------\n{result}\n").unwrap();
w
});
Expand Down
25 changes: 24 additions & 1 deletion crates/oxc_transformer/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,39 @@
mod es_target;
mod plugins;
mod targets;

use std::path::Path;

use oxc_allocator::Allocator;
use oxc_codegen::{CodeGenerator, CodegenOptions};
use oxc_parser::Parser;
use oxc_semantic::SemanticBuilder;
use oxc_span::SourceType;
use oxc_transformer::{TransformOptions, Transformer};

pub fn run(source_text: &str, source_type: SourceType) -> String {
pub fn codegen(source_text: &str, source_type: SourceType) -> String {
let allocator = Allocator::default();
let ret = Parser::new(&allocator, source_text, source_type).parse();
CodeGenerator::new()
.with_options(CodegenOptions { single_quote: true, ..CodegenOptions::default() })
.build(&ret.program)
.code
}

pub(crate) fn test(source_text: &str, options: TransformOptions) -> String {
let source_type = SourceType::default();
let allocator = Allocator::default();
let ret = Parser::new(&allocator, source_text, source_type).parse();
let mut program = ret.program;
let (symbols, scopes) =
SemanticBuilder::new().build(&program).semantic.into_symbol_table_and_scope_tree();
Transformer::new(&allocator, Path::new(""), options).build_with_symbols_and_scopes(
symbols,
scopes,
&mut program,
);
CodeGenerator::new()
.with_options(CodegenOptions { single_quote: true, ..CodegenOptions::default() })
.build(&program)
.code
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use oxc_semantic::SemanticBuilder;
use oxc_span::SourceType;
use oxc_transformer::{InjectGlobalVariables, InjectGlobalVariablesConfig, InjectImport};

use crate::run;
use crate::codegen;

pub(crate) fn test(source_text: &str, expected: &str, config: InjectGlobalVariablesConfig) {
let source_type = SourceType::default();
Expand All @@ -23,7 +23,7 @@ pub(crate) fn test(source_text: &str, expected: &str, config: InjectGlobalVariab
.with_options(CodegenOptions { single_quote: true, ..CodegenOptions::default() })
.build(&program)
.code;
let expected = run(expected, source_type);
let expected = codegen(expected, source_type);
assert_eq!(result, expected, "for source {source_text}");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use oxc_semantic::SemanticBuilder;
use oxc_span::SourceType;
use oxc_transformer::{ReplaceGlobalDefines, ReplaceGlobalDefinesConfig};

use crate::run;
use crate::codegen;

pub(crate) fn test(source_text: &str, expected: &str, config: ReplaceGlobalDefinesConfig) {
let source_type = SourceType::default();
Expand All @@ -19,7 +19,7 @@ pub(crate) fn test(source_text: &str, expected: &str, config: ReplaceGlobalDefin
.with_options(CodegenOptions { single_quote: true, ..CodegenOptions::default() })
.build(&program)
.code;
let expected = run(expected, source_type);
let expected = codegen(expected, source_type);
assert_eq!(result, expected, "for source {source_text}");
}

Expand Down
36 changes: 36 additions & 0 deletions crates/oxc_transformer/tests/targets/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use crate::{codegen, test};
use oxc_span::SourceType;
use oxc_transformer::{ESTarget, EnvOptions, TransformOptions};

#[test]
fn targets() {
let cases = [
("() => {}"),
("a ** b"),
// ("async function foo() {}"),
("({ ...x })"),
("try {} catch {}"),
("a ?? b"),
("a ||= b"),
// ("class foo { static {} }"),
];

// Test no transformation for default targets.
for case in cases {
let options = TransformOptions {
env: EnvOptions::from_browerslist_query("defaults").unwrap(),
..TransformOptions::default()
};
assert_eq!(codegen(case, SourceType::mjs()), test(case, options));
}

// Test transformation for very low targets.
for case in cases {
let options = TransformOptions::from(ESTarget::ES5);
let options_node = TransformOptions {
env: EnvOptions::from_browerslist_query("node 0.10").unwrap(),
..TransformOptions::default()
};
assert_eq!(test(case, options), test(case, options_node));
}
}

0 comments on commit fd28a55

Please sign in to comment.