Skip to main content

boa_ast/expression/
spread.rs

1use boa_interner::{Interner, ToInternedString};
2use core::ops::ControlFlow;
3
4use crate::{
5    Span, Spanned,
6    visitor::{VisitWith, Visitor, VisitorMut},
7};
8
9use super::Expression;
10
11/// The `spread` operator allows an iterable such as an array expression or string to be
12/// expanded.
13///
14/// Syntax: `...x`
15///
16/// It expands array expressions or strings in places where zero or more arguments (for
17/// function calls) or elements (for array literals)
18/// are expected, or an object expression to be expanded in places where zero or more key-value
19/// pairs (for object literals) are expected.
20///
21/// More information:
22///  - [ECMAScript reference][spec]
23///  - [MDN documentation][mdn]
24///
25/// [spec]: https://tc39.es/ecma262/#prod-SpreadElement
26/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
27#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
28#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
29#[derive(Clone, Debug, PartialEq)]
30pub struct Spread {
31    target: Box<Expression>,
32    span: Span,
33}
34
35impl Spread {
36    /// Creates a [`Spread`] AST Expression.
37    #[inline]
38    #[must_use]
39    pub fn new(target: Expression, span: Span) -> Self {
40        Self {
41            target: Box::new(target),
42            span,
43        }
44    }
45
46    /// Gets the target expression to be expanded by the spread operator.
47    #[inline]
48    #[must_use]
49    pub const fn target(&self) -> &Expression {
50        &self.target
51    }
52}
53
54impl Spanned for Spread {
55    #[inline]
56    fn span(&self) -> Span {
57        self.span
58    }
59}
60
61impl ToInternedString for Spread {
62    #[inline]
63    fn to_interned_string(&self, interner: &Interner) -> String {
64        format!("...{}", self.target().to_interned_string(interner))
65    }
66}
67
68impl From<Spread> for Expression {
69    #[inline]
70    fn from(spread: Spread) -> Self {
71        Self::Spread(spread)
72    }
73}
74
75impl VisitWith for Spread {
76    fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
77    where
78        V: Visitor<'a>,
79    {
80        visitor.visit_expression(&self.target)
81    }
82
83    fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
84    where
85        V: VisitorMut<'a>,
86    {
87        visitor.visit_expression_mut(&mut self.target)
88    }
89}