swc_ecma_utils/
constructor.rs1use 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 }
44
45 fn visit_mut_function(&mut self, _: &mut Function) {
46 }
48
49 fn visit_mut_getter_prop(&mut self, _: &mut GetterProp) {
50 }
52
53 fn visit_mut_setter_prop(&mut self, _: &mut SetterProp) {
54 }
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}