Skip to main content

boa_ast/statement/
return.rs

1use crate::{
2    expression::Expression,
3    statement::Statement,
4    visitor::{VisitWith, Visitor, VisitorMut},
5};
6use boa_interner::{Interner, ToInternedString};
7use core::ops::ControlFlow;
8
9/// The `return` statement ends function execution and specifies a value to be returned to the
10/// function caller.
11///
12/// Syntax: `return [expression];`
13///
14/// `expression`:
15///  > The expression whose value is to be returned. If omitted, `undefined` is returned instead.
16///
17/// When a `return` statement is used in a function body, the execution of the function is
18/// stopped. If specified, a given value is returned to the function caller.
19///
20/// More information:
21///  - [ECMAScript reference][spec]
22///  - [MDN documentation][mdn]
23///
24/// [spec]: https://tc39.es/ecma262/#prod-ReturnStatement
25/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return
26#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
27#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
28#[derive(Clone, Debug, PartialEq)]
29pub struct Return {
30    target: Option<Expression>,
31}
32
33impl Return {
34    /// Gets the target expression value of this `Return` statement.
35    #[must_use]
36    pub const fn target(&self) -> Option<&Expression> {
37        self.target.as_ref()
38    }
39
40    /// Creates a `Return` AST node.
41    #[must_use]
42    pub const fn new(expression: Option<Expression>) -> Self {
43        Self { target: expression }
44    }
45}
46
47impl From<Return> for Statement {
48    fn from(return_smt: Return) -> Self {
49        Self::Return(return_smt)
50    }
51}
52
53impl ToInternedString for Return {
54    fn to_interned_string(&self, interner: &Interner) -> String {
55        self.target().map_or_else(
56            || "return".to_owned(),
57            |ex| format!("return {}", ex.to_interned_string(interner)),
58        )
59    }
60}
61
62impl VisitWith for Return {
63    fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
64    where
65        V: Visitor<'a>,
66    {
67        if let Some(expr) = &self.target {
68            visitor.visit_expression(expr)
69        } else {
70            ControlFlow::Continue(())
71        }
72    }
73
74    fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
75    where
76        V: VisitorMut<'a>,
77    {
78        if let Some(expr) = &mut self.target {
79            visitor.visit_expression_mut(expr)
80        } else {
81            ControlFlow::Continue(())
82        }
83    }
84}