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}