boa/syntax/ast/node/break_node/
mod.rs

1use super::Node;
2use crate::{
3    exec::Executable,
4    exec::InterpreterState,
5    gc::{Finalize, Trace},
6    Context, JsResult, JsValue,
7};
8use std::fmt;
9
10#[cfg(feature = "deser")]
11use serde::{Deserialize, Serialize};
12
13#[cfg(test)]
14mod tests;
15
16/// The `break` statement terminates the current loop, switch, or label statement and transfers
17/// program control to the statement following the terminated statement.
18///
19/// The break statement includes an optional label that allows the program to break out of a
20/// labeled statement. The break statement needs to be nested within the referenced label. The
21/// labeled statement can be any block statement; it does not have to be preceded by a loop
22/// statement.
23///
24/// More information:
25///  - [ECMAScript reference][spec]
26///  - [MDN documentation][mdn]
27///
28/// [spec]: https://tc39.es/ecma262/#prod-BreakStatement
29/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/break
30#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
31#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
32pub struct Break {
33    label: Option<Box<str>>,
34}
35
36impl Break {
37    /// Creates a `Break` AST node.
38    pub fn new<OL, L>(label: OL) -> Self
39    where
40        L: Into<Box<str>>,
41        OL: Into<Option<L>>,
42    {
43        Self {
44            label: label.into().map(L::into),
45        }
46    }
47
48    /// Gets the label of the break statement, if any.
49    pub fn label(&self) -> Option<&str> {
50        self.label.as_ref().map(Box::as_ref)
51    }
52}
53
54impl Executable for Break {
55    fn run(&self, context: &mut Context) -> JsResult<JsValue> {
56        context
57            .executor()
58            .set_current_state(InterpreterState::Break(self.label().map(Box::from)));
59
60        Ok(JsValue::undefined())
61    }
62}
63
64impl fmt::Display for Break {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        write!(
67            f,
68            "break{}",
69            if self.label().is_some() {
70                format!(" {}", self.label().as_ref().unwrap())
71            } else {
72                String::new()
73            }
74        )
75    }
76}
77
78impl From<Break> for Node {
79    fn from(break_smt: Break) -> Node {
80        Self::Break(break_smt)
81    }
82}