Skip to main content

boa_ast/statement/
with.rs

1use crate::{
2    expression::Expression,
3    scope::Scope,
4    statement::Statement,
5    visitor::{VisitWith, Visitor, VisitorMut},
6};
7use boa_interner::{Interner, ToIndentedString, ToInternedString};
8use core::ops::ControlFlow;
9
10/// The `with` statement extends the scope chain for a statement.
11///
12/// More information:
13///  - [ECMAScript reference][spec]
14///  - [MDN documentation][mdn]
15///
16/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with
17/// [spec]: https://tc39.es/ecma262/#prod-WithStatement
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
20#[derive(Clone, Debug, PartialEq)]
21pub struct With {
22    pub(crate) expression: Expression,
23    pub(crate) statement: Box<Statement>,
24
25    #[cfg_attr(feature = "serde", serde(skip))]
26    pub(crate) scope: Scope,
27}
28
29impl With {
30    /// Creates a `With` AST node.
31    #[must_use]
32    pub fn new(expression: Expression, statement: Statement) -> Self {
33        Self {
34            expression,
35            statement: Box::new(statement),
36            scope: Scope::default(),
37        }
38    }
39
40    /// Gets the expression value of this `With` statement.
41    #[must_use]
42    pub const fn expression(&self) -> &Expression {
43        &self.expression
44    }
45
46    /// Gets the statement value of this `With` statement.
47    #[must_use]
48    pub const fn statement(&self) -> &Statement {
49        &self.statement
50    }
51
52    /// Returns the scope of the `With` statement.
53    #[must_use]
54    pub const fn scope(&self) -> &Scope {
55        &self.scope
56    }
57}
58
59impl From<With> for Statement {
60    fn from(with: With) -> Self {
61        Self::With(with)
62    }
63}
64
65impl ToIndentedString for With {
66    fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
67        format!(
68            "with ({}) {}",
69            self.expression().to_interned_string(interner),
70            self.statement().to_indented_string(interner, indentation)
71        )
72    }
73}
74
75impl VisitWith for With {
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.expression)?;
81        visitor.visit_statement(&self.statement)
82    }
83
84    fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
85    where
86        V: VisitorMut<'a>,
87    {
88        visitor.visit_expression_mut(&mut self.expression)?;
89        visitor.visit_statement_mut(&mut self.statement)
90    }
91}