boa_ast/
pattern.rs

1//! A pattern binding or assignment node.
2//!
3//! A [`Pattern`] Corresponds to the [`BindingPattern`][spec1] and the [`AssignmentPattern`][spec2]
4//! nodes, each of which is used in different situations and have slightly different grammars.
5//! For example, a variable declaration combined with a destructuring expression is a `BindingPattern`:
6//!
7//! ```Javascript
8//! const obj = { a: 1, b: 2 };
9//! const { a, b } = obj; // BindingPattern
10//! ```
11//!
12//! On the other hand, a simple destructuring expression with already declared variables is called
13//! an `AssignmentPattern`:
14//!
15//! ```Javascript
16//! let a = 1;
17//! let b = 3;
18//! [a, b] = [b, a]; // AssignmentPattern
19//! ```
20//!
21//! [spec1]: https://tc39.es/ecma262/#prod-BindingPattern
22//! [spec2]: https://tc39.es/ecma262/#prod-AssignmentPattern
23//! [destr]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
24
25use crate::{
26    Expression, Span, Spanned,
27    expression::{Identifier, access::PropertyAccess},
28    property::PropertyName,
29    visitor::{VisitWith, Visitor, VisitorMut},
30};
31use boa_interner::{Interner, ToInternedString};
32use core::{fmt::Write as _, ops::ControlFlow};
33
34/// An object or array pattern binding or assignment.
35///
36/// See the [module level documentation][self] for more information.
37#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
38#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
39#[derive(Clone, Debug, PartialEq)]
40pub enum Pattern {
41    /// An object pattern (`let {a, b, c} = object`).
42    Object(ObjectPattern),
43    /// An array pattern (`[a, b, c] = array`).
44    Array(ArrayPattern),
45}
46
47impl Spanned for Pattern {
48    #[inline]
49    fn span(&self) -> Span {
50        match self {
51            Pattern::Object(object_pattern) => object_pattern.span(),
52            Pattern::Array(array_pattern) => array_pattern.span(),
53        }
54    }
55}
56
57impl From<ObjectPattern> for Pattern {
58    fn from(obj: ObjectPattern) -> Self {
59        Self::Object(obj)
60    }
61}
62
63impl From<ArrayPattern> for Pattern {
64    fn from(obj: ArrayPattern) -> Self {
65        Self::Array(obj)
66    }
67}
68
69impl ToInternedString for Pattern {
70    fn to_interned_string(&self, interner: &Interner) -> String {
71        match &self {
72            Self::Object(o) => o.to_interned_string(interner),
73            Self::Array(a) => a.to_interned_string(interner),
74        }
75    }
76}
77
78impl VisitWith for Pattern {
79    fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
80    where
81        V: Visitor<'a>,
82    {
83        match self {
84            Self::Object(op) => visitor.visit_object_pattern(op),
85            Self::Array(ap) => visitor.visit_array_pattern(ap),
86        }
87    }
88
89    fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
90    where
91        V: VisitorMut<'a>,
92    {
93        match self {
94            Self::Object(op) => visitor.visit_object_pattern_mut(op),
95            Self::Array(ap) => visitor.visit_array_pattern_mut(ap),
96        }
97    }
98}
99
100/// An object binding or assignment pattern.
101///
102/// Corresponds to the [`ObjectBindingPattern`][spec1] and the [`ObjectAssignmentPattern`][spec2]
103/// Parse Nodes.
104///
105/// For more information on what is a valid binding in an object pattern, see [`ObjectPatternElement`].
106///
107/// [spec1]: https://tc39.es/ecma262/#prod-ObjectBindingPattern
108/// [spec2]: https://tc39.es/ecma262/#prod-ObjectAssignmentPattern
109#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
110#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
111#[derive(Clone, Debug, PartialEq)]
112pub struct ObjectPattern {
113    elements: Box<[ObjectPatternElement]>,
114    span: Span,
115}
116
117impl ToInternedString for ObjectPattern {
118    fn to_interned_string(&self, interner: &Interner) -> String {
119        let mut buf = "{".to_owned();
120        for (i, binding) in self.elements.iter().enumerate() {
121            let binding = binding.to_interned_string(interner);
122            let str = if i == self.elements.len() - 1 {
123                format!("{binding} ")
124            } else {
125                format!("{binding},")
126            };
127
128            buf.push_str(&str);
129        }
130        if self.elements.is_empty() {
131            buf.push(' ');
132        }
133        buf.push('}');
134        buf
135    }
136}
137
138impl ObjectPattern {
139    /// Creates a new object binding pattern.
140    #[inline]
141    #[must_use]
142    pub const fn new(elements: Box<[ObjectPatternElement]>, span: Span) -> Self {
143        Self { elements, span }
144    }
145
146    /// Gets the bindings for the object binding pattern.
147    #[inline]
148    #[must_use]
149    pub const fn bindings(&self) -> &[ObjectPatternElement] {
150        &self.elements
151    }
152
153    /// Returns true if the object binding pattern has a rest element.
154    #[inline]
155    #[must_use]
156    pub const fn has_rest(&self) -> bool {
157        matches!(
158            self.elements.last(),
159            Some(ObjectPatternElement::RestProperty { .. })
160        )
161    }
162}
163
164impl Spanned for ObjectPattern {
165    #[inline]
166    fn span(&self) -> Span {
167        self.span
168    }
169}
170
171impl VisitWith for ObjectPattern {
172    fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
173    where
174        V: Visitor<'a>,
175    {
176        for elem in &*self.elements {
177            visitor.visit_object_pattern_element(elem)?;
178        }
179        ControlFlow::Continue(())
180    }
181
182    fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
183    where
184        V: VisitorMut<'a>,
185    {
186        for elem in &mut *self.elements {
187            visitor.visit_object_pattern_element_mut(elem)?;
188        }
189        ControlFlow::Continue(())
190    }
191}
192
193/// An array binding or assignment pattern.
194///
195/// Corresponds to the [`ArrayBindingPattern`][spec1] and the [`ArrayAssignmentPattern`][spec2]
196/// Parse Nodes.
197///
198/// For more information on what is a valid binding in an array pattern, see [`ArrayPatternElement`].
199///
200/// [spec1]: https://tc39.es/ecma262/#prod-ArrayBindingPattern
201/// [spec2]: https://tc39.es/ecma262/#prod-ArrayAssignmentPattern
202#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
203#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
204#[derive(Clone, Debug, PartialEq)]
205pub struct ArrayPattern {
206    bindings: Box<[ArrayPatternElement]>,
207    span: Span,
208}
209
210impl ToInternedString for ArrayPattern {
211    fn to_interned_string(&self, interner: &Interner) -> String {
212        let mut buf = "[".to_owned();
213        for (i, binding) in self.bindings.iter().enumerate() {
214            if i == self.bindings.len() - 1 {
215                match binding {
216                    ArrayPatternElement::Elision => {
217                        let _ = write!(buf, "{}, ", binding.to_interned_string(interner));
218                    }
219                    _ => {
220                        let _ = write!(buf, "{} ", binding.to_interned_string(interner));
221                    }
222                }
223            } else {
224                let _ = write!(buf, "{},", binding.to_interned_string(interner));
225            }
226        }
227        buf.push(']');
228        buf
229    }
230}
231
232impl ArrayPattern {
233    /// Creates a new array binding pattern.
234    #[inline]
235    #[must_use]
236    pub fn new(bindings: Box<[ArrayPatternElement]>, span: Span) -> Self {
237        Self { bindings, span }
238    }
239
240    /// Gets the bindings for the array binding pattern.
241    #[inline]
242    #[must_use]
243    pub const fn bindings(&self) -> &[ArrayPatternElement] {
244        &self.bindings
245    }
246}
247
248impl Spanned for ArrayPattern {
249    #[inline]
250    fn span(&self) -> Span {
251        self.span
252    }
253}
254
255impl VisitWith for ArrayPattern {
256    fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
257    where
258        V: Visitor<'a>,
259    {
260        for elem in &*self.bindings {
261            visitor.visit_array_pattern_element(elem)?;
262        }
263        ControlFlow::Continue(())
264    }
265
266    fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
267    where
268        V: VisitorMut<'a>,
269    {
270        for elem in &mut *self.bindings {
271            visitor.visit_array_pattern_element_mut(elem)?;
272        }
273        ControlFlow::Continue(())
274    }
275}
276
277/// The different types of bindings that an [`ObjectPattern`] may contain.
278///
279/// Corresponds to the [`BindingProperty`][spec1] and the [`AssignmentProperty`][spec2] nodes.
280///
281/// [spec1]: https://tc39.es/ecma262/#prod-BindingProperty
282/// [spec2]: https://tc39.es/ecma262/#prod-AssignmentProperty
283#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
284#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
285#[derive(Clone, Debug, PartialEq)]
286pub enum ObjectPatternElement {
287    /// `SingleName` represents one of the following properties:
288    ///
289    /// - `SingleName` with an identifier and an optional default initializer.
290    /// - `BindingProperty` with an property name and a `SingleNameBinding` as  the `BindingElement`.
291    ///
292    /// More information:
293    ///  - [ECMAScript reference: 14.3.3 Destructuring Binding Patterns - SingleNameBinding][spec1]
294    ///  - [ECMAScript reference: 14.3.3 Destructuring Binding Patterns - BindingProperty][spec2]
295    ///
296    /// [spec1]: https://tc39.es/ecma262/#prod-SingleNameBinding
297    /// [spec2]: https://tc39.es/ecma262/#prod-BindingProperty
298    SingleName {
299        /// The identifier name of the property to be destructured.
300        name: PropertyName,
301        /// The variable name where the property value will be stored.
302        ident: Identifier,
303        /// An optional default value for the variable, in case the property doesn't exist.
304        default_init: Option<Expression>,
305    },
306
307    /// `RestProperty` represents a `BindingRestProperty` with an identifier.
308    ///
309    /// It also includes a list of the property keys that should be excluded from the rest,
310    /// because they where already assigned.
311    ///
312    /// More information:
313    ///  - [ECMAScript reference: 14.3.3 Destructuring Binding Patterns - BindingRestProperty][spec1]
314    ///
315    /// [spec1]: https://tc39.es/ecma262/#prod-BindingRestProperty
316    RestProperty {
317        /// The variable name where the unassigned properties will be stored.
318        ident: Identifier,
319    },
320
321    /// `AssignmentGetField` represents an `AssignmentProperty` with an expression field member expression `AssignmentElement`.
322    ///
323    /// Note: According to the spec this is not part of an `ObjectBindingPattern`.
324    /// This is only used when a object literal is used to cover an `AssignmentPattern`.
325    ///
326    /// More information:
327    ///  - [ECMAScript reference][spec]
328    ///
329    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentProperty
330    AssignmentPropertyAccess {
331        /// The identifier name of the property to be destructured.
332        name: PropertyName,
333        /// The property access where the property value will be destructured.
334        access: PropertyAccess,
335        /// An optional default value for the variable, in case the property doesn't exist.
336        default_init: Option<Expression>,
337    },
338
339    /// `AssignmentRestProperty` represents a rest property with a `DestructuringAssignmentTarget`.
340    ///
341    /// Note: According to the spec this is not part of an `ObjectBindingPattern`.
342    /// This is only used when a object literal is used to cover an `AssignmentPattern`.
343    ///
344    /// More information:
345    ///  - [ECMAScript reference][spec]
346    ///
347    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentRestProperty
348    AssignmentRestPropertyAccess {
349        /// The property access where the unassigned properties will be stored.
350        access: PropertyAccess,
351    },
352
353    /// Pattern represents a property with a `Pattern` as the element.
354    ///
355    /// Additionally to the identifier of the new property and the nested pattern,
356    /// this may also include an optional default initializer.
357    ///
358    /// More information:
359    ///  - [ECMAScript reference: 14.3.3 Destructuring Binding Patterns - BindingProperty][spec1]
360    ///
361    /// [spec1]: https://tc39.es/ecma262/#prod-BindingProperty
362    Pattern {
363        /// The identifier name of the property to be destructured.
364        name: PropertyName,
365        /// The pattern where the property value will be destructured.
366        pattern: Pattern,
367        /// An optional default value for the variable, in case the property doesn't exist.
368        default_init: Option<Expression>,
369    },
370}
371
372impl ToInternedString for ObjectPatternElement {
373    fn to_interned_string(&self, interner: &Interner) -> String {
374        match self {
375            Self::SingleName {
376                ident,
377                name,
378                default_init,
379            } => {
380                let mut buf = match name {
381                    PropertyName::Literal(name) if name == ident => {
382                        format!(" {}", interner.resolve_expect(ident.sym()))
383                    }
384                    PropertyName::Literal(name) => {
385                        format!(
386                            " {} : {}",
387                            interner.resolve_expect(name.sym()),
388                            interner.resolve_expect(ident.sym())
389                        )
390                    }
391                    PropertyName::Computed(node) => {
392                        format!(
393                            " [{}] : {}",
394                            node.to_interned_string(interner),
395                            interner.resolve_expect(ident.sym())
396                        )
397                    }
398                };
399                if let Some(init) = default_init {
400                    let _ = write!(buf, " = {}", init.to_interned_string(interner));
401                }
402                buf
403            }
404            Self::RestProperty { ident } => {
405                format!(" ... {}", interner.resolve_expect(ident.sym()))
406            }
407            Self::AssignmentRestPropertyAccess { access } => {
408                format!(" ... {}", access.to_interned_string(interner))
409            }
410            Self::AssignmentPropertyAccess {
411                name,
412                access,
413                default_init,
414            } => {
415                let mut buf = match name {
416                    PropertyName::Literal(name) => {
417                        format!(
418                            " {} : {}",
419                            interner.resolve_expect(name.sym()),
420                            access.to_interned_string(interner)
421                        )
422                    }
423                    PropertyName::Computed(node) => {
424                        format!(
425                            " [{}] : {}",
426                            node.to_interned_string(interner),
427                            access.to_interned_string(interner)
428                        )
429                    }
430                };
431                if let Some(init) = &default_init {
432                    let _ = write!(buf, " = {}", init.to_interned_string(interner));
433                }
434                buf
435            }
436            Self::Pattern {
437                name,
438                pattern,
439                default_init,
440            } => {
441                let mut buf = match name {
442                    PropertyName::Literal(name) => {
443                        format!(
444                            " {} : {}",
445                            interner.resolve_expect(name.sym()),
446                            pattern.to_interned_string(interner),
447                        )
448                    }
449                    PropertyName::Computed(node) => {
450                        format!(
451                            " [{}] : {}",
452                            node.to_interned_string(interner),
453                            pattern.to_interned_string(interner),
454                        )
455                    }
456                };
457                if let Some(init) = default_init {
458                    let _ = write!(buf, " = {}", init.to_interned_string(interner));
459                }
460                buf
461            }
462        }
463    }
464}
465
466impl VisitWith for ObjectPatternElement {
467    fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
468    where
469        V: Visitor<'a>,
470    {
471        match self {
472            Self::SingleName {
473                name,
474                ident,
475                default_init,
476            } => {
477                visitor.visit_property_name(name)?;
478                visitor.visit_identifier(ident)?;
479                if let Some(expr) = default_init {
480                    visitor.visit_expression(expr)
481                } else {
482                    ControlFlow::Continue(())
483                }
484            }
485            Self::RestProperty { ident, .. } => visitor.visit_identifier(ident),
486            Self::AssignmentPropertyAccess {
487                name,
488                access,
489                default_init,
490            } => {
491                visitor.visit_property_name(name)?;
492                visitor.visit_property_access(access)?;
493                if let Some(expr) = default_init {
494                    visitor.visit_expression(expr)
495                } else {
496                    ControlFlow::Continue(())
497                }
498            }
499            Self::AssignmentRestPropertyAccess { access, .. } => {
500                visitor.visit_property_access(access)
501            }
502            Self::Pattern {
503                name,
504                pattern,
505                default_init,
506            } => {
507                visitor.visit_property_name(name)?;
508                visitor.visit_pattern(pattern)?;
509                if let Some(expr) = default_init {
510                    visitor.visit_expression(expr)
511                } else {
512                    ControlFlow::Continue(())
513                }
514            }
515        }
516    }
517
518    fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
519    where
520        V: VisitorMut<'a>,
521    {
522        match self {
523            Self::SingleName {
524                name,
525                ident,
526                default_init,
527            } => {
528                visitor.visit_property_name_mut(name)?;
529                visitor.visit_identifier_mut(ident)?;
530                if let Some(expr) = default_init {
531                    visitor.visit_expression_mut(expr)
532                } else {
533                    ControlFlow::Continue(())
534                }
535            }
536            Self::RestProperty { ident, .. } => visitor.visit_identifier_mut(ident),
537            Self::AssignmentPropertyAccess {
538                name,
539                access,
540                default_init,
541            } => {
542                visitor.visit_property_name_mut(name)?;
543                visitor.visit_property_access_mut(access)?;
544                if let Some(expr) = default_init {
545                    visitor.visit_expression_mut(expr)
546                } else {
547                    ControlFlow::Continue(())
548                }
549            }
550            Self::AssignmentRestPropertyAccess { access, .. } => {
551                visitor.visit_property_access_mut(access)
552            }
553            Self::Pattern {
554                name,
555                pattern,
556                default_init,
557            } => {
558                visitor.visit_property_name_mut(name)?;
559                visitor.visit_pattern_mut(pattern)?;
560                if let Some(expr) = default_init {
561                    visitor.visit_expression_mut(expr)
562                } else {
563                    ControlFlow::Continue(())
564                }
565            }
566        }
567    }
568}
569
570/// The different types of bindings that an array binding pattern may contain.
571///
572/// Corresponds to the [`BindingElement`][spec1] and the [`AssignmentElement`][spec2] nodes.
573///
574/// [spec1]: https://tc39.es/ecma262/#prod-BindingElement
575/// [spec2]: https://tc39.es/ecma262/#prod-AssignmentElement
576#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
577#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
578#[derive(Clone, Debug, PartialEq)]
579pub enum ArrayPatternElement {
580    /// Elision represents the elision of an item in the array binding pattern.
581    ///
582    /// An `Elision` may occur at multiple points in the pattern and may be multiple elisions.
583    /// This variant strictly represents one elision. If there are multiple, this should be used multiple times.
584    ///
585    /// More information:
586    ///  - [ECMAScript reference: 13.2.4 Array Initializer - Elision][spec1]
587    ///
588    /// [spec1]: https://tc39.es/ecma262/#prod-Elision
589    Elision,
590
591    /// `SingleName` represents a `SingleName` with an identifier and an optional default initializer.
592    ///
593    /// More information:
594    ///  - [ECMAScript reference: 14.3.3 Destructuring Binding Patterns - SingleNameBinding][spec1]
595    ///
596    /// [spec1]: https://tc39.es/ecma262/#prod-SingleNameBinding
597    SingleName {
598        /// The variable name where the index element will be stored.
599        ident: Identifier,
600        /// An optional default value for the variable, in case the index element doesn't exist.
601        default_init: Option<Expression>,
602    },
603
604    /// `PropertyAccess` represents a binding with a property accessor.
605    ///
606    /// Note: According to the spec this is not part of an `ArrayBindingPattern`.
607    /// This is only used when a array literal is used as the left-hand-side of an assignment expression.
608    ///
609    /// More information:
610    ///  - [ECMAScript reference][spec]
611    ///
612    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentExpression
613    PropertyAccess {
614        /// The property access where the index element will be stored.
615        access: PropertyAccess,
616        /// An optional default value for the variable, in case the index element doesn't exist.
617        default_init: Option<Expression>,
618    },
619
620    /// Pattern represents a `Pattern` in an `Element` of an array pattern.
621    ///
622    /// The pattern and the optional default initializer are both stored in the `DeclarationPattern`.
623    ///
624    /// More information:
625    ///  - [ECMAScript reference: 14.3.3 Destructuring Binding Patterns - BindingElement][spec1]
626    ///
627    /// [spec1]: https://tc39.es/ecma262/#prod-BindingElement
628    Pattern {
629        /// The pattern where the index element will be stored.
630        pattern: Pattern,
631        /// An optional default value for the pattern, in case the index element doesn't exist.
632        default_init: Option<Expression>,
633    },
634
635    /// `SingleNameRest` represents a `BindingIdentifier` in a `BindingRestElement` of an array pattern.
636    ///
637    /// More information:
638    ///  - [ECMAScript reference: 14.3.3 Destructuring Binding Patterns - BindingRestElement][spec1]
639    ///
640    /// [spec1]: https://tc39.es/ecma262/#prod-BindingRestElement
641    SingleNameRest {
642        /// The variable where the unassigned index elements will be stored.
643        ident: Identifier,
644    },
645
646    /// `PropertyAccess` represents a rest (spread operator) with a property accessor.
647    ///
648    /// Note: According to the spec this is not part of an `ArrayBindingPattern`.
649    /// This is only used when a array literal is used as the left-hand-side of an assignment expression.
650    ///
651    /// More information:
652    ///  - [ECMAScript reference][spec]
653    ///
654    /// [spec]: https://tc39.es/ecma262/#prod-AssignmentExpression
655    PropertyAccessRest {
656        /// The property access where the unassigned index elements will be stored.
657        access: PropertyAccess,
658    },
659
660    /// `PatternRest` represents a `Pattern` in a `RestElement` of an array pattern.
661    ///
662    /// More information:
663    ///  - [ECMAScript reference: 14.3.3 Destructuring Binding Patterns - BindingRestElement][spec1]
664    ///
665    /// [spec1]: https://tc39.es/ecma262/#prod-BindingRestElement
666    PatternRest {
667        /// The pattern where the unassigned index elements will be stored.
668        pattern: Pattern,
669    },
670}
671
672impl ToInternedString for ArrayPatternElement {
673    fn to_interned_string(&self, interner: &Interner) -> String {
674        match self {
675            Self::Elision => " ".to_owned(),
676            Self::SingleName {
677                ident,
678                default_init,
679            } => {
680                let mut buf = format!(" {}", interner.resolve_expect(ident.sym()));
681                if let Some(init) = default_init {
682                    let _ = write!(buf, " = {}", init.to_interned_string(interner));
683                }
684                buf
685            }
686            Self::PropertyAccess {
687                access,
688                default_init,
689            } => {
690                let mut buf = format!(" {}", access.to_interned_string(interner));
691                if let Some(init) = default_init {
692                    let _ = write!(buf, " = {}", init.to_interned_string(interner));
693                }
694                buf
695            }
696            Self::Pattern {
697                pattern,
698                default_init,
699            } => {
700                let mut buf = format!(" {}", pattern.to_interned_string(interner));
701                if let Some(init) = default_init {
702                    let _ = write!(buf, " = {}", init.to_interned_string(interner));
703                }
704                buf
705            }
706            Self::SingleNameRest { ident } => {
707                format!(" ... {}", interner.resolve_expect(ident.sym()))
708            }
709            Self::PropertyAccessRest { access } => {
710                format!(" ... {}", access.to_interned_string(interner))
711            }
712            Self::PatternRest { pattern } => {
713                format!(" ... {}", pattern.to_interned_string(interner))
714            }
715        }
716    }
717}
718
719impl VisitWith for ArrayPatternElement {
720    fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
721    where
722        V: Visitor<'a>,
723    {
724        match self {
725            Self::SingleName {
726                ident,
727                default_init,
728            } => {
729                visitor.visit_identifier(ident)?;
730                if let Some(expr) = default_init {
731                    visitor.visit_expression(expr)
732                } else {
733                    ControlFlow::Continue(())
734                }
735            }
736            Self::PropertyAccess {
737                access,
738                default_init,
739            } => {
740                visitor.visit_property_access(access)?;
741                if let Some(expr) = default_init {
742                    visitor.visit_expression(expr)
743                } else {
744                    ControlFlow::Continue(())
745                }
746            }
747            Self::PropertyAccessRest { access } => visitor.visit_property_access(access),
748            Self::Pattern {
749                pattern,
750                default_init,
751            } => {
752                visitor.visit_pattern(pattern)?;
753                if let Some(expr) = default_init {
754                    visitor.visit_expression(expr)
755                } else {
756                    ControlFlow::Continue(())
757                }
758            }
759            Self::SingleNameRest { ident } => visitor.visit_identifier(ident),
760            Self::PatternRest { pattern } => visitor.visit_pattern(pattern),
761            Self::Elision => {
762                // special case to be handled by user
763                ControlFlow::Continue(())
764            }
765        }
766    }
767
768    fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
769    where
770        V: VisitorMut<'a>,
771    {
772        match self {
773            Self::SingleName {
774                ident,
775                default_init,
776            } => {
777                visitor.visit_identifier_mut(ident)?;
778                if let Some(expr) = default_init {
779                    visitor.visit_expression_mut(expr)
780                } else {
781                    ControlFlow::Continue(())
782                }
783            }
784            Self::PropertyAccess {
785                access,
786                default_init,
787            } => {
788                visitor.visit_property_access_mut(access)?;
789                if let Some(expr) = default_init {
790                    visitor.visit_expression_mut(expr)
791                } else {
792                    ControlFlow::Continue(())
793                }
794            }
795            Self::PropertyAccessRest { access } => visitor.visit_property_access_mut(access),
796            Self::Pattern {
797                pattern,
798                default_init,
799            } => {
800                visitor.visit_pattern_mut(pattern)?;
801                if let Some(expr) = default_init {
802                    visitor.visit_expression_mut(expr)
803                } else {
804                    ControlFlow::Continue(())
805                }
806            }
807            Self::SingleNameRest { ident } => visitor.visit_identifier_mut(ident),
808            Self::PatternRest { pattern } => visitor.visit_pattern_mut(pattern),
809            Self::Elision => {
810                // special case to be handled by user
811                ControlFlow::Continue(())
812            }
813        }
814    }
815}