Skip to content

Commit

Permalink
feat(transformer_conformance): read plugins options from babel `optio…
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen authored Oct 17, 2023
1 parent 077585a commit 1b3b100
Show file tree
Hide file tree
Showing 26 changed files with 498 additions and 347 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions crates/oxc_syntax/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ categories.workspace = true
[lib]
doctest = false

[features]
default = []
serde = ["dep:serde"]

[dependencies]
oxc_index = { workspace = true }
oxc_span = { workspace = true }
Expand All @@ -29,3 +25,7 @@ bitflags = { workspace = true }
rustc-hash = { workspace = true }
indexmap = { workspace = true }
dashmap = { workspace = true }

[features]
default = []
serde = ["dep:serde"]
15 changes: 15 additions & 0 deletions crates/oxc_syntax/src/assumptions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#[cfg(feature = "serde")]
use serde::Deserialize;

/// Compiler assumptions
///
/// See <https://babeljs.io/docs/assumptions>
#[derive(Debug, Default, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct CompilerAssumptions {
/// When using operators that check for null or undefined, assume that they are never used with the special value document.all.
/// See <https://babeljs.io/docs/assumptions#nodocumentall>.
#[cfg_attr(feature = "serde", serde(default))]
pub no_document_all: bool,
}
1 change: 1 addition & 0 deletions crates/oxc_syntax/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Common code for JavaScript Syntax

pub mod assumptions;
pub mod identifier;
pub mod module_record;
pub mod operator;
Expand Down
2 changes: 2 additions & 0 deletions crates/oxc_transformer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ oxc_allocator = { workspace = true }
oxc_syntax = { workspace = true }
oxc_semantic = { workspace = true }

serde = { workspace = true }

[dev-dependencies]
oxc_parser = { workspace = true }
oxc_codegen = { workspace = true }
11 changes: 3 additions & 8 deletions crates/oxc_transformer/examples/transformer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ use oxc_codegen::{Codegen, CodegenOptions};
use oxc_parser::Parser;
use oxc_semantic::SemanticBuilder;
use oxc_span::SourceType;
use oxc_transformer::{
Assumptions, TransformOptions, TransformReactOptions, TransformTarget, Transformer,
};
use oxc_transformer::{TransformOptions, TransformTarget, Transformer};

// Instruction:
// create a `test.js`,
Expand Down Expand Up @@ -40,11 +38,8 @@ fn main() {
let symbols = Rc::new(RefCell::new(symbols));

let program = allocator.alloc(ret.program);
let transform_options = TransformOptions {
target: TransformTarget::ES2015,
react: Some(TransformReactOptions::default()),
assumptions: Assumptions::default(),
};
let transform_options =
TransformOptions { target: TransformTarget::ES2015, ..TransformOptions::default() };
Transformer::new(&allocator, source_type, &symbols, transform_options).build(program);
let printed = Codegen::<false>::new(source_text.len(), codegen_options).build(program);
println!("Transformed:\n");
Expand Down
9 changes: 6 additions & 3 deletions crates/oxc_transformer/src/es2015/shorthand_properties.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::rc::Rc;

use oxc_ast::{ast::*, AstBuilder};
use oxc_span::GetSpan;

use std::rc::Rc;
use crate::options::{TransformOptions, TransformTarget};

/// ES2015: Shorthand Properties
///
Expand All @@ -13,8 +15,9 @@ pub struct ShorthandProperties<'a> {
}

impl<'a> ShorthandProperties<'a> {
pub fn new(ast: Rc<AstBuilder<'a>>) -> Self {
Self { ast }
pub fn new(ast: Rc<AstBuilder<'a>>, options: &TransformOptions) -> Option<Self> {
(options.target < TransformTarget::ES2015 || options.shorthand_properties)
.then(|| Self { ast })
}

pub fn transform_object_property<'b>(&mut self, obj_prop: &'b mut ObjectProperty<'a>) {
Expand Down
17 changes: 13 additions & 4 deletions crates/oxc_transformer/src/es2016/exponentiation_operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ use oxc_semantic::SymbolTable;
use oxc_span::{Atom, Span};
use oxc_syntax::operator::{AssignmentOperator, BinaryOperator};

use crate::utils::CreateVars;
use crate::{
options::{TransformOptions, TransformTarget},
utils::CreateVars,
};

/// ES2016: Exponentiation Operator
///
Expand Down Expand Up @@ -36,9 +39,15 @@ impl<'a> CreateVars<'a> for ExponentiationOperator<'a> {
}

impl<'a> ExponentiationOperator<'a> {
pub fn new(ast: Rc<AstBuilder<'a>>, symbols: Rc<RefCell<SymbolTable>>) -> Self {
let vars = ast.new_vec();
Self { ast, symbols, vars }
pub fn new(
ast: Rc<AstBuilder<'a>>,
symbols: Rc<RefCell<SymbolTable>>,
options: &TransformOptions,
) -> Option<Self> {
(options.target < TransformTarget::ES2016 || options.exponentiation_operator).then(|| {
let vars = ast.new_vec();
Self { ast, symbols, vars }
})
}

pub fn transform_expression(&mut self, expr: &mut Expression<'a>) {
Expand Down
9 changes: 6 additions & 3 deletions crates/oxc_transformer/src/es2019/optional_catch_binding.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::rc::Rc;

use oxc_ast::{ast::*, AstBuilder};
use oxc_span::Span;

use std::rc::Rc;
use crate::options::{TransformOptions, TransformTarget};

/// ES2019: Optional Catch Binding
///
Expand All @@ -13,8 +15,9 @@ pub struct OptionalCatchBinding<'a> {
}

impl<'a> OptionalCatchBinding<'a> {
pub fn new(ast: Rc<AstBuilder<'a>>) -> Self {
Self { ast }
pub fn new(ast: Rc<AstBuilder<'a>>, options: &TransformOptions) -> Option<Self> {
(options.target < TransformTarget::ES2019 || options.optional_catch_binding)
.then(|| Self { ast })
}

pub fn transform_catch_clause<'b>(&mut self, clause: &'b mut CatchClause<'a>) {
Expand Down
4 changes: 3 additions & 1 deletion crates/oxc_transformer/src/es2020/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod nullish_coalescing_operator;

pub use nullish_coalescing_operator::NullishCoalescingOperator;
pub use nullish_coalescing_operator::{
NullishCoalescingOperator, NullishCoalescingOperatorOptions,
};
29 changes: 22 additions & 7 deletions crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use serde::Deserialize;
use std::{cell::RefCell, rc::Rc};

use oxc_allocator::Vec;
Expand All @@ -6,17 +7,26 @@ use oxc_semantic::SymbolTable;
use oxc_span::Span;
use oxc_syntax::operator::{AssignmentOperator, BinaryOperator, LogicalOperator};

use crate::{options::Assumptions, utils::CreateVars};
use crate::{utils::CreateVars, TransformOptions, TransformTarget};

#[derive(Debug, Default, Clone, Copy, Deserialize)]
pub struct NullishCoalescingOperatorOptions {
/// When true, this transform will pretend `document.all` does not exist,
/// and perform loose equality checks with null instead of strict equality checks against both null and undefined.
#[serde(default)]
loose: bool,
}

/// ES2020: Nullish Coalescing Operator
///
/// References:
/// * <https://babeljs.io/docs/babel-plugin-transform-nullish-coalescing-operator>
/// * <https://github.com/babel/babel/tree/main/packages/babel-plugin-transform-nullish-coalescing-operator>
pub struct NullishCoalescingOperator<'a> {
no_document_all: bool,

ast: Rc<AstBuilder<'a>>,
symbols: Rc<RefCell<SymbolTable>>,
assumptions: Assumptions,
vars: Vec<'a, VariableDeclarator<'a>>,
}

Expand All @@ -34,10 +44,15 @@ impl<'a> NullishCoalescingOperator<'a> {
pub fn new(
ast: Rc<AstBuilder<'a>>,
symbols: Rc<RefCell<SymbolTable>>,
assumptions: Assumptions,
) -> Self {
let vars = ast.new_vec();
Self { ast, symbols, assumptions, vars }
options: &TransformOptions,
) -> Option<Self> {
(options.target < TransformTarget::ES2020 || options.nullish_coalescing_operator.is_some())
.then(|| {
let no_document_all = options.assumptions.no_document_all
|| options.nullish_coalescing_operator.is_some_and(|o| o.loose);
let vars = ast.new_vec();
Self { no_document_all, ast, symbols, vars }
})
}

pub fn transform_expression(&mut self, expr: &mut Expression<'a>) {
Expand Down Expand Up @@ -67,7 +82,7 @@ impl<'a> NullishCoalescingOperator<'a> {
self.ast.assignment_expression(span, AssignmentOperator::Assign, left, right);
};

let test = if self.assumptions.no_document_all {
let test = if self.no_document_all {
let null = self.ast.literal_null_expression(NullLiteral::new(span));
self.ast.binary_expression(span, assignment, BinaryOperator::Inequality, null)
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use std::rc::Rc;

use oxc_ast::{ast::*, AstBuilder};
use oxc_span::Span;
use oxc_syntax::operator::{AssignmentOperator, LogicalOperator};

use std::rc::Rc;
use crate::options::{TransformOptions, TransformTarget};

/// ES2021: Logical Assignment Operators
///
Expand All @@ -14,8 +16,9 @@ pub struct LogicalAssignmentOperators<'a> {
}

impl<'a> LogicalAssignmentOperators<'a> {
pub fn new(ast: Rc<AstBuilder<'a>>) -> Self {
Self { ast }
pub fn new(ast: Rc<AstBuilder<'a>>, options: &TransformOptions) -> Option<Self> {
(options.target < TransformTarget::ES2021 || options.logical_assignment_operators)
.then(|| Self { ast })
}

pub fn transform_expression<'b>(&mut self, expr: &'b mut Expression<'a>) {
Expand Down
9 changes: 6 additions & 3 deletions crates/oxc_transformer/src/es2022/class_static_block.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::{collections::HashSet, rc::Rc};

use oxc_ast::{ast::*, AstBuilder};
use oxc_span::{Atom, Span};

use std::{collections::HashSet, rc::Rc};
use crate::options::{TransformOptions, TransformTarget};

/// ES2022: Class Static Block
///
Expand All @@ -13,8 +15,9 @@ pub struct ClassStaticBlock<'a> {
}

impl<'a> ClassStaticBlock<'a> {
pub fn new(ast: Rc<AstBuilder<'a>>) -> Self {
Self { ast }
pub fn new(ast: Rc<AstBuilder<'a>>, options: &TransformOptions) -> Option<Self> {
(options.target < TransformTarget::ES2022 || options.class_static_block)
.then(|| Self { ast })
}

pub fn transform_class_body<'b>(&mut self, class_body: &'b mut ClassBody<'a>) {
Expand Down
29 changes: 16 additions & 13 deletions crates/oxc_transformer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,15 @@ use oxc_span::SourceType;

use crate::{
es2015::ShorthandProperties, es2016::ExponentiationOperator, es2019::OptionalCatchBinding,
es2020::NullishCoalescingOperator, es2021::LogicalAssignmentOperators, react_jsx::ReactJsx,
regexp::RegexpFlags, typescript::TypeScript, utils::CreateVars,
es2020::NullishCoalescingOperator, es2021::LogicalAssignmentOperators,
es2022::ClassStaticBlock, react_jsx::ReactJsx, regexp::RegexpFlags, typescript::TypeScript,
utils::CreateVars,
};

pub use crate::options::{
Assumptions, TransformOptions, TransformReactOptions, TransformReactRuntime, TransformTarget,
pub use crate::{
es2020::NullishCoalescingOperatorOptions,
options::{TransformOptions, TransformTarget},
react_jsx::{ReactJsxOptions, ReactJsxRuntime},
};

#[derive(Default)]
Expand All @@ -46,7 +49,7 @@ pub struct Transformer<'a> {
react_jsx: Option<ReactJsx<'a>>,
regexp_flags: Option<RegexpFlags<'a>>,
// es2022
es2022_class_static_block: Option<es2022::ClassStaticBlock<'a>>,
es2022_class_static_block: Option<ClassStaticBlock<'a>>,
// es2021
es2021_logical_assignment_operators: Option<LogicalAssignmentOperators<'a>>,
// es2020
Expand All @@ -70,14 +73,14 @@ impl<'a> Transformer<'a> {
let ast = Rc::new(AstBuilder::new(allocator));
Self {
typescript: source_type.is_typescript().then(|| TypeScript::new(Rc::clone(&ast))),
react_jsx: options.react.map(|options| ReactJsx::new(Rc::clone(&ast), options)),
regexp_flags: RegexpFlags::new(Rc::clone(&ast), options.target),
es2022_class_static_block: (options.target < TransformTarget::ES2022).then(|| es2022::ClassStaticBlock::new(Rc::clone(&ast))),
es2021_logical_assignment_operators: (options.target < TransformTarget::ES2021).then(|| LogicalAssignmentOperators::new(Rc::clone(&ast))),
es2020_nullish_coalescing_operators: (options.target < TransformTarget::ES2020).then(|| NullishCoalescingOperator::new(Rc::clone(&ast), Rc::clone(symbols), options.assumptions)),
es2019_optional_catch_binding: (options.target < TransformTarget::ES2019).then(|| OptionalCatchBinding::new(Rc::clone(&ast))),
es2016_exponentiation_operator: (options.target < TransformTarget::ES2016).then(|| ExponentiationOperator::new(Rc::clone(&ast), Rc::clone(symbols))),
es2015_shorthand_properties: (options.target < TransformTarget::ES2015).then(|| ShorthandProperties::new(Rc::clone(&ast))),
react_jsx: options.react_jsx.map(|options| ReactJsx::new(Rc::clone(&ast), options)),
regexp_flags: RegexpFlags::new(Rc::clone(&ast), &options),
es2022_class_static_block: es2022::ClassStaticBlock::new(Rc::clone(&ast), &options),
es2021_logical_assignment_operators: LogicalAssignmentOperators::new(Rc::clone(&ast), &options),
es2020_nullish_coalescing_operators: NullishCoalescingOperator::new(Rc::clone(&ast), Rc::clone(symbols), &options),
es2019_optional_catch_binding: OptionalCatchBinding::new(Rc::clone(&ast), &options),
es2016_exponentiation_operator: ExponentiationOperator::new(Rc::clone(&ast), Rc::clone(symbols), &options),
es2015_shorthand_properties: ShorthandProperties::new(Rc::clone(&ast), &options),
}
}

Expand Down
Loading

0 comments on commit 1b3b100

Please sign in to comment.