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::{
8 is_empty_comments,
9 scope_helpers::for_each_param_binding,
10 text_writer::{BindingStorage, ScopeKind},
11 ListFormat,
12};
13
14#[node_impl]
15impl MacroNode for ObjectLit {
16 fn emit(&mut self, emitter: &mut Macro) -> Result {
17 emitter.emit_leading_comments_of_span(self.span(), false)?;
18
19 srcmap!(emitter, self, true);
20
21 punct!(emitter, "{");
22
23 let emit_new_line = !emitter.cfg.minify
24 && !(self.props.is_empty() && is_empty_comments(&self.span(), &emitter.comments));
25
26 if emit_new_line {
27 emitter.wr.write_line()?;
28 }
29
30 let mut list_format =
31 ListFormat::ObjectLiteralExpressionProperties | ListFormat::CanSkipTrailingComma;
32
33 if !emit_new_line {
34 list_format -= ListFormat::MultiLine | ListFormat::Indented;
35 }
36
37 emitter.emit_list(self.span(), Some(&self.props), list_format)?;
38
39 if emit_new_line {
40 emitter.wr.write_line()?;
41 }
42
43 srcmap!(emitter, self, false, true);
44 punct!(emitter, "}");
45
46 Ok(())
47 }
48}
49
50#[node_impl]
51impl MacroNode for Prop {
52 fn emit(&mut self, emitter: &mut Macro) -> Result {
53 match self {
54 Prop::Shorthand(ref n) => emit!(n),
55 Prop::KeyValue(ref n) => emit!(n),
56 Prop::Assign(ref n) => emit!(n),
57 Prop::Getter(ref n) => emit!(n),
58 Prop::Setter(ref n) => emit!(n),
59 Prop::Method(ref n) => emit!(n),
60 #[cfg(swc_ast_unknown)]
61 _ => return Err(unknown_error()),
62 }
63
64 Ok(())
65 }
66}
67
68#[node_impl]
69impl MacroNode for KeyValueProp {
70 fn emit(&mut self, emitter: &mut Macro) -> Result {
71 emitter.emit_leading_comments_of_span(self.span(), false)?;
72 let key_span = self.key.span();
73 let value_span = self.value.span();
74 if !key_span.is_dummy() {
75 emitter.wr.add_srcmap(key_span.lo)?;
76 }
77 emit!(self.key);
78 if !key_span.is_dummy() && value_span.is_dummy() {
79 emitter.wr.add_srcmap(key_span.hi)?;
80 }
81 punct!(emitter, ":");
82 formatting_space!(emitter);
83 if key_span.is_dummy() && !value_span.is_dummy() {
84 emitter.wr.add_srcmap(value_span.lo)?;
85 }
86 emit!(self.value);
87
88 Ok(())
89 }
90}
91
92#[node_impl]
93impl MacroNode for AssignProp {
94 fn emit(&mut self, emitter: &mut Macro) -> Result {
95 emitter.emit_leading_comments_of_span(self.span(), false)?;
96
97 srcmap!(emitter, self, true);
98
99 emit!(self.key);
100 punct!(emitter, "=");
101 emit!(self.value);
102
103 Ok(())
104 }
105}
106
107#[node_impl]
108impl MacroNode for GetterProp {
109 fn emit(&mut self, emitter: &mut Macro) -> Result {
110 emitter.emit_leading_comments_of_span(self.span(), false)?;
111
112 srcmap!(emitter, self, true);
113 emitter.start_scope(
114 None,
115 ScopeKind::Function,
116 true,
117 false,
118 Some(self.function.span),
119 )?;
120
121 keyword!(emitter, "get");
122
123 let starts_with_alpha_num = match self.key {
124 PropName::Str(_) | PropName::Computed(_) => false,
125 _ => true,
126 };
127 if starts_with_alpha_num {
128 space!(emitter);
129 } else {
130 formatting_space!(emitter);
131 }
132 emit!(self.key);
133 formatting_space!(emitter);
134 emitter.emit_fn_trailing(&self.function)?;
135 emitter.end_scope()?;
136
137 Ok(())
138 }
139}
140
141#[node_impl]
142impl MacroNode for SetterProp {
143 fn emit(&mut self, emitter: &mut Macro) -> Result {
144 emitter.emit_leading_comments_of_span(self.span(), false)?;
145
146 srcmap!(emitter, self, true);
147 emitter.start_scope(
148 None,
149 ScopeKind::Function,
150 true,
151 false,
152 Some(self.function.span),
153 )?;
154 if emitter.scope_tracking_enabled() {
155 let mut names = vec![];
156 for_each_param_binding(&self.function.params, &mut |name| {
157 names.push(name.to_string())
158 });
159 for name in names {
160 emitter.add_scope_variable(&name, Some(&name), BindingStorage::Lexical)?;
161 }
162 }
163
164 keyword!(emitter, "set");
165
166 let starts_with_alpha_num = match self.key {
167 PropName::Str(_) | PropName::Computed(_) => false,
168 _ => true,
169 };
170
171 if starts_with_alpha_num {
172 space!(emitter);
173 } else {
174 formatting_space!(emitter);
175 }
176
177 emit!(self.key);
178 formatting_space!(emitter);
179
180 if let Some(type_params) = &self.function.type_params {
181 emit!(type_params);
182 }
183
184 emitter.emit_fn_params(&self.function)?;
185
186 if let Some(return_type) = &self.function.return_type {
187 punct!(emitter, ":");
188 formatting_space!(emitter);
189 emit!(return_type);
190 }
191
192 if let Some(body) = &self.function.body {
193 emit!(body);
194 } else {
195 semi!(emitter);
196 }
197 emitter.end_scope()?;
198
199 Ok(())
200 }
201}
202
203#[node_impl]
204impl MacroNode for MethodProp {
205 fn emit(&mut self, emitter: &mut Macro) -> Result {
206 emitter.emit_leading_comments_of_span(self.span(), false)?;
207
208 srcmap!(emitter, self, true);
209 emitter.start_scope(
210 None,
211 ScopeKind::Function,
212 true,
213 false,
214 Some(self.function.span),
215 )?;
216 if emitter.scope_tracking_enabled() {
217 let mut names = vec![];
218 for_each_param_binding(&self.function.params, &mut |name| {
219 names.push(name.to_string())
220 });
221 for name in names {
222 emitter.add_scope_variable(&name, Some(&name), BindingStorage::Lexical)?;
223 }
224 }
225
226 if self.function.is_async {
227 keyword!(emitter, "async");
228 space!(emitter);
229 }
230
231 if self.function.is_generator {
232 punct!(emitter, "*");
233 }
234
235 emit!(self.key);
236 formatting_space!(emitter);
237 emitter.emit_fn_trailing(&self.function)?;
239 emitter.end_scope()?;
240
241 Ok(())
242 }
243}
244
245#[node_impl]
246impl MacroNode for PropName {
247 fn emit(&mut self, emitter: &mut Macro) -> Result {
248 match self {
249 PropName::Ident(ident) => {
250 emitter.emit_leading_comments_of_span(ident.span, false)?;
252
253 emitter.wr.commit_pending_semi()?;
255
256 srcmap!(emitter, ident, true);
257
258 if emitter.cfg.ascii_only {
259 if emitter.wr.can_ignore_invalid_unicodes() {
260 emitter.wr.write_symbol(
261 DUMMY_SP,
262 &crate::get_ascii_only_ident(&ident.sym, true, emitter.cfg.target),
263 )?;
264 } else {
265 emitter.wr.write_symbol(
266 DUMMY_SP,
267 &crate::get_ascii_only_ident(
268 &crate::handle_invalid_unicodes(&ident.sym),
269 true,
270 emitter.cfg.target,
271 ),
272 )?;
273 }
274 } else {
275 emit!(ident);
276 }
277 }
278 PropName::Str(ref n) => emit!(n),
279 PropName::Num(ref n) => emit!(n),
280 PropName::BigInt(ref n) => emit!(n),
281 PropName::Computed(ref n) => emit!(n),
282 #[cfg(swc_ast_unknown)]
283 _ => return Err(unknown_error()),
284 }
285
286 Ok(())
287 }
288}
289
290#[node_impl]
291impl MacroNode for ComputedPropName {
292 fn emit(&mut self, emitter: &mut Macro) -> Result {
293 srcmap!(emitter, self, true);
294
295 punct!(emitter, "[");
296 emit!(self.expr);
297 punct!(emitter, "]");
298
299 srcmap!(emitter, self, false);
300
301 Ok(())
302 }
303}