swc_ecma_codegen/
object.rs

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