swc_ecma_codegen/
object.rs1use 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 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 emitter.emit_leading_comments_of_span(ident.span, false)?;
200
201 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}