Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(transformer): Add babel-plugin-transform-dotall-regex #2774

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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};

/// ES2018: Dotall Regular Expression
///
/// 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
Loading