1use std::{collections::VecDeque, iter::once, mem::take};
2
3use rustc_hash::FxHashMap;
4use swc_atoms::{atom, Atom};
5use swc_common::{util::take::Take, Mark, Spanned, SyntaxContext, DUMMY_SP};
6use swc_ecma_ast::*;
7use swc_ecma_transforms_base::{helper, helper_expr};
8use swc_ecma_utils::{
9 alias_ident_for, constructor::inject_after_super, default_constructor_with_span,
10 is_maybe_branch_directive, private_ident, prop_name_to_expr_value, quote_ident, replace_ident,
11 stack_size::maybe_grow_default, ExprFactory, IdentRenamer,
12};
13use swc_ecma_visit::{noop_visit_mut_type, visit_mut_pass, VisitMut, VisitMutWith};
14
15use crate::DecoratorVersion;
16
17pub(crate) fn decorator_impl(version: DecoratorVersion) -> impl Pass {
18 visit_mut_pass(DecoratorPass {
19 version,
20 ..Default::default()
21 })
22}
23
24#[derive(Default)]
25struct DecoratorPass {
26 extra_vars: Vec<VarDeclarator>,
28
29 extra_lets: Vec<VarDeclarator>,
30
31 state: ClassState,
32
33 pre_class_inits: Vec<Box<Expr>>,
35
36 rename_map: FxHashMap<Id, Id>,
37
38 extra_exports: Vec<ExportSpecifier>,
39
40 #[allow(unused)]
41 version: DecoratorVersion,
42}
43
44#[derive(Default)]
45struct ClassState {
46 private_id_index: u32,
47
48 static_lhs: Vec<Ident>,
49 proto_lhs: Vec<Ident>,
50
51 init_proto: Option<Ident>,
53 init_proto_args: Vec<Option<ExprOrSpread>>,
54
55 init_static: Option<Ident>,
56 init_static_args: Vec<Option<ExprOrSpread>>,
57
58 extra_stmts: Vec<Stmt>,
60
61 class_lhs: Vec<Option<Pat>>,
62 class_decorators: Vec<Option<ExprOrSpread>>,
63
64 super_class: Option<Ident>,
65}
66
67impl DecoratorPass {
68 fn preserve_side_effect_of_decorators(
69 &mut self,
70 decorators: Vec<Decorator>,
71 ) -> Vec<Option<ExprOrSpread>> {
72 decorators
73 .into_iter()
74 .map(|e| Some(self.preserve_side_effect_of_decorator(e.expr).as_arg()))
75 .collect()
76 }
77
78 fn preserve_side_effect_of_decorator(&mut self, dec: Box<Expr>) -> Box<Expr> {
79 if dec.is_ident() || dec.is_arrow() || dec.is_fn_expr() {
80 return dec;
81 }
82
83 let ident = private_ident!("_dec");
84 self.extra_vars.push(VarDeclarator {
85 span: DUMMY_SP,
86 name: ident.clone().into(),
87 init: None,
88 definite: false,
89 });
90 self.pre_class_inits.push(
91 AssignExpr {
92 span: DUMMY_SP,
93 op: op!("="),
94 left: ident.clone().into(),
95 right: dec,
96 }
97 .into(),
98 );
99
100 ident.into()
101 }
102
103 fn consume_inits(&mut self) {
105 if self.state.init_proto_args.is_empty()
106 && self.state.init_static_args.is_empty()
107 && self.state.init_proto.is_none()
108 && self.state.init_static.is_none()
109 && self.state.class_decorators.is_empty()
110 {
111 return;
112 }
113
114 let mut e_lhs = Vec::new();
115 let mut combined_args = vec![ThisExpr { span: DUMMY_SP }.as_arg()];
116
117 for id in self
118 .state
119 .static_lhs
120 .drain(..)
121 .chain(self.state.proto_lhs.drain(..))
122 {
123 e_lhs.push(Some(id.into()));
124 }
125
126 if let Some(init) = self.state.init_proto.clone() {
127 self.extra_vars.push(VarDeclarator {
128 span: DUMMY_SP,
129 name: init.clone().into(),
130 init: None,
131 definite: false,
132 });
133
134 e_lhs.push(Some(init.into()));
135 }
136
137 if let Some(init) = self.state.init_static.clone() {
138 self.extra_vars.push(VarDeclarator {
139 span: DUMMY_SP,
140 name: init.clone().into(),
141 init: None,
142 definite: false,
143 });
144
145 e_lhs.push(Some(init.into()));
146 }
147
148 combined_args.push(
149 ArrayLit {
150 span: DUMMY_SP,
151 elems: self
152 .state
153 .init_static_args
154 .drain(..)
155 .chain(self.state.init_proto_args.drain(..))
156 .collect(),
157 }
158 .as_arg(),
159 );
160
161 combined_args.push(
162 ArrayLit {
163 span: DUMMY_SP,
164 elems: self.state.class_decorators.take(),
165 }
166 .as_arg(),
167 );
168
169 if let Some(super_class) = self.state.super_class.as_ref() {
170 combined_args.push(super_class.clone().as_arg());
171 }
172
173 let e_pat = if e_lhs.is_empty() {
174 None
175 } else {
176 Some(ObjectPatProp::KeyValue(KeyValuePatProp {
177 key: PropName::Ident(atom!("e").into()),
178 value: ArrayPat {
179 span: DUMMY_SP,
180 elems: e_lhs,
181 type_ann: Default::default(),
182 optional: false,
183 }
184 .into(),
185 }))
186 };
187
188 let c_pat = if self.state.class_lhs.is_empty() {
189 None
190 } else {
191 Some(ObjectPatProp::KeyValue(KeyValuePatProp {
192 key: PropName::Ident(atom!("c").into()),
193 value: ArrayPat {
194 span: DUMMY_SP,
195 elems: self.state.class_lhs.take(),
196 type_ann: Default::default(),
197 optional: false,
198 }
199 .into(),
200 }))
201 };
202
203 let expr = AssignExpr {
204 span: DUMMY_SP,
205 op: op!("="),
206 left: ObjectPat {
207 span: DUMMY_SP,
208 props: e_pat.into_iter().chain(c_pat).collect(),
209 optional: false,
210 type_ann: None,
211 }
212 .into(),
213 right: Box::new(
214 CallExpr {
215 span: DUMMY_SP,
216 callee: helper!(apply_decs_2203_r),
217 args: combined_args,
218 ..Default::default()
219 }
220 .into(),
221 ),
222 }
223 .into();
224
225 self.state.extra_stmts.push(
226 ExprStmt {
227 span: DUMMY_SP,
228 expr,
229 }
230 .into(),
231 );
232
233 if let Some(init) = self.state.init_static.take() {
234 self.state.extra_stmts.push(
235 ExprStmt {
236 span: DUMMY_SP,
237 expr: CallExpr {
238 span: DUMMY_SP,
239 callee: init.as_callee(),
240 args: vec![ThisExpr { span: DUMMY_SP }.as_arg()],
241 ..Default::default()
242 }
243 .into(),
244 }
245 .into(),
246 );
247 }
248 }
249
250 fn initializer_name(&mut self, name: &mut PropName, prefix: &str) -> (Box<Expr>, Ident) {
252 match name {
253 PropName::Ident(i) => (
254 Lit::Str(Str {
255 span: i.span,
256 value: i.sym.clone().into(),
257 raw: None,
258 })
259 .into(),
260 Ident::new(
261 format!("_{prefix}_{}", i.sym).into(),
262 i.span,
263 SyntaxContext::empty().apply_mark(Mark::new()),
264 ),
265 ),
266 PropName::Computed(c) if c.expr.is_ident() => match &*c.expr {
267 Expr::Ident(i) => (
268 i.clone().into(),
269 Ident::new(
270 format!("_{prefix}_{}", i.sym).into(),
271 i.span,
272 SyntaxContext::empty().apply_mark(Mark::new()),
273 ),
274 ),
275 _ => {
276 unreachable!()
277 }
278 },
279 _ => {
280 let key_ident = private_ident!(name.span(), "_computedKey");
281 self.extra_vars.push(VarDeclarator {
282 span: DUMMY_SP,
283 name: key_ident.clone().into(),
284 init: None,
285 definite: false,
286 });
287
288 self.pre_class_inits.push(
289 AssignExpr {
290 span: DUMMY_SP,
291 op: op!("="),
292 left: key_ident.clone().into(),
293 right: Box::new(prop_name_to_expr_value(name.take())),
294 }
295 .into(),
296 );
297 *name = PropName::Computed(ComputedPropName {
298 span: DUMMY_SP,
299 expr: key_ident.clone().into(),
300 });
301
302 let init = Ident::new(
303 format!("_{prefix}_computedKey").into(),
304 key_ident.span,
305 SyntaxContext::empty().apply_mark(Mark::new()),
306 );
307
308 (key_ident.into(), init)
309 }
310 }
311 }
312
313 fn ensure_constructor<'a>(&mut self, c: &'a mut Class) -> &'a mut Constructor {
314 let mut insert_index = 0;
315 for (i, member) in c.body.iter().enumerate() {
316 if let ClassMember::Constructor(constructor) = member {
317 if constructor.body.is_some() {
319 if let Some(ClassMember::Constructor(c)) = c.body.get_mut(i) {
320 return c;
321 } else {
322 unreachable!()
323 }
324 } else {
325 insert_index = i + 1;
326 }
327 }
328 }
329
330 c.body.insert(
331 insert_index,
332 default_constructor_with_span(c.super_class.is_some(), c.span).into(),
333 );
334
335 if let Some(ClassMember::Constructor(c)) = c.body.get_mut(insert_index) {
336 c
337 } else {
338 unreachable!()
339 }
340 }
341
342 fn ensure_identity_constructor<'a>(&mut self, c: &'a mut Class) -> &'a mut Constructor {
343 let mut insert_index = 0;
344 for (i, member) in c.body.iter().enumerate() {
345 if let ClassMember::Constructor(constructor) = member {
346 if constructor.body.is_some() {
348 if let Some(ClassMember::Constructor(c)) = c.body.get_mut(i) {
349 return c;
350 } else {
351 unreachable!()
352 }
353 } else {
354 insert_index = i + 1;
355 }
356 }
357 }
358
359 c.body.insert(
360 insert_index,
361 ClassMember::Constructor(Constructor {
362 span: DUMMY_SP,
363 key: PropName::Ident(atom!("constructor").into()),
364 params: Vec::new(),
365 body: Some(BlockStmt {
366 span: DUMMY_SP,
367 stmts: Vec::new(),
368 ..Default::default()
369 }),
370 ..Default::default()
371 }),
372 );
373
374 if let Some(ClassMember::Constructor(c)) = c.body.get_mut(insert_index) {
375 c
376 } else {
377 unreachable!()
378 }
379 }
380
381 fn handle_super_class(&mut self, class: &mut Class) {
382 if let Some(super_class) = class.super_class.take() {
383 let id = alias_ident_for(&super_class, "_super");
384 self.extra_vars.push(VarDeclarator {
385 span: DUMMY_SP,
386 name: id.clone().into(),
387 init: None,
388 definite: false,
389 });
390
391 class.super_class = Some(
392 AssignExpr {
393 span: DUMMY_SP,
394 op: AssignOp::Assign,
395 left: id.clone().into(),
396 right: super_class,
397 }
398 .into(),
399 );
400
401 self.state.super_class = Some(id);
402 }
403 }
404
405 fn handle_class_expr(&mut self, class: &mut Class, ident: Option<&Ident>) -> Ident {
406 debug_assert!(
407 !class.decorators.is_empty(),
408 "handle_class_decorator should be called only when decorators are present"
409 );
410
411 let init_class = private_ident!("_initClass");
412
413 self.extra_vars.push(VarDeclarator {
414 span: DUMMY_SP,
415 name: init_class.clone().into(),
416 init: None,
417 definite: false,
418 });
419
420 let new_class_name = ident.as_ref().map_or_else(
421 || private_ident!("_class"),
422 |i| private_ident!(format!("_{}", i.sym)),
423 );
424
425 if let Some(ident) = ident {
426 replace_ident(&mut class.body, ident.to_id(), &new_class_name);
427 }
428
429 self.state
430 .class_lhs
431 .push(Some(new_class_name.clone().into()));
432 self.state.class_lhs.push(Some(init_class.clone().into()));
433
434 self.extra_vars.push(VarDeclarator {
435 span: DUMMY_SP,
436 name: new_class_name.clone().into(),
437 init: None,
438 definite: false,
439 });
440
441 let decorators = self.preserve_side_effect_of_decorators(class.decorators.take());
442 self.state.class_decorators.extend(decorators);
443 self.handle_super_class(class);
444
445 {
446 let call_stmt = CallExpr {
447 span: DUMMY_SP,
448 callee: init_class.as_callee(),
449 args: Vec::new(),
450 ..Default::default()
451 }
452 .into_stmt();
453
454 class.body.push(ClassMember::StaticBlock(StaticBlock {
455 span: DUMMY_SP,
456 body: BlockStmt {
457 span: DUMMY_SP,
458 stmts: vec![call_stmt],
459 ..Default::default()
460 },
461 }));
462 }
463
464 new_class_name
465 }
466
467 fn handle_class_decl(&mut self, c: &mut ClassDecl) -> Stmt {
469 let old_state = take(&mut self.state);
470
471 let decorators = self.preserve_side_effect_of_decorators(c.class.decorators.take());
472
473 let init_class = private_ident!("_initClass");
474
475 self.extra_vars.push(VarDeclarator {
476 span: DUMMY_SP,
477 name: init_class.clone().into(),
478 init: None,
479 definite: false,
480 });
481
482 let preserved_class_name = c.ident.clone().into_private();
483 let new_class_name = private_ident!(format!("_{}", c.ident.sym));
484
485 self.extra_lets.push(VarDeclarator {
486 span: DUMMY_SP,
487 name: new_class_name.clone().into(),
488 init: None,
489 definite: false,
490 });
491
492 self.rename_map
493 .insert(c.ident.to_id(), new_class_name.to_id());
494
495 self.state
496 .class_lhs
497 .push(Some(new_class_name.clone().into()));
498 self.state.class_lhs.push(Some(init_class.clone().into()));
499
500 self.state.class_decorators.extend(decorators);
501 self.handle_super_class(&mut c.class);
502
503 let mut body = c.class.body.take();
504
505 let has_static_member = body.iter().any(|m| match m {
506 ClassMember::Method(m) => m.is_static,
507 ClassMember::PrivateMethod(m) => m.is_static,
508 ClassMember::AutoAccessor(m) => m.is_static,
509 ClassMember::ClassProp(ClassProp { is_static, .. })
510 | ClassMember::PrivateProp(PrivateProp { is_static, .. }) => *is_static,
511 ClassMember::StaticBlock(_) => true,
512 _ => false,
513 });
514
515 if has_static_member {
516 let mut last_static_block = None;
517
518 self.process_decorators_of_class_members(&mut body);
519
520 for m in body.iter_mut() {
522 match m {
523 ClassMember::ClassProp(ClassProp { value, .. })
524 | ClassMember::PrivateProp(PrivateProp { value, .. }) => {
525 if let Some(value) = value {
526 if let Some(last_static_block) = last_static_block.take() {
527 **value = SeqExpr {
528 span: DUMMY_SP,
529 exprs: vec![
530 Box::new(Expr::Call(CallExpr {
531 span: DUMMY_SP,
532 callee: ArrowExpr {
533 span: DUMMY_SP,
534 params: Vec::new(),
535 body: Box::new(BlockStmtOrExpr::BlockStmt(
536 BlockStmt {
537 span: DUMMY_SP,
538 stmts: last_static_block,
539 ..Default::default()
540 },
541 )),
542 is_async: false,
543 is_generator: false,
544 ..Default::default()
545 }
546 .as_callee(),
547 args: Vec::new(),
548 ..Default::default()
549 })),
550 value.take(),
551 ],
552 }
553 .into()
554 }
555 }
556 }
557 ClassMember::StaticBlock(s) => match &mut last_static_block {
558 None => {
559 last_static_block = Some(s.body.stmts.take());
560 }
561 Some(v) => {
562 v.append(&mut s.body.stmts);
563 }
564 },
565 _ => {}
566 }
567 }
568
569 body.retain(|m| !matches!(m, ClassMember::StaticBlock(..) | ClassMember::Empty(..)));
571
572 for m in body.iter_mut() {
573 match m {
574 ClassMember::ClassProp(..)
575 | ClassMember::PrivateProp(..)
576 | ClassMember::AutoAccessor(..) => {
577 replace_ident(m, c.ident.to_id(), &new_class_name);
578 }
579
580 _ => {}
581 }
582 }
583
584 let mut inner_class = ClassDecl {
585 ident: c.ident.clone(),
586 declare: Default::default(),
587 class: Box::new(Class {
588 span: DUMMY_SP,
589 decorators: Vec::new(),
590 body,
591 super_class: c.class.super_class.take(),
592 ..Default::default()
593 }),
594 };
595
596 inner_class.class.visit_mut_with(self);
597
598 for m in inner_class.class.body.iter_mut() {
599 let mut should_move = false;
600
601 match m {
602 ClassMember::PrivateProp(p) => {
603 if p.is_static {
604 should_move = true;
605 p.is_static = false;
606 }
607 }
608 ClassMember::PrivateMethod(p) => {
609 if p.is_static {
610 should_move = true;
611 p.is_static = false;
612 }
613 }
614
615 ClassMember::AutoAccessor(p) => {
616 if p.is_static {
617 should_move = true;
618 p.is_static = false;
619 }
620 }
621 _ => (),
622 }
623
624 if should_move {
625 c.class.body.push(m.take())
626 }
627 }
628
629 c.class.body.insert(
630 0,
631 ClassMember::StaticBlock(StaticBlock {
632 span: DUMMY_SP,
633 body: BlockStmt {
634 span: DUMMY_SP,
635 stmts: vec![Stmt::Decl(Decl::Class(inner_class))],
636 ..Default::default()
637 },
638 }),
639 );
640
641 replace_ident(&mut c.class, c.ident.to_id(), &preserved_class_name);
642
643 {
644 let constructor = self.ensure_identity_constructor(&mut c.class);
645
646 let super_call = CallExpr {
647 span: DUMMY_SP,
648 callee: Callee::Super(Super { span: DUMMY_SP }),
649 args: vec![c.ident.clone().as_arg()],
650 ..Default::default()
651 }
652 .into();
653 let static_call = last_static_block.map(|last| {
654 CallExpr {
655 span: DUMMY_SP,
656 callee: ArrowExpr {
657 span: DUMMY_SP,
658 params: Vec::new(),
659 body: Box::new(BlockStmtOrExpr::BlockStmt(BlockStmt {
660 span: DUMMY_SP,
661 stmts: last,
662 ..Default::default()
663 })),
664 is_async: false,
665 is_generator: false,
666 ..Default::default()
667 }
668 .as_callee(),
669 args: Vec::new(),
670 ..Default::default()
671 }
672 .into()
673 });
674
675 let init_class_call = CallExpr {
676 span: DUMMY_SP,
677 callee: init_class.as_callee(),
678 args: Vec::new(),
679 ..Default::default()
680 }
681 .into();
682
683 constructor.body.as_mut().unwrap().stmts.insert(
684 0,
685 SeqExpr {
686 span: DUMMY_SP,
687 exprs: once(super_call)
688 .chain(static_call)
689 .chain(once(init_class_call))
690 .collect(),
691 }
692 .into_stmt(),
693 );
694 }
695
696 let class = Box::new(Class {
697 span: DUMMY_SP,
698 decorators: Vec::new(),
699 body: c.class.body.take(),
700 super_class: Some(Box::new(helper_expr!(identity))),
701 ..Default::default()
702 });
703
704 self.state = old_state;
705
706 return NewExpr {
707 span: DUMMY_SP,
708 callee: ClassExpr { ident: None, class }.into(),
709 args: Some(Vec::new()),
710 ..Default::default()
711 }
712 .into_stmt();
713 }
714 for m in body.iter_mut() {
715 if let ClassMember::Constructor(..) = m {
716 c.class.body.push(m.take());
717 }
718 }
719 body.visit_mut_with(self);
720 c.ident = preserved_class_name.clone();
721 replace_ident(&mut c.class, c.ident.to_id(), &preserved_class_name);
722 c.class.body.extend(body);
723 c.visit_mut_with(self);
724 c.class.body.push(ClassMember::StaticBlock(StaticBlock {
725 span: DUMMY_SP,
726 body: BlockStmt {
727 span: DUMMY_SP,
728 stmts: vec![CallExpr {
729 span: DUMMY_SP,
730 callee: init_class.as_callee(),
731 args: Vec::new(),
732 ..Default::default()
733 }
734 .into_stmt()],
735 ..Default::default()
736 },
737 }));
738 self.state = old_state;
739
740 c.take().into()
741 }
742
743 fn process_decorators(&mut self, decorators: &mut [Decorator]) {
744 decorators.iter_mut().for_each(|dec| {
745 let e = self.preserve_side_effect_of_decorator(dec.expr.take());
746
747 dec.expr = e;
748 })
749 }
750
751 fn process_prop_name(&mut self, name: &mut PropName) {
752 match name {
753 PropName::Ident(..) => {}
754 PropName::Computed(c) if c.expr.is_ident() => {}
755 _ => {
756 let ident = private_ident!("_computedKey");
757 self.extra_vars.push(VarDeclarator {
758 span: DUMMY_SP,
759 name: ident.clone().into(),
760 init: None,
761 definite: false,
762 });
763
764 self.pre_class_inits.push(
765 AssignExpr {
766 span: DUMMY_SP,
767 op: op!("="),
768 left: ident.clone().into(),
769 right: Box::new(prop_name_to_expr_value(name.take())),
770 }
771 .into(),
772 );
773 *name = PropName::Computed(ComputedPropName {
774 span: DUMMY_SP,
775 expr: ident.into(),
776 });
777 }
778 }
779 }
780
781 fn process_decorators_of_class_members(&mut self, members: &mut [ClassMember]) {
782 for mut m in members {
783 match &mut m {
784 ClassMember::Method(m) if m.function.body.is_some() => {
785 self.process_decorators(&mut m.function.decorators);
786 self.process_prop_name(&mut m.key);
787 }
788 ClassMember::PrivateMethod(m) if m.function.body.is_some() => {
789 self.process_decorators(&mut m.function.decorators);
790 }
791 ClassMember::ClassProp(m) if !m.declare => {
792 self.process_decorators(&mut m.decorators);
793 self.process_prop_name(&mut m.key);
794 }
795 ClassMember::PrivateProp(m) => {
796 self.process_decorators(&mut m.decorators);
797 }
798 ClassMember::AutoAccessor(m) => {
799 self.process_decorators(&mut m.decorators);
800 }
801
802 _ => {}
803 }
804 }
805 }
806}
807
808impl VisitMut for DecoratorPass {
809 noop_visit_mut_type!();
810
811 fn visit_mut_class(&mut self, n: &mut Class) {
812 let old_stmts = self.state.extra_stmts.take();
813
814 n.visit_mut_children_with(self);
815
816 if let Some(init_proto) = self.state.init_proto.clone() {
817 let init_proto_expr = CallExpr {
818 span: DUMMY_SP,
819 callee: init_proto.clone().as_callee(),
820 args: vec![ThisExpr { span: DUMMY_SP }.as_arg()],
821 ..Default::default()
822 };
823 let mut proto_inited = false;
824 for member in n.body.iter_mut() {
825 if let ClassMember::ClassProp(prop) = member {
826 if prop.is_static {
827 continue;
828 }
829 if let Some(value) = prop.value.clone() {
830 prop.value = Some(Expr::from_exprs(vec![
831 init_proto_expr.clone().into(),
832 value,
833 ]));
834
835 proto_inited = true;
836 break;
837 }
838 } else if let ClassMember::PrivateProp(prop) = member {
839 if prop.is_static {
840 continue;
841 }
842 if let Some(value) = prop.value.clone() {
843 prop.value = Some(Expr::from_exprs(vec![
844 init_proto_expr.clone().into(),
845 value,
846 ]));
847
848 proto_inited = true;
849 break;
850 }
851 }
852 }
853
854 if !proto_inited {
855 let c = self.ensure_constructor(n);
856
857 inject_after_super(c, vec![Box::new(init_proto_expr.into())])
858 }
859 }
860
861 self.consume_inits();
862
863 if !self.state.extra_stmts.is_empty() {
864 n.body.insert(
865 0,
866 ClassMember::StaticBlock(StaticBlock {
867 span: DUMMY_SP,
868 body: BlockStmt {
869 span: DUMMY_SP,
870 stmts: self.state.extra_stmts.take(),
871 ..Default::default()
872 },
873 }),
874 );
875 }
876
877 self.state.init_proto = None;
878
879 self.state.extra_stmts = old_stmts;
880 }
881
882 fn visit_mut_class_member(&mut self, n: &mut ClassMember) {
883 n.visit_mut_children_with(self);
884
885 if let ClassMember::PrivateMethod(p) = n {
886 if p.function.decorators.is_empty() {
887 return;
888 }
889
890 let decorators = self.preserve_side_effect_of_decorators(p.function.decorators.take());
891 let dec = merge_decorators(decorators);
892
893 let init = private_ident!(format!("_call_{}", p.key.name));
894
895 self.extra_vars.push(VarDeclarator {
896 span: p.span,
897 name: init.clone().into(),
898 init: None,
899 definite: false,
900 });
901
902 if p.is_static {
903 self.state
904 .init_static
905 .get_or_insert_with(|| private_ident!("_initStatic"));
906 } else {
907 self.state
908 .init_proto
909 .get_or_insert_with(|| private_ident!("_initProto"));
910 }
911
912 let caller = FnExpr {
913 ident: None,
914 function: p.function.clone(),
915 };
916
917 let arg = Some(
918 ArrayLit {
919 span: DUMMY_SP,
920 elems: vec![
921 dec,
922 Some(
923 if p.is_static {
924 match p.kind {
925 MethodKind::Method => 7,
926 MethodKind::Setter => 9,
927 MethodKind::Getter => 8,
928 #[cfg(swc_ast_unknown)]
929 _ => panic!("unable to access unknown nodes"),
930 }
931 } else {
932 match p.kind {
933 MethodKind::Method => 2,
934 MethodKind::Setter => 4,
935 MethodKind::Getter => 3,
936 #[cfg(swc_ast_unknown)]
937 _ => panic!("unable to access unknown nodes"),
938 }
939 }
940 .as_arg(),
941 ),
942 Some(p.key.name.clone().as_arg()),
943 Some(caller.as_arg()),
944 ],
945 }
946 .as_arg(),
947 );
948 if p.is_static {
949 self.state.init_static_args.push(arg);
950 } else {
951 self.state.init_proto_args.push(arg);
952 }
953
954 if p.is_static {
955 self.state.static_lhs.push(init.clone());
956 } else {
957 self.state.proto_lhs.push(init.clone());
958 }
959
960 match p.kind {
961 MethodKind::Method => {
962 let call_stmt = ReturnStmt {
963 span: DUMMY_SP,
964 arg: Some(init.into()),
965 }
966 .into();
967
968 p.kind = MethodKind::Getter;
969 p.function.body = Some(BlockStmt {
970 span: DUMMY_SP,
971 stmts: vec![call_stmt],
972 ..Default::default()
973 });
974 }
975 MethodKind::Getter => {
976 let call_stmt = ReturnStmt {
977 span: DUMMY_SP,
978 arg: Some(
979 CallExpr {
980 span: DUMMY_SP,
981 callee: init.as_callee(),
982 args: vec![ThisExpr { span: DUMMY_SP }.as_arg()],
983 ..Default::default()
984 }
985 .into(),
986 ),
987 }
988 .into();
989
990 p.function.body = Some(BlockStmt {
991 span: DUMMY_SP,
992 stmts: vec![call_stmt],
993 ..Default::default()
994 });
995 }
996 MethodKind::Setter => {
997 let call_stmt = ReturnStmt {
998 span: DUMMY_SP,
999 arg: Some(
1000 CallExpr {
1001 span: DUMMY_SP,
1002 callee: init.as_callee(),
1003 args: vec![
1004 ThisExpr { span: DUMMY_SP }.as_arg(),
1005 Ident::from(p.function.params[0].pat.as_ident().unwrap())
1006 .as_arg(),
1007 ],
1008 ..Default::default()
1009 }
1010 .into(),
1011 ),
1012 }
1013 .into();
1014
1015 p.function.body = Some(BlockStmt {
1016 span: DUMMY_SP,
1017 stmts: vec![call_stmt],
1018 ..Default::default()
1019 });
1020 }
1021 #[cfg(swc_ast_unknown)]
1022 _ => panic!("unable to access unknown nodes"),
1023 }
1024 }
1025 }
1026
1027 fn visit_mut_class_members(&mut self, members: &mut Vec<ClassMember>) {
1028 let mut new = Vec::with_capacity(members.len());
1029
1030 self.process_decorators_of_class_members(members);
1031
1032 for mut m in members.take() {
1033 match m {
1034 ClassMember::AutoAccessor(mut accessor) => {
1035 accessor.value.visit_mut_with(self);
1036
1037 let name;
1038 let init;
1039 let field_name_like: Atom;
1040 let private_field = PrivateProp {
1041 span: DUMMY_SP,
1042 key: match &mut accessor.key {
1043 Key::Private(k) => {
1044 name = Lit::Str(Str {
1045 span: DUMMY_SP,
1046 value: k.name.clone().into(),
1047 raw: None,
1048 })
1049 .into();
1050 init = private_ident!(format!("_init_{}", k.name));
1051 field_name_like = format!("__{}", k.name).into();
1052
1053 self.state.private_id_index += 1;
1054 PrivateName {
1055 span: k.span,
1056 name: format!("__{}_{}", k.name, self.state.private_id_index)
1057 .into(),
1058 }
1059 }
1060 Key::Public(k) => {
1061 (name, init) = self.initializer_name(k, "init");
1062 field_name_like = format!("__{}", init.sym)
1063 .replacen("init", "private", 1)
1064 .into();
1065
1066 self.state.private_id_index += 1;
1067
1068 PrivateName {
1069 span: init.span,
1070 name: format!(
1071 "{field_name_like}_{}",
1072 self.state.private_id_index
1073 )
1074 .into(),
1075 }
1076 }
1077 #[cfg(swc_ast_unknown)]
1078 _ => panic!("unable to access unknown nodes"),
1079 },
1080 value: if accessor.decorators.is_empty() {
1081 accessor.value
1082 } else {
1083 let init_call = CallExpr {
1084 span: DUMMY_SP,
1085 callee: init.clone().as_callee(),
1086 args: once(ThisExpr { span: DUMMY_SP }.as_arg())
1087 .chain(accessor.value.take().map(|v| v.as_arg()))
1088 .collect(),
1089 ..Default::default()
1090 }
1091 .into();
1092
1093 Some(init_call)
1094 },
1095 type_ann: None,
1096 is_static: accessor.is_static,
1097 decorators: Default::default(),
1098 accessibility: Default::default(),
1099 is_optional: false,
1100 is_override: false,
1101 readonly: false,
1102 definite: false,
1103 ctxt: Default::default(),
1104 };
1105
1106 let mut getter_function = Box::new(Function {
1107 params: Default::default(),
1108 decorators: Default::default(),
1109 span: DUMMY_SP,
1110 body: Some(BlockStmt {
1111 span: DUMMY_SP,
1112 stmts: vec![Stmt::Return(ReturnStmt {
1113 span: DUMMY_SP,
1114 arg: Some(Box::new(Expr::Member(MemberExpr {
1115 span: DUMMY_SP,
1116 obj: ThisExpr { span: DUMMY_SP }.into(),
1117 prop: MemberProp::PrivateName(private_field.key.clone()),
1118 }))),
1119 })],
1120 ..Default::default()
1121 }),
1122 is_generator: false,
1123 is_async: false,
1124 ..Default::default()
1125 });
1126 let mut setter_function = {
1127 let param = private_ident!("_v");
1128
1129 Box::new(Function {
1130 params: vec![Param {
1131 span: DUMMY_SP,
1132 decorators: Default::default(),
1133 pat: param.clone().into(),
1134 }],
1135 decorators: Default::default(),
1136 span: DUMMY_SP,
1137 body: Some(BlockStmt {
1138 span: DUMMY_SP,
1139 stmts: vec![Stmt::Expr(ExprStmt {
1140 span: DUMMY_SP,
1141 expr: Box::new(Expr::Assign(AssignExpr {
1142 span: DUMMY_SP,
1143 op: op!("="),
1144 left: MemberExpr {
1145 span: DUMMY_SP,
1146 obj: ThisExpr { span: DUMMY_SP }.into(),
1147 prop: MemberProp::PrivateName(
1148 private_field.key.clone(),
1149 ),
1150 }
1151 .into(),
1152 right: param.clone().into(),
1153 })),
1154 })],
1155 ..Default::default()
1156 }),
1157 is_generator: false,
1158 is_async: false,
1159 ..Default::default()
1160 })
1161 };
1162
1163 if !accessor.decorators.is_empty() {
1164 let decorators =
1165 self.preserve_side_effect_of_decorators(accessor.decorators.take());
1166 let dec = merge_decorators(decorators);
1167
1168 self.extra_vars.push(VarDeclarator {
1169 span: accessor.span,
1170 name: init.clone().into(),
1171 init: None,
1172 definite: false,
1173 });
1174
1175 let (getter_var, setter_var) = match &accessor.key {
1176 Key::Private(_) => (
1177 Some(private_ident!(format!("_get_{}", field_name_like))),
1178 Some(private_ident!(format!("_set_{}", field_name_like))),
1179 ),
1180 Key::Public(_) => Default::default(),
1181 #[cfg(swc_ast_unknown)]
1182 _ => panic!("unable to access unknown nodes"),
1183 };
1184
1185 let initialize_init = {
1186 ArrayLit {
1187 span: DUMMY_SP,
1188 elems: match &accessor.key {
1189 Key::Private(_) => {
1190 let data = vec![
1191 dec,
1192 Some(if accessor.is_static {
1193 6.as_arg()
1194 } else {
1195 1.as_arg()
1196 }),
1197 Some(name.as_arg()),
1198 Some(
1199 FnExpr {
1200 ident: None,
1201 function: getter_function,
1202 }
1203 .as_arg(),
1204 ),
1205 Some(
1206 FnExpr {
1207 ident: None,
1208 function: setter_function,
1209 }
1210 .as_arg(),
1211 ),
1212 ];
1213
1214 self.extra_vars.push(VarDeclarator {
1215 span: DUMMY_SP,
1216 name: getter_var.clone().unwrap().into(),
1217 init: None,
1218 definite: false,
1219 });
1220 self.extra_vars.push(VarDeclarator {
1221 span: DUMMY_SP,
1222 name: setter_var.clone().unwrap().into(),
1223 init: None,
1224 definite: false,
1225 });
1226
1227 getter_function = Box::new(Function {
1228 params: Vec::new(),
1229 span: DUMMY_SP,
1230 body: Some(BlockStmt {
1231 span: DUMMY_SP,
1232 stmts: vec![Stmt::Return(ReturnStmt {
1233 span: DUMMY_SP,
1234 arg: Some(Box::new(Expr::Call(CallExpr {
1235 span: DUMMY_SP,
1236 callee: getter_var
1237 .clone()
1238 .unwrap()
1239 .as_callee(),
1240 args: vec![
1241 ThisExpr { span: DUMMY_SP }.as_arg()
1242 ],
1243 ..Default::default()
1244 }))),
1245 })],
1246 ..Default::default()
1247 }),
1248 is_generator: false,
1249 is_async: false,
1250 ..Default::default()
1251 });
1252
1253 let param = private_ident!("_v");
1254
1255 setter_function = Box::new(Function {
1256 params: vec![Param {
1257 span: DUMMY_SP,
1258 decorators: Default::default(),
1259 pat: param.clone().into(),
1260 }],
1261 decorators: Default::default(),
1262 span: DUMMY_SP,
1263 body: Some(BlockStmt {
1264 span: DUMMY_SP,
1265 stmts: vec![Stmt::Expr(ExprStmt {
1266 span: DUMMY_SP,
1267 expr: Box::new(Expr::Call(CallExpr {
1268 span: DUMMY_SP,
1269 callee: setter_var
1270 .clone()
1271 .unwrap()
1272 .as_callee(),
1273 args: vec![
1274 ThisExpr { span: DUMMY_SP }.as_arg(),
1275 param.as_arg(),
1276 ],
1277 ..Default::default()
1278 })),
1279 })],
1280 ..Default::default()
1281 }),
1282 is_generator: false,
1283 is_async: false,
1284 ..Default::default()
1285 });
1286
1287 data
1288 }
1289 Key::Public(_) => {
1290 vec![
1291 dec,
1292 Some(if accessor.is_static {
1293 6.as_arg()
1294 } else {
1295 1.as_arg()
1296 }),
1297 Some(name.as_arg()),
1298 ]
1299 }
1300 #[cfg(swc_ast_unknown)]
1301 _ => panic!("unable to access unknown nodes"),
1302 },
1303 }
1304 .as_arg()
1305 };
1306
1307 if accessor.is_static {
1308 self.state.static_lhs.push(init);
1309 self.state.init_static_args.push(Some(initialize_init));
1310 self.state
1311 .static_lhs
1312 .extend(getter_var.into_iter().chain(setter_var));
1313 } else {
1314 self.state.proto_lhs.push(init);
1315 self.state.init_proto_args.push(Some(initialize_init));
1316 self.state
1317 .proto_lhs
1318 .extend(getter_var.into_iter().chain(setter_var));
1319 }
1320
1321 if accessor.is_static {
1322 self.state
1323 .init_static
1324 .get_or_insert_with(|| private_ident!("_initStatic"));
1325 } else {
1326 self.state
1327 .init_proto
1328 .get_or_insert_with(|| private_ident!("_initProto"));
1329 }
1330 }
1331
1332 match accessor.key {
1333 Key::Private(key) => {
1334 let getter = PrivateMethod {
1335 span: DUMMY_SP,
1336 key: key.clone(),
1337 function: getter_function,
1338 kind: MethodKind::Getter,
1339 is_static: accessor.is_static,
1340 accessibility: None,
1341 is_abstract: false,
1342 is_optional: false,
1343 is_override: false,
1344 };
1345 let setter = PrivateMethod {
1346 span: DUMMY_SP,
1347 key: key.clone(),
1348 function: setter_function,
1349 kind: MethodKind::Setter,
1350 is_static: accessor.is_static,
1351 accessibility: None,
1352 is_abstract: false,
1353 is_optional: false,
1354 is_override: false,
1355 };
1356
1357 new.push(ClassMember::PrivateProp(private_field));
1358 new.push(ClassMember::PrivateMethod(getter));
1359 new.push(ClassMember::PrivateMethod(setter));
1360 }
1361 Key::Public(key) => {
1362 let getter = ClassMethod {
1363 span: DUMMY_SP,
1364 key: key.clone(),
1365 function: getter_function,
1366 kind: MethodKind::Getter,
1367 is_static: accessor.is_static,
1368 accessibility: None,
1369 is_abstract: false,
1370 is_optional: false,
1371 is_override: false,
1372 };
1373 let setter = ClassMethod {
1374 span: DUMMY_SP,
1375 key: key.clone(),
1376 function: setter_function,
1377 kind: MethodKind::Setter,
1378 is_static: accessor.is_static,
1379 accessibility: None,
1380 is_abstract: false,
1381 is_optional: false,
1382 is_override: false,
1383 };
1384
1385 new.push(ClassMember::PrivateProp(private_field));
1386 new.push(ClassMember::Method(getter));
1387 new.push(ClassMember::Method(setter));
1388 }
1389 #[cfg(swc_ast_unknown)]
1390 _ => panic!("unable to access unknown nodes"),
1391 }
1392
1393 continue;
1394 }
1395
1396 ClassMember::Method(..) | ClassMember::PrivateMethod(..) => {
1397 m.visit_mut_with(self);
1398 }
1399
1400 _ => {}
1401 }
1402
1403 new.push(m);
1404 }
1405
1406 for mut m in new.take() {
1407 match m {
1408 ClassMember::Method(..)
1409 | ClassMember::PrivateMethod(..)
1410 | ClassMember::AutoAccessor(..) => {}
1411
1412 _ => {
1413 if !m.span().is_dummy() {
1414 m.visit_mut_with(self);
1415 }
1416 }
1417 }
1418
1419 new.push(m);
1420 }
1421
1422 *members = new;
1423 }
1424
1425 fn visit_mut_class_method(&mut self, n: &mut ClassMethod) {
1426 if n.function.body.is_none() {
1428 return;
1429 }
1430
1431 n.visit_mut_children_with(self);
1432
1433 if n.function.decorators.is_empty() {
1434 return;
1435 }
1436
1437 let decorators = self.preserve_side_effect_of_decorators(n.function.decorators.take());
1438 let dec = merge_decorators(decorators);
1439
1440 let (name, _init) = self.initializer_name(&mut n.key, "call");
1441
1442 if n.is_static {
1443 self.state
1444 .init_static
1445 .get_or_insert_with(|| private_ident!("_initStatic"));
1446 } else {
1447 self.state
1448 .init_proto
1449 .get_or_insert_with(|| private_ident!("_initProto"));
1450 }
1451
1452 let arg = Some(
1453 ArrayLit {
1454 span: DUMMY_SP,
1455 elems: vec![
1456 dec,
1457 Some(
1458 match (n.is_static, n.kind) {
1459 (true, MethodKind::Method) => 7,
1460 (false, MethodKind::Method) => 2,
1461 (true, MethodKind::Setter) => 9,
1462 (false, MethodKind::Setter) => 4,
1463 (true, MethodKind::Getter) => 8,
1464 (false, MethodKind::Getter) => 3,
1465 #[cfg(swc_ast_unknown)]
1466 _ => panic!("unable to access unknown nodes"),
1467 }
1468 .as_arg(),
1469 ),
1470 Some(name.as_arg()),
1471 ],
1472 }
1473 .as_arg(),
1474 );
1475 if n.is_static {
1476 self.state.init_static_args.push(arg);
1477 } else {
1478 self.state.init_proto_args.push(arg);
1479 }
1480 }
1481
1482 fn visit_mut_class_prop(&mut self, p: &mut ClassProp) {
1483 if p.declare {
1484 return;
1485 }
1486
1487 p.visit_mut_children_with(self);
1488
1489 if p.decorators.is_empty() {
1490 return;
1491 }
1492
1493 let decorators = self.preserve_side_effect_of_decorators(p.decorators.take());
1494 let dec = merge_decorators(decorators);
1495
1496 let (name, init) = self.initializer_name(&mut p.key, "init");
1497
1498 self.extra_vars.push(VarDeclarator {
1499 span: p.span,
1500 name: init.clone().into(),
1501 init: None,
1502 definite: false,
1503 });
1504
1505 p.value = Some(
1506 CallExpr {
1507 span: DUMMY_SP,
1508 callee: init.clone().as_callee(),
1509 args: once(ThisExpr { span: DUMMY_SP }.as_arg())
1510 .chain(p.value.take().map(|v| v.as_arg()))
1511 .collect(),
1512
1513 ..Default::default()
1514 }
1515 .into(),
1516 );
1517
1518 let initialize_init = {
1519 Some(
1520 ArrayLit {
1521 span: DUMMY_SP,
1522 elems: vec![
1523 dec,
1524 Some(if p.is_static { 5.as_arg() } else { 0.as_arg() }),
1525 Some(name.as_arg()),
1526 ],
1527 }
1528 .as_arg(),
1529 )
1530 };
1531
1532 if p.is_static {
1533 self.state.static_lhs.push(init);
1534 self.state.init_static_args.push(initialize_init);
1535 } else {
1536 self.state.proto_lhs.push(init);
1537 self.state.init_proto_args.push(initialize_init);
1538 }
1539 }
1540
1541 fn visit_mut_expr(&mut self, e: &mut Expr) {
1542 if let Expr::Class(c) = e {
1543 if !c.class.decorators.is_empty() {
1544 let new = self.handle_class_expr(&mut c.class, c.ident.as_ref());
1545
1546 c.visit_mut_with(self);
1547
1548 *e = SeqExpr {
1549 span: DUMMY_SP,
1550 exprs: vec![Box::new(e.take()), Box::new(Expr::Ident(new))],
1551 }
1552 .into();
1553
1554 return;
1555 }
1556 }
1557
1558 maybe_grow_default(|| e.visit_mut_children_with(self));
1559 }
1560
1561 fn visit_mut_module_item(&mut self, s: &mut ModuleItem) {
1562 match s {
1563 ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
1564 span,
1565 decl: Decl::Class(c),
1566 })) if !c.class.decorators.is_empty() => {
1567 let ident = c.ident.clone();
1568 let span = *span;
1569 let new_stmt = self.handle_class_decl(c);
1570
1571 *s = new_stmt.into();
1572 self.extra_exports
1573 .push(ExportSpecifier::Named(ExportNamedSpecifier {
1574 span,
1575 orig: ModuleExportName::Ident(ident),
1576 exported: None,
1577 is_type_only: false,
1578 }));
1579 }
1580 ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(ExportDefaultDecl {
1581 span,
1582 decl: DefaultDecl::Class(c),
1583 })) if !c.class.decorators.is_empty() => {
1584 let ident = c
1585 .ident
1586 .get_or_insert_with(|| private_ident!("_default"))
1587 .clone();
1588
1589 let mut class_decl = c.take().as_class_decl().unwrap();
1590 let new_stmt = self.handle_class_decl(&mut class_decl);
1591
1592 self.extra_exports
1593 .push(ExportSpecifier::Named(ExportNamedSpecifier {
1594 span: *span,
1595 orig: ModuleExportName::Ident(ident),
1596 exported: Some(quote_ident!("default").into()),
1597 is_type_only: false,
1598 }));
1599
1600 *s = new_stmt.into();
1601 }
1602 _ => {
1603 s.visit_mut_children_with(self);
1604 }
1605 }
1606 }
1607
1608 fn visit_mut_module_items(&mut self, n: &mut Vec<ModuleItem>) {
1609 let extra_vars = self.extra_vars.take();
1610 let extra_lets = self.extra_lets.take();
1611 let pre_class_inits = self.pre_class_inits.take();
1612 let extra_exports = self.extra_exports.take();
1613
1614 let mut insert_builder = InsertPassBuilder::new();
1615
1616 for (index, n) in n.iter_mut().enumerate() {
1617 n.visit_mut_with(self);
1618 if !self.extra_lets.is_empty() {
1619 insert_builder.push_back(
1620 index,
1621 VarDecl {
1622 span: DUMMY_SP,
1623 kind: VarDeclKind::Let,
1624 decls: self.extra_lets.take(),
1625 declare: false,
1626 ..Default::default()
1627 }
1628 .into(),
1629 );
1630 }
1631 if !self.pre_class_inits.is_empty() {
1632 insert_builder.push_back(
1633 index,
1634 ExprStmt {
1635 span: DUMMY_SP,
1636 expr: Expr::from_exprs(self.pre_class_inits.take()),
1637 }
1638 .into(),
1639 );
1640 }
1641 }
1642
1643 if !self.extra_vars.is_empty() {
1644 let insert_pos = n
1645 .iter()
1646 .position(|module_item| match module_item {
1647 ModuleItem::Stmt(stmt) => !is_maybe_branch_directive(stmt),
1648 ModuleItem::ModuleDecl(_) => true,
1649 #[cfg(swc_ast_unknown)]
1650 _ => panic!("unable to access unknown nodes"),
1651 })
1652 .unwrap_or(0);
1653 insert_builder.push_front(
1654 insert_pos,
1655 VarDecl {
1656 span: DUMMY_SP,
1657 kind: VarDeclKind::Var,
1658 decls: self.extra_vars.take(),
1659 declare: false,
1660 ..Default::default()
1661 }
1662 .into(),
1663 );
1664 }
1665
1666 if !self.extra_exports.is_empty() {
1667 insert_builder.push_back(
1668 n.len() + 1,
1669 NamedExport {
1670 span: DUMMY_SP,
1671 specifiers: self.extra_exports.take(),
1672 src: None,
1673 type_only: false,
1674 with: None,
1675 }
1676 .into(),
1677 );
1678 }
1679
1680 *n = insert_builder.build(n.take());
1681
1682 if !self.rename_map.is_empty() {
1683 n.visit_mut_with(&mut IdentRenamer::new(&self.rename_map));
1684 }
1685
1686 self.extra_vars = extra_vars;
1687 self.extra_lets = extra_lets;
1688 self.pre_class_inits = pre_class_inits;
1689 self.extra_exports = extra_exports;
1690 }
1691
1692 fn visit_mut_private_prop(&mut self, p: &mut PrivateProp) {
1693 p.visit_mut_children_with(self);
1694
1695 if p.decorators.is_empty() {
1696 return;
1697 }
1698
1699 let decorators = self.preserve_side_effect_of_decorators(p.decorators.take());
1700 let dec = merge_decorators(decorators);
1701
1702 let init = private_ident!(format!("_init_{}", p.key.name));
1703
1704 self.extra_vars.push(VarDeclarator {
1705 span: p.span,
1706 name: init.clone().into(),
1707 init: None,
1708 definite: false,
1709 });
1710
1711 p.value = Some(
1712 CallExpr {
1713 span: DUMMY_SP,
1714 callee: init.clone().as_callee(),
1715 args: once(ThisExpr { span: DUMMY_SP }.as_arg())
1716 .chain(p.value.take().map(|v| v.as_arg()))
1717 .collect(),
1718 ..Default::default()
1719 }
1720 .into(),
1721 );
1722
1723 let initialize_init = {
1724 let access_expr = MemberExpr {
1725 span: DUMMY_SP,
1726 obj: ThisExpr { span: DUMMY_SP }.into(),
1727 prop: MemberProp::PrivateName(p.key.clone()),
1728 };
1729
1730 let getter = Box::new(Function {
1731 span: DUMMY_SP,
1732 body: Some(BlockStmt {
1733 span: DUMMY_SP,
1734 stmts: vec![Stmt::Return(ReturnStmt {
1735 span: DUMMY_SP,
1736 arg: Some(access_expr.clone().into()),
1737 })],
1738 ..Default::default()
1739 }),
1740 is_async: false,
1741 is_generator: false,
1742 ..Default::default()
1743 });
1744 let settter_arg = private_ident!("value");
1745 let setter = Box::new(Function {
1746 span: DUMMY_SP,
1747 body: Some(BlockStmt {
1748 span: DUMMY_SP,
1749 stmts: vec![Stmt::Expr(ExprStmt {
1750 span: DUMMY_SP,
1751 expr: Box::new(Expr::Assign(AssignExpr {
1752 span: DUMMY_SP,
1753 op: op!("="),
1754 left: access_expr.into(),
1755 right: Box::new(Expr::Ident(settter_arg.clone())),
1756 })),
1757 })],
1758 ..Default::default()
1759 }),
1760 is_async: false,
1761 is_generator: false,
1762 decorators: Default::default(),
1763 params: vec![Param {
1764 span: DUMMY_SP,
1765 decorators: Default::default(),
1766 pat: Pat::Ident(settter_arg.into()),
1767 }],
1768 ..Default::default()
1769 });
1770
1771 ArrayLit {
1772 span: DUMMY_SP,
1773 elems: vec![
1774 dec,
1775 Some(if p.is_static { 5.as_arg() } else { 0.as_arg() }),
1776 Some((&*p.key.name).as_arg()),
1777 Some(
1778 FnExpr {
1779 ident: None,
1780 function: getter,
1781 }
1782 .as_arg(),
1783 ),
1784 Some(
1785 FnExpr {
1786 ident: None,
1787 function: setter,
1788 }
1789 .as_arg(),
1790 ),
1791 ],
1792 }
1793 .as_arg()
1794 };
1795
1796 if p.is_static {
1797 self.state.static_lhs.push(init);
1798 self.state.init_static_args.push(Some(initialize_init));
1799 } else {
1800 self.state.proto_lhs.push(init);
1801 self.state.init_proto_args.push(Some(initialize_init));
1802 }
1803 }
1804
1805 fn visit_mut_stmt(&mut self, s: &mut Stmt) {
1806 match s {
1807 Stmt::Decl(Decl::Class(c)) if !c.class.decorators.is_empty() => {
1808 *s = self.handle_class_decl(c);
1809 }
1810 _ => {
1811 s.visit_mut_children_with(self);
1812 }
1813 }
1814 }
1815
1816 fn visit_mut_stmts(&mut self, n: &mut Vec<Stmt>) {
1817 let old_state = take(&mut self.state);
1818 let old_pre_class_inits = self.pre_class_inits.take();
1819 let old_extra_lets = self.extra_lets.take();
1820 let old_extra_vars = self.extra_vars.take();
1821
1822 let mut insert_builder = InsertPassBuilder::new();
1823 for (index, n) in n.iter_mut().enumerate() {
1824 n.visit_mut_with(self);
1825 if !self.extra_lets.is_empty() {
1826 insert_builder.push_back(
1827 index,
1828 VarDecl {
1829 span: DUMMY_SP,
1830 kind: VarDeclKind::Let,
1831 decls: self.extra_lets.take(),
1832 declare: false,
1833 ..Default::default()
1834 }
1835 .into(),
1836 );
1837 }
1838 if !self.pre_class_inits.is_empty() {
1839 insert_builder.push_back(
1840 index,
1841 ExprStmt {
1842 span: DUMMY_SP,
1843 expr: Expr::from_exprs(self.pre_class_inits.take()),
1844 }
1845 .into(),
1846 );
1847 }
1848 }
1849
1850 if !self.extra_vars.is_empty() {
1851 let insert_pos = n
1852 .iter()
1853 .position(|stmt| !is_maybe_branch_directive(stmt))
1854 .unwrap_or(0);
1855 insert_builder.push_front(
1856 insert_pos,
1857 VarDecl {
1858 span: DUMMY_SP,
1859 kind: VarDeclKind::Var,
1860 decls: self.extra_vars.take(),
1861 declare: false,
1862 ..Default::default()
1863 }
1864 .into(),
1865 );
1866 }
1867
1868 *n = insert_builder.build(n.take());
1869
1870 self.extra_vars = old_extra_vars;
1871 self.extra_lets = old_extra_lets;
1872 self.pre_class_inits = old_pre_class_inits;
1873 self.state = old_state;
1874 }
1875}
1876
1877struct InsertPassBuilder<T> {
1882 inserts: VecDeque<(usize, T)>,
1883}
1884
1885impl<T> InsertPassBuilder<T> {
1886 pub fn new() -> Self {
1887 Self {
1888 inserts: Default::default(),
1889 }
1890 }
1891
1892 pub fn push_front(&mut self, index: usize, item: T) {
1893 if cfg!(debug_assertions) {
1894 if let Some(past) = self.inserts.front() {
1895 debug_assert!(past.0 >= index, "{} {}", past.0, index);
1896 }
1897 }
1898 self.inserts.push_front((index, item));
1899 }
1900
1901 pub fn push_back(&mut self, index: usize, item: T) {
1902 if cfg!(debug_assertions) {
1903 if let Some(past) = self.inserts.back() {
1904 debug_assert!(past.0 <= index, "{} {}", past.0, index);
1905 }
1906 }
1907 self.inserts.push_back((index, item));
1908 }
1909
1910 pub fn build(mut self, original: Vec<T>) -> Vec<T> {
1911 let capacity = original.len() + self.inserts.len();
1912 let mut new = Vec::with_capacity(capacity);
1913 for (index, item) in original.into_iter().enumerate() {
1914 while self
1915 .inserts
1916 .front()
1917 .map(|(item_index, _)| *item_index == index)
1918 .unwrap_or(false)
1919 {
1920 new.push(self.inserts.pop_front().unwrap().1);
1921 }
1922 new.push(item);
1923 }
1924 new.extend(self.inserts.into_iter().map(|v| v.1));
1925
1926 debug_assert!(new.len() == capacity, "len: {} / {}", new.len(), capacity);
1927 new
1928 }
1929}
1930
1931fn merge_decorators(decorators: Vec<Option<ExprOrSpread>>) -> Option<ExprOrSpread> {
1932 if decorators.len() == 1 {
1933 return decorators.into_iter().next().unwrap();
1934 }
1935
1936 Some(
1937 ArrayLit {
1938 span: DUMMY_SP,
1939 elems: decorators,
1940 }
1941 .as_arg(),
1942 )
1943}