swc_ecma_utils/
constructor.rs

1use std::{iter, mem};
2
3use swc_common::{util::take::Take, DUMMY_SP};
4use swc_ecma_ast::*;
5use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith};
6
7use crate::ExprFactory;
8
9pub fn inject_after_super(c: &mut Constructor, exprs: Vec<Box<Expr>>) {
10    if exprs.is_empty() {
11        return;
12    }
13
14    let body = c.body.as_mut().expect("constructor should have a body");
15
16    let mut injector = Injector {
17        exprs,
18        ..Default::default()
19    };
20
21    body.visit_mut_with(&mut injector);
22
23    if !injector.injected {
24        let exprs = injector.exprs.take();
25        body.stmts
26            .splice(0..0, exprs.into_iter().map(|e| e.into_stmt()));
27    }
28}
29
30#[derive(Default)]
31struct Injector {
32    exprs: Vec<Box<Expr>>,
33    ignore_return_value: bool,
34
35    injected: bool,
36}
37
38impl VisitMut for Injector {
39    noop_visit_mut_type!();
40
41    fn visit_mut_constructor(&mut self, _: &mut Constructor) {
42        // skip
43    }
44
45    fn visit_mut_function(&mut self, _: &mut Function) {
46        // skip
47    }
48
49    fn visit_mut_getter_prop(&mut self, _: &mut GetterProp) {
50        // skip
51    }
52
53    fn visit_mut_setter_prop(&mut self, _: &mut SetterProp) {
54        // skip
55    }
56
57    fn visit_mut_expr_stmt(&mut self, node: &mut ExprStmt) {
58        let ignore_return_value = mem::replace(&mut self.ignore_return_value, true);
59        node.visit_mut_children_with(self);
60        self.ignore_return_value = ignore_return_value;
61    }
62
63    fn visit_mut_seq_expr(&mut self, node: &mut SeqExpr) {
64        if let Some(mut tail) = node.exprs.pop() {
65            let ignore_return_value = mem::replace(&mut self.ignore_return_value, true);
66            node.visit_mut_children_with(self);
67            self.ignore_return_value = ignore_return_value;
68            tail.visit_mut_with(self);
69            node.exprs.push(tail);
70        }
71    }
72
73    fn visit_mut_expr(&mut self, node: &mut Expr) {
74        let ignore_return_value = self.ignore_return_value;
75        if !matches!(node, Expr::Paren(..) | Expr::Seq(..)) {
76            self.ignore_return_value = false;
77        }
78        node.visit_mut_children_with(self);
79        self.ignore_return_value = ignore_return_value;
80
81        if let Expr::Call(CallExpr {
82            callee: Callee::Super(..),
83            ..
84        }) = node
85        {
86            self.injected = true;
87
88            let super_call = node.take();
89            let exprs = self.exprs.clone();
90
91            let exprs = iter::once(Box::new(super_call)).chain(exprs);
92
93            *node = if ignore_return_value {
94                SeqExpr {
95                    span: DUMMY_SP,
96                    exprs: exprs.collect(),
97                }
98                .into()
99            } else {
100                let array = ArrayLit {
101                    span: DUMMY_SP,
102                    elems: exprs.map(ExprOrSpread::from).map(Some).collect(),
103                };
104
105                MemberExpr {
106                    span: DUMMY_SP,
107                    obj: array.into(),
108                    prop: ComputedPropName {
109                        span: DUMMY_SP,
110                        expr: 0.into(),
111                    }
112                    .into(),
113                }
114                .into()
115            }
116        }
117    }
118}