swc_ecma_codegen/
object.rs

1use swc_common::{Spanned, DUMMY_SP};
2use swc_ecma_ast::*;
3use swc_ecma_codegen_macros::node_impl;
4
5use crate::{is_empty_comments, ListFormat};
6
7#[node_impl]
8impl MacroNode for ObjectLit {
9    fn emit(&mut self, emitter: &mut Macro) -> Result {
10        emitter.emit_leading_comments_of_span(self.span(), false)?;
11
12        srcmap!(emitter, self, true);
13
14        punct!(emitter, "{");
15
16        let emit_new_line = !emitter.cfg.minify
17            && !(self.props.is_empty() && is_empty_comments(&self.span(), &emitter.comments));
18
19        if emit_new_line {
20            emitter.wr.write_line()?;
21        }
22
23        let mut list_format =
24            ListFormat::ObjectLiteralExpressionProperties | ListFormat::CanSkipTrailingComma;
25
26        if !emit_new_line {
27            list_format -= ListFormat::MultiLine | ListFormat::Indented;
28        }
29
30        emitter.emit_list(self.span(), Some(&self.props), list_format)?;
31
32        if emit_new_line {
33            emitter.wr.write_line()?;
34        }
35
36        srcmap!(emitter, self, false, true);
37        punct!(emitter, "}");
38
39        Ok(())
40    }
41}
42
43#[node_impl]
44impl MacroNode for Prop {
45    fn emit(&mut self, emitter: &mut Macro) -> Result {
46        match self {
47            Prop::Shorthand(ref n) => emit!(n),
48            Prop::KeyValue(ref n) => emit!(n),
49            Prop::Assign(ref n) => emit!(n),
50            Prop::Getter(ref n) => emit!(n),
51            Prop::Setter(ref n) => emit!(n),
52            Prop::Method(ref n) => emit!(n),
53        }
54
55        Ok(())
56    }
57}
58
59#[node_impl]
60impl MacroNode for KeyValueProp {
61    fn emit(&mut self, emitter: &mut Macro) -> Result {
62        emitter.emit_leading_comments_of_span(self.span(), false)?;
63        let key_span = self.key.span();
64        let value_span = self.value.span();
65        if !key_span.is_dummy() {
66            emitter.wr.add_srcmap(key_span.lo)?;
67        }
68        emit!(self.key);
69        if !key_span.is_dummy() && value_span.is_dummy() {
70            emitter.wr.add_srcmap(key_span.hi)?;
71        }
72        punct!(emitter, ":");
73        formatting_space!(emitter);
74        if key_span.is_dummy() && !value_span.is_dummy() {
75            emitter.wr.add_srcmap(value_span.lo)?;
76        }
77        emit!(self.value);
78
79        Ok(())
80    }
81}
82
83#[node_impl]
84impl MacroNode for AssignProp {
85    fn emit(&mut self, emitter: &mut Macro) -> Result {
86        emitter.emit_leading_comments_of_span(self.span(), false)?;
87
88        srcmap!(emitter, self, true);
89
90        emit!(self.key);
91        punct!(emitter, "=");
92        emit!(self.value);
93
94        Ok(())
95    }
96}
97
98#[node_impl]
99impl MacroNode for GetterProp {
100    fn emit(&mut self, emitter: &mut Macro) -> Result {
101        emitter.emit_leading_comments_of_span(self.span(), false)?;
102
103        srcmap!(emitter, self, true);
104
105        keyword!(emitter, "get");
106
107        let starts_with_alpha_num = match self.key {
108            PropName::Str(_) | PropName::Computed(_) => false,
109            _ => true,
110        };
111        if starts_with_alpha_num {
112            space!(emitter);
113        } else {
114            formatting_space!(emitter);
115        }
116        emit!(self.key);
117        formatting_space!(emitter);
118        punct!(emitter, "(");
119        punct!(emitter, ")");
120        formatting_space!(emitter);
121        emit!(self.body);
122
123        Ok(())
124    }
125}
126
127#[node_impl]
128impl MacroNode for SetterProp {
129    fn emit(&mut self, emitter: &mut Macro) -> Result {
130        emitter.emit_leading_comments_of_span(self.span(), false)?;
131
132        srcmap!(emitter, self, true);
133
134        keyword!(emitter, "set");
135
136        let starts_with_alpha_num = match self.key {
137            PropName::Str(_) | PropName::Computed(_) => false,
138            _ => true,
139        };
140
141        if starts_with_alpha_num {
142            space!(emitter);
143        } else {
144            formatting_space!(emitter);
145        }
146
147        emit!(self.key);
148        formatting_space!(emitter);
149
150        punct!(emitter, "(");
151        if let Some(this) = &self.this_param {
152            emit!(this);
153            punct!(emitter, ",");
154
155            formatting_space!(emitter);
156        }
157
158        emit!(self.param);
159
160        punct!(emitter, ")");
161
162        emit!(self.body);
163
164        Ok(())
165    }
166}
167
168#[node_impl]
169impl MacroNode for MethodProp {
170    fn emit(&mut self, emitter: &mut Macro) -> Result {
171        emitter.emit_leading_comments_of_span(self.span(), false)?;
172
173        srcmap!(emitter, self, true);
174
175        if self.function.is_async {
176            keyword!(emitter, "async");
177            space!(emitter);
178        }
179
180        if self.function.is_generator {
181            punct!(emitter, "*");
182        }
183
184        emit!(self.key);
185        formatting_space!(emitter);
186        // TODO
187        emitter.emit_fn_trailing(&self.function)?;
188
189        Ok(())
190    }
191}
192
193#[node_impl]
194impl MacroNode for PropName {
195    fn emit(&mut self, emitter: &mut Macro) -> Result {
196        match self {
197            PropName::Ident(ident) => {
198                // TODO: Use write_symbol when ident is a symbol.
199                emitter.emit_leading_comments_of_span(ident.span, false)?;
200
201                // Source map
202                emitter.wr.commit_pending_semi()?;
203
204                srcmap!(emitter, ident, true);
205
206                if emitter.cfg.ascii_only {
207                    if emitter.wr.can_ignore_invalid_unicodes() {
208                        emitter.wr.write_symbol(
209                            DUMMY_SP,
210                            &crate::get_ascii_only_ident(&ident.sym, true, emitter.cfg.target),
211                        )?;
212                    } else {
213                        emitter.wr.write_symbol(
214                            DUMMY_SP,
215                            &crate::get_ascii_only_ident(
216                                &crate::handle_invalid_unicodes(&ident.sym),
217                                true,
218                                emitter.cfg.target,
219                            ),
220                        )?;
221                    }
222                } else {
223                    emit!(ident);
224                }
225            }
226            PropName::Str(ref n) => emit!(n),
227            PropName::Num(ref n) => emit!(n),
228            PropName::BigInt(ref n) => emit!(n),
229            PropName::Computed(ref n) => emit!(n),
230        }
231
232        Ok(())
233    }
234}
235
236#[node_impl]
237impl MacroNode for ComputedPropName {
238    fn emit(&mut self, emitter: &mut Macro) -> Result {
239        srcmap!(emitter, self, true);
240
241        punct!(emitter, "[");
242        emit!(self.expr);
243        punct!(emitter, "]");
244
245        srcmap!(emitter, self, false);
246
247        Ok(())
248    }
249}