feat: add dependency
This commit is contained in:
79
javascript-engine/external/boa/boa_ast/src/statement/iteration/break.rs
vendored
Normal file
79
javascript-engine/external/boa/boa_ast/src/statement/iteration/break.rs
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
use boa_interner::{Interner, Sym, ToInternedString};
|
||||
use core::ops::ControlFlow;
|
||||
|
||||
use crate::visitor::{VisitWith, Visitor, VisitorMut};
|
||||
use crate::Statement;
|
||||
|
||||
/// The `break` statement terminates the current loop, switch, or label statement and transfers
|
||||
/// program control to the statement following the terminated statement.
|
||||
///
|
||||
/// The break statement includes an optional label that allows the program to break out of a
|
||||
/// labeled statement. The break statement needs to be nested within the referenced label. The
|
||||
/// labeled statement can be any block statement; it does not have to be preceded by a loop
|
||||
/// statement.
|
||||
///
|
||||
/// More information:
|
||||
/// - [ECMAScript reference][spec]
|
||||
/// - [MDN documentation][mdn]
|
||||
///
|
||||
/// [spec]: https://tc39.es/ecma262/#prod-BreakStatement
|
||||
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/break
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Break {
|
||||
label: Option<Sym>,
|
||||
}
|
||||
|
||||
impl Break {
|
||||
/// Creates a `Break` AST node.
|
||||
#[must_use]
|
||||
pub const fn new(label: Option<Sym>) -> Self {
|
||||
Self { label }
|
||||
}
|
||||
|
||||
/// Gets the label of the break statement, if any.
|
||||
#[must_use]
|
||||
pub const fn label(&self) -> Option<Sym> {
|
||||
self.label
|
||||
}
|
||||
}
|
||||
|
||||
impl ToInternedString for Break {
|
||||
fn to_interned_string(&self, interner: &Interner) -> String {
|
||||
self.label.map_or_else(
|
||||
|| "break".to_owned(),
|
||||
|label| format!("break {}", interner.resolve_expect(label)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Break> for Statement {
|
||||
fn from(break_smt: Break) -> Self {
|
||||
Self::Break(break_smt)
|
||||
}
|
||||
}
|
||||
|
||||
impl VisitWith for Break {
|
||||
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
|
||||
where
|
||||
V: Visitor<'a>,
|
||||
{
|
||||
if let Some(sym) = &self.label {
|
||||
visitor.visit_sym(sym)
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
|
||||
where
|
||||
V: VisitorMut<'a>,
|
||||
{
|
||||
if let Some(sym) = &mut self.label {
|
||||
visitor.visit_sym_mut(sym)
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
}
|
||||
77
javascript-engine/external/boa/boa_ast/src/statement/iteration/continue.rs
vendored
Normal file
77
javascript-engine/external/boa/boa_ast/src/statement/iteration/continue.rs
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
use crate::statement::Statement;
|
||||
use crate::visitor::{VisitWith, Visitor, VisitorMut};
|
||||
use boa_interner::{Interner, Sym, ToInternedString};
|
||||
use core::ops::ControlFlow;
|
||||
|
||||
/// The `continue` statement terminates execution of the statements in the current iteration of
|
||||
/// the current or labeled loop, and continues execution of the loop with the next iteration.
|
||||
///
|
||||
/// The continue statement can include an optional label that allows the program to jump to the
|
||||
/// next iteration of a labeled loop statement instead of the current loop. In this case, the
|
||||
/// continue statement needs to be nested within this labeled statement.
|
||||
///
|
||||
/// More information:
|
||||
/// - [ECMAScript reference][spec]
|
||||
/// - [MDN documentation][mdn]
|
||||
///
|
||||
/// [spec]: https://tc39.es/ecma262/#prod-ContinueStatement
|
||||
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/continue
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct Continue {
|
||||
label: Option<Sym>,
|
||||
}
|
||||
|
||||
impl Continue {
|
||||
/// Creates a `Continue` AST node.
|
||||
#[must_use]
|
||||
pub const fn new(label: Option<Sym>) -> Self {
|
||||
Self { label }
|
||||
}
|
||||
|
||||
/// Gets the label of this `Continue` statement.
|
||||
#[must_use]
|
||||
pub const fn label(&self) -> Option<Sym> {
|
||||
self.label
|
||||
}
|
||||
}
|
||||
|
||||
impl ToInternedString for Continue {
|
||||
fn to_interned_string(&self, interner: &Interner) -> String {
|
||||
self.label.map_or_else(
|
||||
|| "continue".to_owned(),
|
||||
|label| format!("continue {}", interner.resolve_expect(label)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Continue> for Statement {
|
||||
fn from(cont: Continue) -> Self {
|
||||
Self::Continue(cont)
|
||||
}
|
||||
}
|
||||
|
||||
impl VisitWith for Continue {
|
||||
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
|
||||
where
|
||||
V: Visitor<'a>,
|
||||
{
|
||||
if let Some(sym) = &self.label {
|
||||
visitor.visit_sym(sym)
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
|
||||
where
|
||||
V: VisitorMut<'a>,
|
||||
{
|
||||
if let Some(sym) = &mut self.label {
|
||||
visitor.visit_sym_mut(sym)
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
}
|
||||
87
javascript-engine/external/boa/boa_ast/src/statement/iteration/do_while_loop.rs
vendored
Normal file
87
javascript-engine/external/boa/boa_ast/src/statement/iteration/do_while_loop.rs
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
use crate::{
|
||||
expression::Expression,
|
||||
statement::Statement,
|
||||
try_break,
|
||||
visitor::{VisitWith, Visitor, VisitorMut},
|
||||
};
|
||||
use boa_interner::{Interner, ToIndentedString, ToInternedString};
|
||||
use core::ops::ControlFlow;
|
||||
|
||||
/// The `do...while` statement creates a loop that executes a specified statement until the
|
||||
/// test condition evaluates to false.
|
||||
///
|
||||
/// The condition is evaluated after executing the statement, resulting in the specified
|
||||
/// statement executing at least once.
|
||||
///
|
||||
/// More information:
|
||||
/// - [ECMAScript reference][spec]
|
||||
/// - [MDN documentation][mdn]
|
||||
///
|
||||
/// [spec]: https://tc39.es/ecma262/#sec-do-while-statement
|
||||
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/do...while
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct DoWhileLoop {
|
||||
body: Box<Statement>,
|
||||
condition: Expression,
|
||||
}
|
||||
|
||||
impl DoWhileLoop {
|
||||
/// Gets the body of the do-while loop.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn body(&self) -> &Statement {
|
||||
&self.body
|
||||
}
|
||||
|
||||
/// Gets the condition of the do-while loop.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn cond(&self) -> &Expression {
|
||||
&self.condition
|
||||
}
|
||||
/// Creates a `DoWhileLoop` AST node.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn new(body: Statement, condition: Expression) -> Self {
|
||||
Self {
|
||||
body: body.into(),
|
||||
condition,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToIndentedString for DoWhileLoop {
|
||||
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
|
||||
format!(
|
||||
"do {} while ({})",
|
||||
self.body().to_indented_string(interner, indentation),
|
||||
self.cond().to_interned_string(interner)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DoWhileLoop> for Statement {
|
||||
fn from(do_while: DoWhileLoop) -> Self {
|
||||
Self::DoWhileLoop(do_while)
|
||||
}
|
||||
}
|
||||
|
||||
impl VisitWith for DoWhileLoop {
|
||||
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
|
||||
where
|
||||
V: Visitor<'a>,
|
||||
{
|
||||
try_break!(visitor.visit_statement(&self.body));
|
||||
visitor.visit_expression(&self.condition)
|
||||
}
|
||||
|
||||
fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
|
||||
where
|
||||
V: VisitorMut<'a>,
|
||||
{
|
||||
try_break!(visitor.visit_statement_mut(&mut self.body));
|
||||
visitor.visit_expression_mut(&mut self.condition)
|
||||
}
|
||||
}
|
||||
98
javascript-engine/external/boa/boa_ast/src/statement/iteration/for_in_loop.rs
vendored
Normal file
98
javascript-engine/external/boa/boa_ast/src/statement/iteration/for_in_loop.rs
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
use crate::try_break;
|
||||
use crate::visitor::{VisitWith, Visitor, VisitorMut};
|
||||
use crate::{
|
||||
expression::Expression,
|
||||
statement::{iteration::IterableLoopInitializer, Statement},
|
||||
};
|
||||
use boa_interner::{Interner, ToIndentedString, ToInternedString};
|
||||
use core::ops::ControlFlow;
|
||||
|
||||
/// A `for...in` loop statement, as defined by the [spec].
|
||||
///
|
||||
/// [`for...in`][forin] statements loop over all enumerable string properties of an object, including
|
||||
/// inherited properties.
|
||||
///
|
||||
/// [forin]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in
|
||||
/// [spec]: https://tc39.es/ecma262/#prod-ForInOfStatement
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct ForInLoop {
|
||||
initializer: IterableLoopInitializer,
|
||||
target: Expression,
|
||||
body: Box<Statement>,
|
||||
}
|
||||
|
||||
impl ForInLoop {
|
||||
/// Creates a new `ForInLoop`.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn new(initializer: IterableLoopInitializer, target: Expression, body: Statement) -> Self {
|
||||
Self {
|
||||
initializer,
|
||||
target,
|
||||
body: body.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the initializer of the for...in loop.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn initializer(&self) -> &IterableLoopInitializer {
|
||||
&self.initializer
|
||||
}
|
||||
|
||||
/// Gets the target object of the for...in loop.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn target(&self) -> &Expression {
|
||||
&self.target
|
||||
}
|
||||
|
||||
/// Gets the body of the for...in loop.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn body(&self) -> &Statement {
|
||||
&self.body
|
||||
}
|
||||
}
|
||||
|
||||
impl ToIndentedString for ForInLoop {
|
||||
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
|
||||
let mut buf = format!(
|
||||
"for ({} in {}) ",
|
||||
self.initializer.to_interned_string(interner),
|
||||
self.target.to_interned_string(interner)
|
||||
);
|
||||
buf.push_str(&self.body().to_indented_string(interner, indentation));
|
||||
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ForInLoop> for Statement {
|
||||
#[inline]
|
||||
fn from(for_in: ForInLoop) -> Self {
|
||||
Self::ForInLoop(for_in)
|
||||
}
|
||||
}
|
||||
|
||||
impl VisitWith for ForInLoop {
|
||||
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
|
||||
where
|
||||
V: Visitor<'a>,
|
||||
{
|
||||
try_break!(visitor.visit_iterable_loop_initializer(&self.initializer));
|
||||
try_break!(visitor.visit_expression(&self.target));
|
||||
visitor.visit_statement(&self.body)
|
||||
}
|
||||
|
||||
fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
|
||||
where
|
||||
V: VisitorMut<'a>,
|
||||
{
|
||||
try_break!(visitor.visit_iterable_loop_initializer_mut(&mut self.initializer));
|
||||
try_break!(visitor.visit_expression_mut(&mut self.target));
|
||||
visitor.visit_statement_mut(&mut self.body)
|
||||
}
|
||||
}
|
||||
263
javascript-engine/external/boa/boa_ast/src/statement/iteration/for_loop.rs
vendored
Normal file
263
javascript-engine/external/boa/boa_ast/src/statement/iteration/for_loop.rs
vendored
Normal file
@@ -0,0 +1,263 @@
|
||||
use crate::try_break;
|
||||
use crate::visitor::{VisitWith, Visitor, VisitorMut};
|
||||
use crate::{
|
||||
declaration::{LexicalDeclaration, VarDeclaration},
|
||||
statement::Statement,
|
||||
Expression,
|
||||
};
|
||||
use boa_interner::{Interner, ToIndentedString, ToInternedString};
|
||||
use core::ops::ControlFlow;
|
||||
|
||||
/// The `for` statement creates a loop that consists of three optional expressions.
|
||||
///
|
||||
/// A [`for`][mdn] loop repeats until a specified condition evaluates to `false`.
|
||||
/// The JavaScript for loop is similar to the Java and C for loop.
|
||||
///
|
||||
/// More information:
|
||||
/// - [ECMAScript reference][spec]
|
||||
///
|
||||
/// [spec]: https://tc39.es/ecma262/#prod-ForDeclaration
|
||||
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct ForLoop {
|
||||
#[cfg_attr(feature = "serde", serde(flatten))]
|
||||
inner: Box<InnerForLoop>,
|
||||
}
|
||||
|
||||
impl ForLoop {
|
||||
/// Creates a new for loop AST node.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn new(
|
||||
init: Option<ForLoopInitializer>,
|
||||
condition: Option<Expression>,
|
||||
final_expr: Option<Expression>,
|
||||
body: Statement,
|
||||
) -> Self {
|
||||
Self {
|
||||
inner: Box::new(InnerForLoop::new(init, condition, final_expr, body)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the initialization node.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn init(&self) -> Option<&ForLoopInitializer> {
|
||||
self.inner.init()
|
||||
}
|
||||
|
||||
/// Gets the loop condition node.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn condition(&self) -> Option<&Expression> {
|
||||
self.inner.condition()
|
||||
}
|
||||
|
||||
/// Gets the final expression node.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn final_expr(&self) -> Option<&Expression> {
|
||||
self.inner.final_expr()
|
||||
}
|
||||
|
||||
/// Gets the body of the for loop.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn body(&self) -> &Statement {
|
||||
self.inner.body()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToIndentedString for ForLoop {
|
||||
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
|
||||
let mut buf = String::from("for (");
|
||||
if let Some(init) = self.init() {
|
||||
buf.push_str(&init.to_interned_string(interner));
|
||||
}
|
||||
buf.push_str("; ");
|
||||
if let Some(condition) = self.condition() {
|
||||
buf.push_str(&condition.to_interned_string(interner));
|
||||
}
|
||||
buf.push_str("; ");
|
||||
if let Some(final_expr) = self.final_expr() {
|
||||
buf.push_str(&final_expr.to_interned_string(interner));
|
||||
}
|
||||
buf.push_str(&format!(
|
||||
") {}",
|
||||
self.inner.body().to_indented_string(interner, indentation)
|
||||
));
|
||||
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ForLoop> for Statement {
|
||||
#[inline]
|
||||
fn from(for_loop: ForLoop) -> Self {
|
||||
Self::ForLoop(for_loop)
|
||||
}
|
||||
}
|
||||
|
||||
impl VisitWith for ForLoop {
|
||||
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
|
||||
where
|
||||
V: Visitor<'a>,
|
||||
{
|
||||
if let Some(fli) = &self.inner.init {
|
||||
try_break!(visitor.visit_for_loop_initializer(fli));
|
||||
}
|
||||
if let Some(expr) = &self.inner.condition {
|
||||
try_break!(visitor.visit_expression(expr));
|
||||
}
|
||||
if let Some(expr) = &self.inner.final_expr {
|
||||
try_break!(visitor.visit_expression(expr));
|
||||
}
|
||||
visitor.visit_statement(&self.inner.body)
|
||||
}
|
||||
|
||||
fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
|
||||
where
|
||||
V: VisitorMut<'a>,
|
||||
{
|
||||
if let Some(fli) = &mut self.inner.init {
|
||||
try_break!(visitor.visit_for_loop_initializer_mut(fli));
|
||||
}
|
||||
if let Some(expr) = &mut self.inner.condition {
|
||||
try_break!(visitor.visit_expression_mut(expr));
|
||||
}
|
||||
if let Some(expr) = &mut self.inner.final_expr {
|
||||
try_break!(visitor.visit_expression_mut(expr));
|
||||
}
|
||||
visitor.visit_statement_mut(&mut self.inner.body)
|
||||
}
|
||||
}
|
||||
|
||||
/// Inner structure to avoid multiple indirections in the heap.
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
struct InnerForLoop {
|
||||
init: Option<ForLoopInitializer>,
|
||||
condition: Option<Expression>,
|
||||
final_expr: Option<Expression>,
|
||||
body: Statement,
|
||||
}
|
||||
|
||||
impl InnerForLoop {
|
||||
/// Creates a new inner for loop.
|
||||
#[inline]
|
||||
const fn new(
|
||||
init: Option<ForLoopInitializer>,
|
||||
condition: Option<Expression>,
|
||||
final_expr: Option<Expression>,
|
||||
body: Statement,
|
||||
) -> Self {
|
||||
Self {
|
||||
init,
|
||||
condition,
|
||||
final_expr,
|
||||
body,
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the initialization node.
|
||||
#[inline]
|
||||
const fn init(&self) -> Option<&ForLoopInitializer> {
|
||||
self.init.as_ref()
|
||||
}
|
||||
|
||||
/// Gets the loop condition node.
|
||||
#[inline]
|
||||
const fn condition(&self) -> Option<&Expression> {
|
||||
self.condition.as_ref()
|
||||
}
|
||||
|
||||
/// Gets the final expression node.
|
||||
#[inline]
|
||||
const fn final_expr(&self) -> Option<&Expression> {
|
||||
self.final_expr.as_ref()
|
||||
}
|
||||
|
||||
/// Gets the body of the for loop.
|
||||
#[inline]
|
||||
const fn body(&self) -> &Statement {
|
||||
&self.body
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`ForLoop`] initializer, as defined by the [spec].
|
||||
///
|
||||
/// A `ForLoop` initializer differs a lot from an
|
||||
/// [`IterableLoopInitializer`][super::IterableLoopInitializer], since it can contain any arbitrary
|
||||
/// expression instead of only accessors and patterns. Additionally, it can also contain many variable
|
||||
/// declarations instead of only one.
|
||||
///
|
||||
/// [spec]: https://tc39.es/ecma262/#prod-ForStatement
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum ForLoopInitializer {
|
||||
/// An expression initializer.
|
||||
Expression(Expression),
|
||||
/// A var declaration initializer.
|
||||
Var(VarDeclaration),
|
||||
/// A lexical declaration initializer.
|
||||
Lexical(LexicalDeclaration),
|
||||
}
|
||||
|
||||
impl ToInternedString for ForLoopInitializer {
|
||||
fn to_interned_string(&self, interner: &Interner) -> String {
|
||||
match self {
|
||||
Self::Var(var) => var.to_interned_string(interner),
|
||||
Self::Lexical(lex) => lex.to_interned_string(interner),
|
||||
Self::Expression(expr) => expr.to_interned_string(interner),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Expression> for ForLoopInitializer {
|
||||
#[inline]
|
||||
fn from(expr: Expression) -> Self {
|
||||
Self::Expression(expr)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LexicalDeclaration> for ForLoopInitializer {
|
||||
#[inline]
|
||||
fn from(list: LexicalDeclaration) -> Self {
|
||||
Self::Lexical(list)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VarDeclaration> for ForLoopInitializer {
|
||||
#[inline]
|
||||
fn from(list: VarDeclaration) -> Self {
|
||||
Self::Var(list)
|
||||
}
|
||||
}
|
||||
|
||||
impl VisitWith for ForLoopInitializer {
|
||||
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
|
||||
where
|
||||
V: Visitor<'a>,
|
||||
{
|
||||
match self {
|
||||
Self::Expression(expr) => visitor.visit_expression(expr),
|
||||
Self::Var(vd) => visitor.visit_var_declaration(vd),
|
||||
Self::Lexical(ld) => visitor.visit_lexical_declaration(ld),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
|
||||
where
|
||||
V: VisitorMut<'a>,
|
||||
{
|
||||
match self {
|
||||
Self::Expression(expr) => visitor.visit_expression_mut(expr),
|
||||
Self::Var(vd) => visitor.visit_var_declaration_mut(vd),
|
||||
Self::Lexical(ld) => visitor.visit_lexical_declaration_mut(ld),
|
||||
}
|
||||
}
|
||||
}
|
||||
115
javascript-engine/external/boa/boa_ast/src/statement/iteration/for_of_loop.rs
vendored
Normal file
115
javascript-engine/external/boa/boa_ast/src/statement/iteration/for_of_loop.rs
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
use crate::try_break;
|
||||
use crate::visitor::{VisitWith, Visitor, VisitorMut};
|
||||
use crate::{
|
||||
expression::Expression,
|
||||
statement::{iteration::IterableLoopInitializer, Statement},
|
||||
};
|
||||
use boa_interner::{Interner, ToIndentedString, ToInternedString};
|
||||
use core::ops::ControlFlow;
|
||||
|
||||
/// A `for...of` loop statement, as defined by the [spec].
|
||||
///
|
||||
/// [`for..of`][forof] statements loop over a sequence of values obtained from an iterable object (Array,
|
||||
/// String, Map, generators).
|
||||
///
|
||||
/// This type combines `for..of` and [`for await...of`][forawait] statements in a single structure,
|
||||
/// since `for await...of` is essentially the same statement but with async iterable objects
|
||||
/// as the source of iteration.
|
||||
///
|
||||
/// [forof]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of
|
||||
/// [spec]: https://tc39.es/ecma262/#prod-ForInOfStatement
|
||||
/// [forawait]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct ForOfLoop {
|
||||
init: IterableLoopInitializer,
|
||||
iterable: Expression,
|
||||
body: Box<Statement>,
|
||||
r#await: bool,
|
||||
}
|
||||
|
||||
impl ForOfLoop {
|
||||
/// Creates a new "for of" loop AST node.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn new(
|
||||
init: IterableLoopInitializer,
|
||||
iterable: Expression,
|
||||
body: Statement,
|
||||
r#await: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
init,
|
||||
iterable,
|
||||
body: body.into(),
|
||||
r#await,
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the initializer of the for...of loop.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn initializer(&self) -> &IterableLoopInitializer {
|
||||
&self.init
|
||||
}
|
||||
|
||||
/// Gets the iterable expression of the for...of loop.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn iterable(&self) -> &Expression {
|
||||
&self.iterable
|
||||
}
|
||||
|
||||
/// Gets the body to execute in the for...of loop.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn body(&self) -> &Statement {
|
||||
&self.body
|
||||
}
|
||||
|
||||
/// Returns true if this "for...of" loop is an "for await...of" loop.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn r#await(&self) -> bool {
|
||||
self.r#await
|
||||
}
|
||||
}
|
||||
|
||||
impl ToIndentedString for ForOfLoop {
|
||||
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
|
||||
format!(
|
||||
"for ({} of {}) {}",
|
||||
self.init.to_interned_string(interner),
|
||||
self.iterable.to_interned_string(interner),
|
||||
self.body().to_indented_string(interner, indentation)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ForOfLoop> for Statement {
|
||||
#[inline]
|
||||
fn from(for_of: ForOfLoop) -> Self {
|
||||
Self::ForOfLoop(for_of)
|
||||
}
|
||||
}
|
||||
|
||||
impl VisitWith for ForOfLoop {
|
||||
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
|
||||
where
|
||||
V: Visitor<'a>,
|
||||
{
|
||||
try_break!(visitor.visit_iterable_loop_initializer(&self.init));
|
||||
try_break!(visitor.visit_expression(&self.iterable));
|
||||
visitor.visit_statement(&self.body)
|
||||
}
|
||||
|
||||
fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
|
||||
where
|
||||
V: VisitorMut<'a>,
|
||||
{
|
||||
try_break!(visitor.visit_iterable_loop_initializer_mut(&mut self.init));
|
||||
try_break!(visitor.visit_expression_mut(&mut self.iterable));
|
||||
visitor.visit_statement_mut(&mut self.body)
|
||||
}
|
||||
}
|
||||
94
javascript-engine/external/boa/boa_ast/src/statement/iteration/mod.rs
vendored
Normal file
94
javascript-engine/external/boa/boa_ast/src/statement/iteration/mod.rs
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
//! Iteration nodes
|
||||
|
||||
mod r#break;
|
||||
mod r#continue;
|
||||
mod do_while_loop;
|
||||
mod for_in_loop;
|
||||
mod for_loop;
|
||||
mod for_of_loop;
|
||||
mod while_loop;
|
||||
|
||||
use crate::{
|
||||
declaration::Binding,
|
||||
expression::{access::PropertyAccess, Identifier},
|
||||
pattern::Pattern,
|
||||
};
|
||||
use core::ops::ControlFlow;
|
||||
|
||||
pub use self::{
|
||||
do_while_loop::DoWhileLoop,
|
||||
for_in_loop::ForInLoop,
|
||||
for_loop::{ForLoop, ForLoopInitializer},
|
||||
for_of_loop::ForOfLoop,
|
||||
r#break::Break,
|
||||
r#continue::Continue,
|
||||
while_loop::WhileLoop,
|
||||
};
|
||||
use crate::visitor::{VisitWith, Visitor, VisitorMut};
|
||||
use boa_interner::{Interner, ToInternedString};
|
||||
|
||||
/// A `for-in`, `for-of` and `for-await-of` loop initializer.
|
||||
///
|
||||
/// The [spec] specifies only single bindings for the listed types of loops, which makes us
|
||||
/// unable to use plain `LexicalDeclaration`s or `VarStatement`s as initializers, since those
|
||||
/// can have more than one binding.
|
||||
///
|
||||
/// [spec]: https://tc39.es/ecma262/#prod-ForInOfStatement
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum IterableLoopInitializer {
|
||||
/// An already declared variable.
|
||||
Identifier(Identifier),
|
||||
/// A property access.
|
||||
Access(PropertyAccess),
|
||||
/// A new var declaration.
|
||||
Var(Binding),
|
||||
/// A new let declaration.
|
||||
Let(Binding),
|
||||
/// A new const declaration.
|
||||
Const(Binding),
|
||||
/// A pattern with already declared variables.
|
||||
Pattern(Pattern),
|
||||
}
|
||||
|
||||
impl ToInternedString for IterableLoopInitializer {
|
||||
fn to_interned_string(&self, interner: &Interner) -> String {
|
||||
let (binding, pre) = match self {
|
||||
Self::Identifier(ident) => return ident.to_interned_string(interner),
|
||||
Self::Pattern(pattern) => return pattern.to_interned_string(interner),
|
||||
Self::Access(access) => return access.to_interned_string(interner),
|
||||
Self::Var(binding) => (binding, "var"),
|
||||
Self::Let(binding) => (binding, "let"),
|
||||
Self::Const(binding) => (binding, "const"),
|
||||
};
|
||||
|
||||
format!("{pre} {}", binding.to_interned_string(interner))
|
||||
}
|
||||
}
|
||||
|
||||
impl VisitWith for IterableLoopInitializer {
|
||||
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
|
||||
where
|
||||
V: Visitor<'a>,
|
||||
{
|
||||
match self {
|
||||
Self::Identifier(id) => visitor.visit_identifier(id),
|
||||
Self::Access(pa) => visitor.visit_property_access(pa),
|
||||
Self::Var(b) | Self::Let(b) | Self::Const(b) => visitor.visit_binding(b),
|
||||
Self::Pattern(p) => visitor.visit_pattern(p),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
|
||||
where
|
||||
V: VisitorMut<'a>,
|
||||
{
|
||||
match self {
|
||||
Self::Identifier(id) => visitor.visit_identifier_mut(id),
|
||||
Self::Access(pa) => visitor.visit_property_access_mut(pa),
|
||||
Self::Var(b) | Self::Let(b) | Self::Const(b) => visitor.visit_binding_mut(b),
|
||||
Self::Pattern(p) => visitor.visit_pattern_mut(p),
|
||||
}
|
||||
}
|
||||
}
|
||||
88
javascript-engine/external/boa/boa_ast/src/statement/iteration/while_loop.rs
vendored
Normal file
88
javascript-engine/external/boa/boa_ast/src/statement/iteration/while_loop.rs
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
use crate::{
|
||||
expression::Expression,
|
||||
statement::Statement,
|
||||
try_break,
|
||||
visitor::{VisitWith, Visitor, VisitorMut},
|
||||
};
|
||||
use boa_interner::{Interner, ToIndentedString, ToInternedString};
|
||||
use core::ops::ControlFlow;
|
||||
|
||||
/// The `while` statement creates a loop that executes a specified statement as long as the
|
||||
/// test condition evaluates to `true`.
|
||||
///
|
||||
/// The condition is evaluated before executing the statement.
|
||||
///
|
||||
/// More information:
|
||||
/// - [ECMAScript reference][spec]
|
||||
/// - [MDN documentation][mdn]
|
||||
///
|
||||
/// [spec]: https://tc39.es/ecma262/#prod-grammar-notation-WhileStatement
|
||||
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/while
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct WhileLoop {
|
||||
condition: Expression,
|
||||
body: Box<Statement>,
|
||||
}
|
||||
|
||||
impl WhileLoop {
|
||||
/// Creates a `WhileLoop` AST node.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn new(condition: Expression, body: Statement) -> Self {
|
||||
Self {
|
||||
condition,
|
||||
body: body.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the condition of the while loop.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn condition(&self) -> &Expression {
|
||||
&self.condition
|
||||
}
|
||||
|
||||
/// Gets the body of the while loop.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn body(&self) -> &Statement {
|
||||
&self.body
|
||||
}
|
||||
}
|
||||
|
||||
impl ToIndentedString for WhileLoop {
|
||||
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
|
||||
format!(
|
||||
"while ({}) {}",
|
||||
self.condition().to_interned_string(interner),
|
||||
self.body().to_indented_string(interner, indentation)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<WhileLoop> for Statement {
|
||||
#[inline]
|
||||
fn from(while_loop: WhileLoop) -> Self {
|
||||
Self::WhileLoop(while_loop)
|
||||
}
|
||||
}
|
||||
|
||||
impl VisitWith for WhileLoop {
|
||||
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
|
||||
where
|
||||
V: Visitor<'a>,
|
||||
{
|
||||
try_break!(visitor.visit_expression(&self.condition));
|
||||
visitor.visit_statement(&self.body)
|
||||
}
|
||||
|
||||
fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
|
||||
where
|
||||
V: VisitorMut<'a>,
|
||||
{
|
||||
try_break!(visitor.visit_expression_mut(&mut self.condition));
|
||||
visitor.visit_statement_mut(&mut self.body)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user