swc_ecma_compat_es2015/
sticky_regex.rs1use swc_ecma_ast::*;
2use swc_ecma_transforms_base::perf::Parallel;
3use swc_ecma_utils::{quote_ident, ExprFactory};
4use swc_ecma_visit::{noop_visit_mut_type, visit_mut_pass, VisitMut, VisitMutWith};
5use swc_trace_macro::swc_trace;
6
7pub fn sticky_regex() -> impl Pass {
22 visit_mut_pass(StickyRegex)
23}
24
25struct StickyRegex;
26
27impl Parallel for StickyRegex {
28 fn merge(&mut self, _: Self) {}
29
30 fn create(&self) -> Self {
31 StickyRegex
32 }
33}
34
35#[swc_trace]
36impl VisitMut for StickyRegex {
37 noop_visit_mut_type!(fail);
38
39 fn visit_mut_expr(&mut self, e: &mut Expr) {
40 e.visit_mut_children_with(self);
41
42 if let Expr::Lit(Lit::Regex(Regex { exp, flags, span })) = e {
43 if flags.contains('y') {
44 *e = NewExpr {
45 span: *span,
46 callee: Box::new(quote_ident!(Default::default(), *span, "RegExp").into()),
47 args: Some(vec![exp.clone().as_arg(), flags.clone().as_arg()]),
48 ..Default::default()
49 }
50 .into()
51 }
52 }
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use swc_ecma_transforms_testing::test;
59
60 use super::*;
61
62 test!(
63 ::swc_ecma_parser::Syntax::default(),
64 |_| sticky_regex(),
65 babel_basic,
66 "var re = /o\"'+/y;"
67 );
68
69 test!(
70 ::swc_ecma_parser::Syntax::default(),
71 |_| sticky_regex(),
72 babel_ignore_non_sticky,
73 "var re = /o+/;"
74 );
75}