1use super::{FormalParameterList, FunctionBody};
4use crate::operations::{ContainsSymbol, contains};
5use crate::scope::{FunctionScopes, Scope};
6use crate::visitor::{VisitWith, Visitor, VisitorMut};
7use crate::{
8 Declaration, Spanned, block_to_string,
9 expression::{Expression, Identifier},
10 join_nodes,
11};
12use crate::{LinearSpan, LinearSpanIgnoreEq, Span};
13use boa_interner::{Interner, ToIndentedString};
14use core::{fmt::Write as _, ops::ControlFlow};
15
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
25#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
26#[derive(Clone, Debug, PartialEq)]
27pub struct AsyncGeneratorDeclaration {
28 name: Identifier,
29 pub(crate) parameters: FormalParameterList,
30 pub(crate) body: FunctionBody,
31 pub(crate) contains_direct_eval: bool,
32
33 #[cfg_attr(feature = "serde", serde(skip))]
34 pub(crate) scopes: FunctionScopes,
35 linear_span: LinearSpanIgnoreEq,
36}
37
38impl AsyncGeneratorDeclaration {
39 #[inline]
41 #[must_use]
42 pub fn new(
43 name: Identifier,
44 parameters: FormalParameterList,
45 body: FunctionBody,
46 linear_span: LinearSpan,
47 ) -> Self {
48 let contains_direct_eval = contains(¶meters, ContainsSymbol::DirectEval)
49 || contains(&body, ContainsSymbol::DirectEval);
50 Self {
51 name,
52 parameters,
53 body,
54 contains_direct_eval,
55 scopes: FunctionScopes::default(),
56 linear_span: linear_span.into(),
57 }
58 }
59
60 #[inline]
62 #[must_use]
63 pub const fn name(&self) -> Identifier {
64 self.name
65 }
66
67 #[inline]
69 #[must_use]
70 pub const fn parameters(&self) -> &FormalParameterList {
71 &self.parameters
72 }
73
74 #[inline]
76 #[must_use]
77 pub const fn body(&self) -> &FunctionBody {
78 &self.body
79 }
80
81 #[inline]
83 #[must_use]
84 pub const fn scopes(&self) -> &FunctionScopes {
85 &self.scopes
86 }
87
88 #[inline]
90 #[must_use]
91 pub const fn linear_span(&self) -> LinearSpan {
92 self.linear_span.0
93 }
94
95 #[inline]
97 #[must_use]
98 pub const fn contains_direct_eval(&self) -> bool {
99 self.contains_direct_eval
100 }
101}
102
103impl ToIndentedString for AsyncGeneratorDeclaration {
104 fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
105 format!(
106 "async function* {}({}) {}",
107 interner.resolve_expect(self.name.sym()),
108 join_nodes(interner, self.parameters.as_ref()),
109 block_to_string(&self.body.statements, interner, indentation)
110 )
111 }
112}
113
114impl VisitWith for AsyncGeneratorDeclaration {
115 fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
116 where
117 V: Visitor<'a>,
118 {
119 visitor.visit_identifier(&self.name)?;
120 visitor.visit_formal_parameter_list(&self.parameters)?;
121 visitor.visit_function_body(&self.body)
122 }
123
124 fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
125 where
126 V: VisitorMut<'a>,
127 {
128 visitor.visit_identifier_mut(&mut self.name)?;
129 visitor.visit_formal_parameter_list_mut(&mut self.parameters)?;
130 visitor.visit_function_body_mut(&mut self.body)
131 }
132}
133
134impl From<AsyncGeneratorDeclaration> for Declaration {
135 #[inline]
136 fn from(f: AsyncGeneratorDeclaration) -> Self {
137 Self::AsyncGeneratorDeclaration(f)
138 }
139}
140
141#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
150#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
151#[derive(Clone, Debug, PartialEq)]
152pub struct AsyncGeneratorExpression {
153 pub(crate) name: Option<Identifier>,
154 pub(crate) parameters: FormalParameterList,
155 pub(crate) body: FunctionBody,
156 pub(crate) has_binding_identifier: bool,
157 pub(crate) contains_direct_eval: bool,
158
159 #[cfg_attr(feature = "serde", serde(skip))]
160 pub(crate) name_scope: Option<Scope>,
161
162 #[cfg_attr(feature = "serde", serde(skip))]
163 pub(crate) scopes: FunctionScopes,
164 linear_span: LinearSpanIgnoreEq,
165
166 span: Span,
167}
168
169impl AsyncGeneratorExpression {
170 #[inline]
172 #[must_use]
173 pub fn new(
174 name: Option<Identifier>,
175 parameters: FormalParameterList,
176 body: FunctionBody,
177 linear_span: LinearSpan,
178 has_binding_identifier: bool,
179 span: Span,
180 ) -> Self {
181 let contains_direct_eval = contains(¶meters, ContainsSymbol::DirectEval)
182 || contains(&body, ContainsSymbol::DirectEval);
183 Self {
184 name,
185 parameters,
186 body,
187 has_binding_identifier,
188 name_scope: None,
189 contains_direct_eval,
190 scopes: FunctionScopes::default(),
191 linear_span: linear_span.into(),
192 span,
193 }
194 }
195
196 #[inline]
198 #[must_use]
199 pub const fn name(&self) -> Option<Identifier> {
200 self.name
201 }
202
203 #[inline]
205 #[must_use]
206 pub const fn parameters(&self) -> &FormalParameterList {
207 &self.parameters
208 }
209
210 #[inline]
212 #[must_use]
213 pub const fn body(&self) -> &FunctionBody {
214 &self.body
215 }
216
217 #[inline]
219 #[must_use]
220 pub const fn has_binding_identifier(&self) -> bool {
221 self.has_binding_identifier
222 }
223
224 #[inline]
226 #[must_use]
227 pub const fn name_scope(&self) -> Option<&Scope> {
228 self.name_scope.as_ref()
229 }
230
231 #[inline]
233 #[must_use]
234 pub const fn scopes(&self) -> &FunctionScopes {
235 &self.scopes
236 }
237
238 #[inline]
240 #[must_use]
241 pub const fn linear_span(&self) -> LinearSpan {
242 self.linear_span.0
243 }
244
245 #[inline]
247 #[must_use]
248 pub const fn contains_direct_eval(&self) -> bool {
249 self.contains_direct_eval
250 }
251}
252
253impl Spanned for AsyncGeneratorExpression {
254 #[inline]
255 fn span(&self) -> Span {
256 self.span
257 }
258}
259
260impl ToIndentedString for AsyncGeneratorExpression {
261 fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
262 let mut buf = "async function*".to_owned();
263 if self.has_binding_identifier
264 && let Some(name) = self.name
265 {
266 let _ = write!(buf, " {}", interner.resolve_expect(name.sym()));
267 }
268 let _ = write!(
269 buf,
270 "({}) {}",
271 join_nodes(interner, self.parameters.as_ref()),
272 block_to_string(&self.body.statements, interner, indentation)
273 );
274
275 buf
276 }
277}
278
279impl From<AsyncGeneratorExpression> for Expression {
280 #[inline]
281 fn from(expr: AsyncGeneratorExpression) -> Self {
282 Self::AsyncGeneratorExpression(expr)
283 }
284}
285
286impl VisitWith for AsyncGeneratorExpression {
287 fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
288 where
289 V: Visitor<'a>,
290 {
291 if let Some(ident) = &self.name {
292 visitor.visit_identifier(ident)?;
293 }
294 visitor.visit_formal_parameter_list(&self.parameters)?;
295 visitor.visit_function_body(&self.body)
296 }
297
298 fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
299 where
300 V: VisitorMut<'a>,
301 {
302 if let Some(ident) = &mut self.name {
303 visitor.visit_identifier_mut(ident)?;
304 }
305 visitor.visit_formal_parameter_list_mut(&mut self.parameters)?;
306 visitor.visit_function_body_mut(&mut self.body)
307 }
308}