swc_ecma_compiler/es2022/
private_in_object.rs1use rustc_hash::FxHashSet;
2use swc_atoms::Atom;
3use swc_common::{Mark, SyntaxContext, DUMMY_SP};
4use swc_ecma_ast::*;
5use swc_ecma_visit::{noop_visit_type, Visit, VisitWith};
6
7use crate::CompilerImpl;
8
9#[derive(Debug)]
10pub(crate) enum Mode {
11 ClassExpr {
12 vars: Vec<VarDeclarator>,
13 init_exprs: Vec<Box<Expr>>,
14 },
15 ClassDecl {
16 vars: Vec<VarDeclarator>,
17 },
18}
19
20impl Default for Mode {
21 fn default() -> Self {
22 Self::ClassDecl {
23 vars: Default::default(),
24 }
25 }
26}
27
28impl Mode {
29 pub(crate) fn push_var(&mut self, n: Ident, init: Option<Box<Expr>>) {
30 match self {
31 Mode::ClassExpr { vars, init_exprs } => {
32 vars.push(VarDeclarator {
33 span: DUMMY_SP,
34 name: n.clone().into(),
35 init: None,
36 definite: Default::default(),
37 });
38 if let Some(init) = init {
39 init_exprs.push(
40 AssignExpr {
41 span: DUMMY_SP,
42 op: op!("="),
43 left: n.into(),
44 right: init,
45 }
46 .into(),
47 );
48 }
49 }
50 Mode::ClassDecl { vars } => {
51 vars.push(VarDeclarator {
52 span: DUMMY_SP,
53 name: n.into(),
54 init,
55 definite: Default::default(),
56 });
57 }
58 }
59 }
60}
61
62#[derive(Default)]
63pub(crate) struct ClassData {
64 pub(crate) ident: Option<Ident>,
65
66 pub(crate) vars: Mode,
67
68 pub(crate) mark: Mark,
72
73 pub(crate) privates: FxHashSet<Atom>,
74
75 pub(crate) methods: Vec<Atom>,
77
78 pub(crate) statics: Vec<Atom>,
80
81 pub(crate) constructor_exprs: Vec<Box<Expr>>,
82
83 pub(crate) names_used_for_brand_checks: FxHashSet<Atom>,
84}
85
86impl CompilerImpl<'_> {
87 pub(crate) fn var_name_for_brand_check(&self, n: &PrivateName, cls: &ClassData) -> Ident {
88 let is_static = cls.statics.contains(&n.name);
89
90 let span = n.span;
91 let ctxt = SyntaxContext::empty().apply_mark(cls.mark);
92
93 if !is_static && cls.methods.contains(&n.name) {
94 if let Some(cls_name) = &cls.ident {
95 return Ident::new(format!("_brand_check_{}", cls_name.sym).into(), span, ctxt);
96 }
97 }
98
99 Ident::new(format!("_brand_check_{}", n.name).into(), span, ctxt)
100 }
101}
102
103pub(crate) struct ClassAnalyzer<'a> {
104 pub(crate) brand_check_names: &'a mut FxHashSet<Atom>,
105 pub(crate) ignore_class: bool,
106}
107
108impl Visit for ClassAnalyzer<'_> {
109 noop_visit_type!(fail);
110
111 fn visit_bin_expr(&mut self, n: &BinExpr) {
112 n.visit_children_with(self);
113
114 if n.op == op!("in") {
115 if let Expr::PrivateName(left) = &*n.left {
116 self.brand_check_names.insert(left.name.clone());
117 }
118 }
119 }
120
121 fn visit_class(&mut self, n: &Class) {
123 if self.ignore_class {
124 return;
125 }
126
127 n.visit_children_with(self);
128 }
129}