Skip to content

Commit

Permalink
feat(transformer): Add babel-plugin-transform-dotall-regex
Browse files Browse the repository at this point in the history
  • Loading branch information
bschoenmaeckers committed Mar 20, 2024
1 parent 3c9e77d commit 07f97e4
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 5 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ tasks/prettier_conformance/prettier/

# Ignore the failures directory, which is used to store the results of the codegen coverage tests
tasks/coverage/failures/

# IntelliJ
.idea/
2 changes: 2 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ project-root = { version = "0.2.2" }
quote = { version = "1.0.35" }
rayon = { version = "1.9.0" }
regex = { version = "1.10.3" }
regex-syntax = { version = "0.8.2" }
rustc-hash = { version = "1.1.0", default-features = false, features = ["std"] }
ryu-js = { version = "1.0.1" }
ropey = { version = "1.6.1" }
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 @@ -30,6 +30,8 @@ rustc-hash = { workspace = true }

serde = { workspace = true, features = ["derive"] }
phf = { workspace = true, features = ["macros"] }
regex-syntax = { workspace = true }
lazy_static = { workspace = true }

[dev-dependencies]
oxc_parser = { workspace = true }
Expand Down
68 changes: 68 additions & 0 deletions crates/oxc_transformer/src/es2018/dotall_regex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use std::rc::Rc;
use lazy_static::lazy_static;

use oxc_ast::{ast::*, AstBuilder};
use oxc_span::SPAN;
use regex_syntax::ast::parse::Parser;
use regex_syntax::ast::{Ast};

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

/// ES2024: Unicode Sets Regex
///
/// References:
/// * <https://babel.dev/docs/babel-plugin-transform-dotall-regex>
/// * <https://github.com/babel/babel/blob/main/packages/babel-plugin-transform-dotall-regex>
pub struct DotallRegex<'a> {
ast: Rc<AstBuilder<'a>>,
}

impl<'a> DotallRegex<'a> {
pub fn new(ast: Rc<AstBuilder<'a>>, options: &TransformOptions) -> Option<Self> {
(options.target < TransformTarget::ES2018 || options.dotall_regex).then_some(Self { ast })
}

pub fn transform_expression(&self, expr: &mut Expression<'a>) {
let Expression::RegExpLiteral(literal) = expr else {
return;
};
if !literal.regex.flags.contains(RegExpFlags::S) {
return;
}
literal.regex.flags.remove(RegExpFlags::S);
let mut parser = Parser::new();
if let Ok(mut pattern) = parser.parse(literal.regex.pattern.as_str()) {
Self::transform_dot(&mut pattern);
let pattern = self.ast.new_str(pattern.to_string().as_str());
let regex = self.ast.reg_exp_literal(SPAN, pattern, literal.regex.flags);
*expr = self.ast.literal_regexp_expression(regex);
}
}

fn transform_dot(ast: &mut Ast) {
lazy_static! {
static ref DOTALL: Ast = {
let mut parser = Parser::new();
parser.parse("[\\s\\S]").unwrap()
};
}
match ast {
Ast::Dot(_) => {
*ast = DOTALL.clone();
}
Ast::Concat(ref mut concat) => {
concat.asts.iter_mut().for_each(Self::transform_dot);
}
Ast::Group(ref mut group) => {
Self::transform_dot(&mut group.ast);
}
Ast::Alternation(ref mut alternation) => {
alternation.asts.iter_mut().for_each(Self::transform_dot);
}
Ast::Repetition(ref mut repetition) => {
Self::transform_dot(&mut repetition.ast);
}
_ => {}
}
}
}
3 changes: 3 additions & 0 deletions crates/oxc_transformer/src/es2018/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod dotall_regex;

pub use dotall_regex::DotallRegex;
7 changes: 7 additions & 0 deletions crates/oxc_transformer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
mod context;
mod es2015;
mod es2016;
mod es2018;
mod es2019;
mod es2020;
mod es2021;
Expand Down Expand Up @@ -38,6 +39,7 @@ use crate::{
context::TransformerCtx,
es2015::*,
es2016::ExponentiationOperator,
es2018::DotallRegex,
es2019::{JsonStrings, OptionalCatchBinding},
es2020::NullishCoalescingOperator,
es2021::LogicalAssignmentOperators,
Expand Down Expand Up @@ -74,6 +76,8 @@ pub struct Transformer<'a> {
// es2019
es2019_json_strings: Option<JsonStrings<'a>>,
es2019_optional_catch_binding: Option<OptionalCatchBinding<'a>>,
// es2018
es2018_dotall_regex: Option<DotallRegex<'a>>,
// es2016
es2016_exponentiation_operator: Option<ExponentiationOperator<'a>>,
// es2015
Expand Down Expand Up @@ -116,6 +120,8 @@ impl<'a> Transformer<'a> {
// es2019
es2019_json_strings: JsonStrings::new(Rc::clone(&ast), &options),
es2019_optional_catch_binding: OptionalCatchBinding::new(Rc::clone(&ast), &options),
// es2018
es2018_dotall_regex: DotallRegex::new(Rc::clone(&ast), &options),
// es2016
es2016_exponentiation_operator: ExponentiationOperator::new(Rc::clone(&ast), ctx.clone(), &options),
// es2015
Expand Down Expand Up @@ -224,6 +230,7 @@ impl<'a> VisitMut<'a> for Transformer<'a> {
fn visit_expression(&mut self, expr: &mut Expression<'a>) {
// self.typescript.as_mut().map(|t| t.transform_expression(expr));
self.react_jsx.as_mut().map(|t| t.transform_expression(expr));
self.es2018_dotall_regex.as_mut().map(|t| t.transform_expression(expr));
self.regexp_flags.as_mut().map(|t| t.transform_expression(expr));

self.es2021_logical_assignment_operators.as_mut().map(|t| t.transform_expression(expr));
Expand Down
1 change: 1 addition & 0 deletions crates/oxc_transformer/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub struct TransformOptions {
pub function_name: bool,
pub arrow_functions: Option<ArrowFunctionsOptions>,
pub shorthand_properties: bool,
pub dotall_regex: bool,
pub sticky_regex: bool,
pub template_literals: bool,
pub property_literals: bool,
Expand Down
25 changes: 20 additions & 5 deletions tasks/transform_conformance/babel.snap.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Passed: 352/1369
Passed: 354/1386

# All Passed:
* babel-plugin-transform-numeric-separator
Expand Down Expand Up @@ -695,9 +695,7 @@ Passed: 352/1369
* regression/gh-7388/input.js
* regression/gh-8323/input.js

# babel-plugin-transform-dotall-regex (0/3)
* dotall-regex/simple/input.js
* dotall-regex/with-unicode-flag/input.js
# babel-plugin-transform-dotall-regex (2/3)
* dotall-regex/with-unicode-property-escape/input.js

# babel-plugin-transform-async-to-generator (1/43)
Expand Down Expand Up @@ -832,7 +830,7 @@ Passed: 352/1369
* general/function-duplicate-name/input.js
* general/object/input.js

# babel-plugin-transform-typescript (97/158)
# babel-plugin-transform-typescript (97/175)
* class/abstract-class-decorated-method/input.ts
* class/abstract-class-decorated-parameter/input.ts
* class/accessor-allowDeclareFields-false/input.ts
Expand All @@ -845,6 +843,23 @@ Passed: 352/1369
* class/parameter-properties-with-parameters/input.ts
* class/private-method-override-transform-private/input.ts
* class/transform-properties-declare-wrong-order/input.ts
* enum/boolean-value/input.ts
* enum/const/input.ts
* enum/constant-folding/input.ts
* enum/enum-merging-inner-references/input.ts
* enum/enum-merging-inner-references-shadow/input.ts
* enum/export/input.ts
* enum/inferred/input.ts
* enum/inner-references/input.ts
* enum/mix-references/input.ts
* enum/non-foldable-constant/input.ts
* enum/non-scoped/input.ts
* enum/outer-references/input.ts
* enum/scoped/input.ts
* enum/string-value/input.ts
* enum/string-value-template/input.ts
* enum/string-values-computed/input.ts
* enum/ts5.0-const-foldable/input.ts
* exports/declared-types/input.ts
* exports/export-const-enums/input.ts
* exports/export-type-star-from/input.ts
Expand Down
1 change: 1 addition & 0 deletions tasks/transform_conformance/src/test_case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ pub trait TestCase {
.get_plugin("transform-exponentiation-operator")
.is_some(),
shorthand_properties: options.get_plugin("transform-shorthand-properties").is_some(),
dotall_regex: options.get_plugin("transform-dotall-regex").is_some(),
sticky_regex: options.get_plugin("transform-sticky-regex").is_some(),
template_literals: options.get_plugin("transform-template-literals").is_some(),
property_literals: options.get_plugin("transform-property-literals").is_some(),
Expand Down

0 comments on commit 07f97e4

Please sign in to comment.