Browse Source

Removed some duplicate code, added `ToIndentedString` (#2367)

In most cases, the `ToInternedString` was just calling `self.to_indented_string(interner, 0)`. This avoids all this duplicate code by adding a new trait, `ToIndentedString`. Any type implementing that automatically implements `ToInternedString`.

I have also added a bunch of `#[inline]` in one-liners, and some one-line documentations for some functions.

I have noticed that we also use `contains()` and `contains_arguments()` a lot. Would it make sense to create traits for this?
pull/2370/head
Iban Eguia Moraza 2 years ago
parent
commit
f4cef141b0
  1. 29
      boa_engine/src/syntax/ast/declaration/mod.rs
  2. 2
      boa_engine/src/syntax/ast/expression/await.rs
  3. 39
      boa_engine/src/syntax/ast/expression/literal/object/mod.rs
  4. 14
      boa_engine/src/syntax/ast/expression/mod.rs
  5. 38
      boa_engine/src/syntax/ast/function/arrow_function.rs
  6. 19
      boa_engine/src/syntax/ast/function/async_function.rs
  7. 18
      boa_engine/src/syntax/ast/function/async_generator.rs
  8. 19
      boa_engine/src/syntax/ast/function/class.rs
  9. 19
      boa_engine/src/syntax/ast/function/generator.rs
  10. 19
      boa_engine/src/syntax/ast/function/mod.rs
  11. 2
      boa_engine/src/syntax/ast/mod.rs
  12. 30
      boa_engine/src/syntax/ast/statement/block.rs
  13. 44
      boa_engine/src/syntax/ast/statement/if.rs
  14. 26
      boa_engine/src/syntax/ast/statement/iteration/do_while_loop.rs
  15. 37
      boa_engine/src/syntax/ast/statement/iteration/for_in_loop.rs
  16. 61
      boa_engine/src/syntax/ast/statement/iteration/for_loop.rs
  17. 32
      boa_engine/src/syntax/ast/statement/iteration/for_of_loop.rs
  18. 40
      boa_engine/src/syntax/ast/statement/iteration/while_loop.rs
  19. 6
      boa_engine/src/syntax/ast/statement/labelled.rs
  20. 46
      boa_engine/src/syntax/ast/statement/mod.rs
  21. 45
      boa_engine/src/syntax/ast/statement/switch/mod.rs
  22. 39
      boa_engine/src/syntax/ast/statement/try/mod.rs
  23. 118
      boa_engine/src/syntax/ast/statement_list/mod.rs
  24. 3
      boa_engine/src/syntax/parser/expression/tests.rs
  25. 12
      boa_interner/src/lib.rs

29
boa_engine/src/syntax/ast/declaration/mod.rs

@ -1,11 +1,10 @@
use boa_interner::{Interner, ToInternedString};
use tap::Tap;
use super::{
expression::Identifier,
function::{AsyncFunction, AsyncGenerator, Class, Function, Generator},
ContainsSymbol,
};
use boa_interner::{Interner, ToIndentedString, ToInternedString};
use tap::Tap;
mod variable;
@ -34,17 +33,6 @@ pub enum Declaration {
}
impl Declaration {
pub(super) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
match self {
Declaration::Function(f) => f.to_indented_string(interner, indentation),
Declaration::Generator(g) => g.to_indented_string(interner, indentation),
Declaration::AsyncFunction(af) => af.to_indented_string(interner, indentation),
Declaration::AsyncGenerator(ag) => ag.to_indented_string(interner, indentation),
Declaration::Class(c) => c.to_indented_string(interner, indentation),
Declaration::Lexical(l) => l.to_interned_string(interner).tap_mut(|s| s.push(';')),
}
}
/// Return the lexically declared names of a `Declaration`.
///
/// The returned list may contain duplicates.
@ -146,8 +134,15 @@ impl Declaration {
}
}
impl ToInternedString for Declaration {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
impl ToIndentedString for Declaration {
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
match self {
Declaration::Function(f) => f.to_indented_string(interner, indentation),
Declaration::Generator(g) => g.to_indented_string(interner, indentation),
Declaration::AsyncFunction(af) => af.to_indented_string(interner, indentation),
Declaration::AsyncGenerator(ag) => ag.to_indented_string(interner, indentation),
Declaration::Class(c) => c.to_indented_string(interner, indentation),
Declaration::Lexical(l) => l.to_interned_string(interner).tap_mut(|s| s.push(';')),
}
}
}

2
boa_engine/src/syntax/ast/expression/await.rs

@ -3,7 +3,7 @@
use crate::syntax::ast::ContainsSymbol;
use super::Expression;
use boa_interner::{Interner, ToInternedString};
use boa_interner::{Interner, ToIndentedString, ToInternedString};
/// An await expression is used within an async function to pause execution and wait for a
/// promise to resolve.

39
boa_engine/src/syntax/ast/expression/literal/object/mod.rs

@ -10,7 +10,7 @@ use crate::syntax::ast::{
property::{MethodDefinition, PropertyDefinition},
ContainsSymbol,
};
use boa_interner::{Interner, ToInternedString};
use boa_interner::{Interner, ToIndentedString, ToInternedString};
/// Objects in JavaScript may be defined as an unordered collection of related data, of
/// primitive or reference types, in the form of “key: value” pairs.
@ -39,13 +39,27 @@ pub struct ObjectLiteral {
}
impl ObjectLiteral {
/// Gets the object literal properties
#[inline]
pub fn properties(&self) -> &[PropertyDefinition] {
&self.properties
}
/// Implements the display formatting with indentation.
pub(crate) fn to_indented_string(&self, interner: &Interner, indent_n: usize) -> String {
#[inline]
pub(crate) fn contains_arguments(&self) -> bool {
self.properties
.iter()
.any(PropertyDefinition::contains_arguments)
}
#[inline]
pub(crate) fn contains(&self, symbol: ContainsSymbol) -> bool {
self.properties.iter().any(|prop| prop.contains(symbol))
}
}
impl ToIndentedString for ObjectLiteral {
fn to_indented_string(&self, interner: &Interner, indent_n: usize) -> String {
let mut buf = "{\n".to_owned();
let indentation = " ".repeat(indent_n + 1);
for property in self.properties().iter() {
@ -119,25 +133,6 @@ impl ObjectLiteral {
buf
}
#[inline]
pub(crate) fn contains_arguments(&self) -> bool {
self.properties
.iter()
.any(PropertyDefinition::contains_arguments)
}
#[inline]
pub(crate) fn contains(&self, symbol: ContainsSymbol) -> bool {
self.properties.iter().any(|prop| prop.contains(symbol))
}
}
impl ToInternedString for ObjectLiteral {
#[inline]
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
}
}
impl<T> From<T> for ObjectLiteral

14
boa_engine/src/syntax/ast/expression/mod.rs

@ -1,4 +1,4 @@
use boa_interner::{Interner, Sym, ToInternedString};
use boa_interner::{Interner, Sym, ToIndentedString, ToInternedString};
use self::{
access::{PrivatePropertyAccess, PropertyAccess, SuperPropertyAccess},
@ -142,12 +142,6 @@ pub enum Expression {
}
impl Expression {
/// Creates a string of the value of the expression with the given indentation.
#[inline]
pub fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
self.to_no_indent_string(interner, indentation)
}
/// Implements the display formatting with indentation.
///
/// This will not prefix the value with any indentation. If you want to prefix this with proper
@ -281,9 +275,9 @@ impl From<Expression> for Statement {
}
}
impl ToInternedString for Expression {
impl ToIndentedString for Expression {
#[inline]
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
self.to_no_indent_string(interner, indentation)
}
}

38
boa_engine/src/syntax/ast/function/arrow_function.rs

@ -2,7 +2,7 @@ use crate::syntax::ast::{
expression::{Expression, Identifier},
join_nodes, ContainsSymbol, StatementList,
};
use boa_interner::{Interner, ToInternedString};
use boa_interner::{Interner, ToIndentedString};
use super::FormalParameterList;
@ -29,6 +29,7 @@ pub struct ArrowFunction {
impl ArrowFunction {
/// Creates a new `ArrowFunctionDecl` AST Expression.
#[inline]
pub(in crate::syntax) fn new(
name: Option<Identifier>,
params: FormalParameterList,
@ -42,40 +43,29 @@ impl ArrowFunction {
}
/// Gets the name of the function declaration.
#[inline]
pub fn name(&self) -> Option<Identifier> {
self.name
}
/// Sets the name of the function declaration.
#[inline]
pub fn set_name(&mut self, name: Option<Identifier>) {
self.name = name;
}
/// Gets the list of parameters of the arrow function.
#[inline]
pub(crate) fn parameters(&self) -> &FormalParameterList {
&self.parameters
}
/// Gets the body of the arrow function.
#[inline]
pub(crate) fn body(&self) -> &StatementList {
&self.body
}
/// Implements the display formatting with indentation.
pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
let mut buf = format!("({}", join_nodes(interner, &self.parameters.parameters));
if self.body().statements().is_empty() {
buf.push_str(") => {}");
} else {
buf.push_str(&format!(
") => {{\n{}{}}}",
self.body.to_indented_string(interner, indentation + 1),
" ".repeat(indentation)
));
}
buf
}
#[inline]
pub(crate) fn contains_arguments(&self) -> bool {
self.parameters.contains_arguments() || self.body.contains_arguments()
@ -97,9 +87,19 @@ impl ArrowFunction {
}
}
impl ToInternedString for ArrowFunction {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
impl ToIndentedString for ArrowFunction {
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
let mut buf = format!("({}", join_nodes(interner, &self.parameters.parameters));
if self.body().statements().is_empty() {
buf.push_str(") => {}");
} else {
buf.push_str(&format!(
") => {{\n{}{}}}",
self.body.to_indented_string(interner, indentation + 1),
" ".repeat(indentation)
));
}
buf
}
}

19
boa_engine/src/syntax/ast/function/async_function.rs

@ -4,7 +4,7 @@ use crate::syntax::ast::{
expression::{Expression, Identifier},
join_nodes, Declaration, StatementList,
};
use boa_interner::{Interner, ToInternedString};
use boa_interner::{Interner, ToIndentedString};
use super::FormalParameterList;
@ -27,6 +27,7 @@ pub struct AsyncFunction {
impl AsyncFunction {
/// Creates a new function expression
#[inline]
pub(in crate::syntax) fn new(
name: Option<Identifier>,
parameters: FormalParameterList,
@ -40,22 +41,26 @@ impl AsyncFunction {
}
/// Gets the name of the function declaration.
#[inline]
pub fn name(&self) -> Option<Identifier> {
self.name
}
/// Gets the list of parameters of the function declaration.
#[inline]
pub fn parameters(&self) -> &FormalParameterList {
&self.parameters
}
/// Gets the body of the function declaration.
#[inline]
pub fn body(&self) -> &StatementList {
&self.body
}
}
/// Implements the display formatting with indentation.
pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
impl ToIndentedString for AsyncFunction {
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
let mut buf = "async function".to_owned();
if let Some(name) = self.name {
buf.push_str(&format!(" {}", interner.resolve_expect(name.sym())));
@ -77,19 +82,15 @@ impl AsyncFunction {
}
}
impl ToInternedString for AsyncFunction {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
}
}
impl From<AsyncFunction> for Expression {
#[inline]
fn from(expr: AsyncFunction) -> Self {
Self::AsyncFunction(expr)
}
}
impl From<AsyncFunction> for Declaration {
#[inline]
fn from(f: AsyncFunction) -> Self {
Self::AsyncFunction(f)
}

18
boa_engine/src/syntax/ast/function/async_generator.rs

@ -4,7 +4,7 @@ use crate::syntax::ast::{
expression::{Expression, Identifier},
join_nodes, Declaration, StatementList,
};
use boa_interner::{Interner, ToInternedString};
use boa_interner::{Interner, ToIndentedString};
use super::FormalParameterList;
@ -24,6 +24,7 @@ pub struct AsyncGenerator {
impl AsyncGenerator {
/// Creates a new async generator expression
#[inline]
pub(in crate::syntax) fn new(
name: Option<Identifier>,
parameters: FormalParameterList,
@ -37,21 +38,26 @@ impl AsyncGenerator {
}
/// Gets the name of the async generator expression
#[inline]
pub fn name(&self) -> Option<Identifier> {
self.name
}
/// Gets the list of parameters of the async generator expression
#[inline]
pub fn parameters(&self) -> &FormalParameterList {
&self.parameters
}
/// Gets the body of the async generator expression
#[inline]
pub fn body(&self) -> &StatementList {
&self.body
}
}
pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
impl ToIndentedString for AsyncGenerator {
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
let mut buf = "async function*".to_owned();
if let Some(name) = self.name {
buf.push_str(&format!(" {}", interner.resolve_expect(name.sym())));
@ -66,19 +72,15 @@ impl AsyncGenerator {
}
}
impl ToInternedString for AsyncGenerator {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
}
}
impl From<AsyncGenerator> for Expression {
#[inline]
fn from(expr: AsyncGenerator) -> Self {
Self::AsyncGenerator(expr)
}
}
impl From<AsyncGenerator> for Declaration {
#[inline]
fn from(f: AsyncGenerator) -> Self {
Self::AsyncGenerator(f)
}

19
boa_engine/src/syntax/ast/function/class.rs

@ -11,7 +11,7 @@ use crate::{
ContainsSymbol, Declaration, StatementList,
},
};
use boa_interner::{Interner, Sym, ToInternedString};
use boa_interner::{Interner, Sym, ToIndentedString, ToInternedString};
use super::Function;
@ -36,6 +36,7 @@ pub struct Class {
impl Class {
/// Creates a new class declaration.
#[inline]
pub(in crate::syntax) fn new(
name: Option<Identifier>,
super_ref: Option<Expression>,
@ -51,25 +52,30 @@ impl Class {
}
/// Returns the name of the class.
#[inline]
pub(crate) fn name(&self) -> Option<Identifier> {
self.name
}
/// Returns the super class ref of the class.
#[inline]
pub(crate) fn super_ref(&self) -> Option<&Expression> {
self.super_ref.as_ref()
}
/// Returns the constructor of the class.
#[inline]
pub(crate) fn constructor(&self) -> Option<&Function> {
self.constructor.as_ref()
}
/// Gets the list of all fields defined on the class.
#[inline]
pub(crate) fn elements(&self) -> &[ClassElement] {
&self.elements
}
#[inline]
pub(crate) fn contains_arguments(&self) -> bool {
matches!(self.name, Some(ref ident) if *ident == Sym::ARGUMENTS)
|| matches!(self.super_ref, Some(ref expr) if expr.contains_arguments())
@ -88,9 +94,10 @@ impl Class {
matches!(self.super_ref, Some(ref expr) if expr.contains(symbol))
|| self.elements.iter().any(|elem| elem.contains(symbol))
}
}
/// Implements the display formatting with indentation.
pub(crate) fn to_indented_string(&self, interner: &Interner, indent_n: usize) -> String {
impl ToIndentedString for Class {
fn to_indented_string(&self, interner: &Interner, indent_n: usize) -> String {
let class_name = self.name.map_or(Cow::Borrowed(""), |s| {
interner.resolve_expect(s.sym()).join(
Cow::Borrowed,
@ -362,12 +369,6 @@ impl Class {
}
}
impl ToInternedString for Class {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
}
}
impl From<Class> for Expression {
fn from(expr: Class) -> Self {
Self::Class(Box::new(expr))

19
boa_engine/src/syntax/ast/function/generator.rs

@ -4,7 +4,7 @@ use crate::syntax::ast::{
join_nodes, Declaration, StatementList,
};
use boa_interner::{Interner, ToInternedString};
use boa_interner::{Interner, ToIndentedString};
use super::FormalParameterList;
@ -26,6 +26,7 @@ pub struct Generator {
impl Generator {
/// Creates a new generator expression
#[inline]
pub(in crate::syntax) fn new(
name: Option<Identifier>,
parameters: FormalParameterList,
@ -39,22 +40,26 @@ impl Generator {
}
/// Gets the name of the generator declaration.
#[inline]
pub fn name(&self) -> Option<Identifier> {
self.name
}
/// Gets the list of parameters of the generator declaration.
#[inline]
pub fn parameters(&self) -> &FormalParameterList {
&self.parameters
}
/// Gets the body of the generator declaration.
#[inline]
pub fn body(&self) -> &StatementList {
&self.body
}
}
/// Converts the generator expresion Expression to a string with indentation.
pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
impl ToIndentedString for Generator {
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
let mut buf = "function*".to_owned();
if let Some(name) = self.name {
buf.push_str(&format!(" {}", interner.resolve_expect(name.sym())));
@ -69,19 +74,15 @@ impl Generator {
}
}
impl ToInternedString for Generator {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
}
}
impl From<Generator> for Expression {
#[inline]
fn from(expr: Generator) -> Self {
Self::Generator(expr)
}
}
impl From<Generator> for Declaration {
#[inline]
fn from(f: Generator) -> Self {
Self::Generator(f)
}

19
boa_engine/src/syntax/ast/function/mod.rs

@ -15,7 +15,7 @@ pub use parameters::{FormalParameter, FormalParameterList};
pub(crate) use parameters::FormalParameterListFlags;
use crate::syntax::ast::{block_to_string, join_nodes, StatementList};
use boa_interner::{Interner, ToInternedString};
use boa_interner::{Interner, ToIndentedString};
use super::expression::{Expression, Identifier};
use super::{ContainsSymbol, Declaration};
@ -46,6 +46,7 @@ pub struct Function {
impl Function {
/// Creates a new function expression
#[inline]
pub(in crate::syntax) fn new(
name: Option<Identifier>,
parameters: FormalParameterList,
@ -59,22 +60,26 @@ impl Function {
}
/// Gets the name of the function declaration.
#[inline]
pub fn name(&self) -> Option<Identifier> {
self.name
}
/// Gets the list of parameters of the function declaration.
#[inline]
pub fn parameters(&self) -> &FormalParameterList {
&self.parameters
}
/// Gets the body of the function declaration.
#[inline]
pub fn body(&self) -> &StatementList {
&self.body
}
}
/// Implements the display formatting with indentation.
pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
impl ToIndentedString for Function {
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
let mut buf = "function".to_owned();
if let Some(name) = self.name {
buf.push_str(&format!(" {}", interner.resolve_expect(name.sym())));
@ -89,19 +94,15 @@ impl Function {
}
}
impl ToInternedString for Function {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
}
}
impl From<Function> for Expression {
#[inline]
fn from(expr: Function) -> Self {
Self::Function(expr)
}
}
impl From<Function> for Declaration {
#[inline]
fn from(f: Function) -> Self {
Self::Function(f)
}

2
boa_engine/src/syntax/ast/mod.rs

@ -11,7 +11,7 @@ pub mod punctuator;
pub mod statement;
pub mod statement_list;
use boa_interner::{Interner, ToInternedString};
use boa_interner::{Interner, ToIndentedString, ToInternedString};
pub use self::{
declaration::Declaration,

30
boa_engine/src/syntax/ast/statement/block.rs

@ -1,9 +1,8 @@
//! Block AST node.
use crate::syntax::ast::{expression::Identifier, ContainsSymbol, StatementList};
use super::Statement;
use boa_interner::{Interner, ToInternedString};
use crate::syntax::ast::{expression::Identifier, ContainsSymbol, StatementList};
use boa_interner::{Interner, ToIndentedString};
/// A `block` statement (or compound statement in other languages) is used to group zero or
/// more statements.
@ -29,25 +28,17 @@ pub struct Block {
impl Block {
/// Gets the list of statements and declarations in this block.
#[inline]
pub(crate) fn statement_list(&self) -> &StatementList {
&self.statements
}
/// Get the lexically declared names of the block.
#[inline]
pub(crate) fn lexically_declared_names(&self) -> Vec<(Identifier, bool)> {
self.statements.lexically_declared_names()
}
/// Implements the display formatting with indentation.
pub(super) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
format!(
"{{\n{}{}}}",
self.statements
.to_indented_string(interner, indentation + 1),
" ".repeat(indentation)
)
}
#[inline]
pub(crate) fn contains_arguments(&self) -> bool {
self.statements.contains_arguments()
@ -63,6 +54,7 @@ impl<T> From<T> for Block
where
T: Into<StatementList>,
{
#[inline]
fn from(list: T) -> Self {
Self {
statements: list.into(),
@ -70,13 +62,19 @@ where
}
}
impl ToInternedString for Block {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
impl ToIndentedString for Block {
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
format!(
"{{\n{}{}}}",
self.statements
.to_indented_string(interner, indentation + 1),
" ".repeat(indentation)
)
}
}
impl From<Block> for Statement {
#[inline]
fn from(block: Block) -> Self {
Self::Block(block)
}

44
boa_engine/src/syntax/ast/statement/if.rs

@ -1,7 +1,7 @@
//! If statement
use crate::syntax::ast::{expression::Expression, statement::Statement, ContainsSymbol};
use boa_interner::{Interner, ToInternedString};
use boa_interner::{Interner, ToIndentedString, ToInternedString};
/// The `if` statement executes a statement if a specified condition is [`truthy`][truthy]. If
/// the condition is [`falsy`][falsy], another statement can be executed.
@ -28,14 +28,20 @@ pub struct If {
}
impl If {
/// Gets the condition of the if statement.
#[inline]
pub fn cond(&self) -> &Expression {
&self.condition
}
/// Gets the body to execute if the condition is true.
#[inline]
pub fn body(&self) -> &Statement {
&self.body
}
/// Gets the `else` node, if it has one.
#[inline]
pub fn else_node(&self) -> Option<&Statement> {
self.else_node.as_ref().map(Box::as_ref)
}
@ -49,23 +55,6 @@ impl If {
}
}
pub(crate) fn to_indented_string(&self, interner: &Interner, indent: usize) -> String {
let mut buf = format!("if ({}) ", self.cond().to_interned_string(interner));
match self.else_node() {
Some(else_e) => {
buf.push_str(&format!(
"{} else {}",
self.body().to_indented_string(interner, indent),
else_e.to_indented_string(interner, indent)
));
}
None => {
buf.push_str(&self.body().to_indented_string(interner, indent));
}
}
buf
}
#[inline]
pub(crate) fn contains_arguments(&self) -> bool {
self.condition.contains_arguments()
@ -81,9 +70,22 @@ impl If {
}
}
impl ToInternedString for If {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
impl ToIndentedString for If {
fn to_indented_string(&self, interner: &Interner, indent: usize) -> String {
let mut buf = format!("if ({}) ", self.cond().to_interned_string(interner));
match self.else_node() {
Some(else_e) => {
buf.push_str(&format!(
"{} else {}",
self.body().to_indented_string(interner, indent),
else_e.to_indented_string(interner, indent)
));
}
None => {
buf.push_str(&self.body().to_indented_string(interner, indent));
}
}
buf
}
}

26
boa_engine/src/syntax/ast/statement/iteration/do_while_loop.rs

@ -1,5 +1,5 @@
use crate::syntax::ast::{expression::Expression, statement::Statement, ContainsSymbol};
use boa_interner::{Interner, ToInternedString};
use boa_interner::{Interner, ToIndentedString, ToInternedString};
/// The `do...while` statement creates a loop that executes a specified statement until the
/// test condition evaluates to false.
@ -21,14 +21,19 @@ pub struct DoWhileLoop {
}
impl DoWhileLoop {
/// Gets the body of the do-while loop.
#[inline]
pub fn body(&self) -> &Statement {
&self.body
}
/// Gets the condition of the do-while loop.
#[inline]
pub fn cond(&self) -> &Expression {
&self.condition
}
/// Creates a `DoWhileLoop` AST node.
#[inline]
pub fn new(body: Statement, condition: Expression) -> Self {
Self {
body: body.into(),
@ -36,15 +41,6 @@ impl DoWhileLoop {
}
}
/// Converts the "do while" loop to a string with the given indentation.
pub(crate) 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)
)
}
#[inline]
pub(crate) fn contains_arguments(&self) -> bool {
self.body.contains_arguments() || self.condition.contains_arguments()
@ -56,9 +52,13 @@ impl DoWhileLoop {
}
}
impl ToInternedString for DoWhileLoop {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
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)
)
}
}

37
boa_engine/src/syntax/ast/statement/iteration/for_in_loop.rs

@ -3,7 +3,8 @@ use crate::syntax::ast::{
statement::{iteration::IterableLoopInitializer, Statement},
ContainsSymbol,
};
use boa_interner::{Interner, ToInternedString};
use boa_interner::{Interner, ToIndentedString, ToInternedString};
#[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq)]
pub struct ForInLoop {
@ -13,6 +14,8 @@ pub struct ForInLoop {
}
impl ForInLoop {
/// Creates a new `ForInLoop`.
#[inline]
pub fn new(init: IterableLoopInitializer, expr: Expression, body: Statement) -> Self {
Self {
init,
@ -21,30 +24,24 @@ impl ForInLoop {
}
}
/// Gets the initializer of the for...in loop.
#[inline]
pub fn init(&self) -> &IterableLoopInitializer {
&self.init
}
/// Gets the for...in loop expression.
#[inline]
pub fn expr(&self) -> &Expression {
&self.expr
}
/// Gets the body of the for...in loop.
#[inline]
pub fn body(&self) -> &Statement {
&self.body
}
/// Converts the "for in" loop to a string with the given indentation.
pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
let mut buf = format!(
"for ({} in {}) ",
self.init.to_interned_string(interner),
self.expr.to_interned_string(interner)
);
buf.push_str(&self.body().to_indented_string(interner, indentation));
buf
}
#[inline]
pub(crate) fn contains_arguments(&self) -> bool {
self.init.contains_arguments()
@ -58,13 +55,21 @@ impl ForInLoop {
}
}
impl ToInternedString for ForInLoop {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
impl ToIndentedString for ForInLoop {
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
let mut buf = format!(
"for ({} in {}) ",
self.init.to_interned_string(interner),
self.expr.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)
}

61
boa_engine/src/syntax/ast/statement/iteration/for_loop.rs

@ -4,7 +4,7 @@ use crate::syntax::ast::{
statement::Statement,
ContainsSymbol, Expression,
};
use boa_interner::{Interner, ToInternedString};
use boa_interner::{Interner, ToIndentedString, ToInternedString};
/// The `for` statement creates a loop that consists of three optional expressions.
///
@ -26,6 +26,7 @@ pub struct ForLoop {
impl ForLoop {
/// Creates a new for loop AST node.
#[inline]
pub(in crate::syntax) fn new(
init: Option<ForLoopInitializer>,
condition: Option<Expression>,
@ -38,47 +39,29 @@ impl ForLoop {
}
/// Gets the initialization node.
#[inline]
pub fn init(&self) -> Option<&ForLoopInitializer> {
self.inner.init()
}
/// Gets the loop condition node.
#[inline]
pub fn condition(&self) -> Option<&Expression> {
self.inner.condition()
}
/// Gets the final expression node.
#[inline]
pub fn final_expr(&self) -> Option<&Expression> {
self.inner.final_expr()
}
/// Gets the body of the for loop.
#[inline]
pub fn body(&self) -> &Statement {
self.inner.body()
}
/// Converts the for loop to a string with the given indentation.
pub(crate) 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
}
#[inline]
pub(crate) fn contains_arguments(&self) -> bool {
let inner = &self.inner;
@ -98,13 +81,31 @@ impl ForLoop {
}
}
impl ToInternedString for ForLoop {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
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)
}
@ -122,6 +123,7 @@ struct InnerForLoop {
impl InnerForLoop {
/// Creates a new inner for loop.
#[inline]
fn new(
init: Option<ForLoopInitializer>,
condition: Option<Expression>,
@ -137,21 +139,25 @@ impl InnerForLoop {
}
/// Gets the initialization node.
#[inline]
fn init(&self) -> Option<&ForLoopInitializer> {
self.init.as_ref()
}
/// Gets the loop condition node.
#[inline]
fn condition(&self) -> Option<&Expression> {
self.condition.as_ref()
}
/// Gets the final expression node.
#[inline]
fn final_expr(&self) -> Option<&Expression> {
self.final_expr.as_ref()
}
/// Gets the body of the for loop.
#[inline]
fn body(&self) -> &Statement {
&self.body
}
@ -213,18 +219,21 @@ impl ToInternedString for ForLoopInitializer {
}
impl From<Expression> for ForLoopInitializer {
#[inline]
fn from(expr: Expression) -> Self {
ForLoopInitializer::Expression(expr)
}
}
impl From<LexicalDeclaration> for ForLoopInitializer {
#[inline]
fn from(list: LexicalDeclaration) -> Self {
ForLoopInitializer::Lexical(list)
}
}
impl From<VarDeclaration> for ForLoopInitializer {
#[inline]
fn from(list: VarDeclaration) -> Self {
ForLoopInitializer::Var(list)
}

32
boa_engine/src/syntax/ast/statement/iteration/for_of_loop.rs

@ -3,7 +3,7 @@ use crate::syntax::ast::{
statement::{iteration::IterableLoopInitializer, Statement},
ContainsSymbol,
};
use boa_interner::{Interner, ToInternedString};
use boa_interner::{Interner, ToIndentedString, ToInternedString};
#[cfg(feature = "deser")]
use serde::{Deserialize, Serialize};
@ -19,6 +19,7 @@ pub struct ForOfLoop {
impl ForOfLoop {
/// Creates a new "for of" loop AST node.
#[inline]
pub fn new(
init: IterableLoopInitializer,
iterable: Expression,
@ -33,33 +34,30 @@ impl ForOfLoop {
}
}
/// Gets the initializer of the for...of loop.
#[inline]
pub fn init(&self) -> &IterableLoopInitializer {
&self.init
}
/// Gets the iterable expression of the for...of loop.
#[inline]
pub fn iterable(&self) -> &Expression {
&self.iterable
}
/// Gets the body to execute in the for...of loop.
#[inline]
pub fn body(&self) -> &Statement {
&self.body
}
/// Returns true if this "for...of" loop is an "for await...of" loop.
#[inline]
pub(crate) fn r#await(&self) -> bool {
self.r#await
}
/// Converts the "for of" loop to a string with the given indentation.
pub(crate) 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)
)
}
#[inline]
pub(crate) fn contains_arguments(&self) -> bool {
self.init.contains_arguments()
@ -73,13 +71,19 @@ impl ForOfLoop {
}
}
impl ToInternedString for ForOfLoop {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
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)
}

40
boa_engine/src/syntax/ast/statement/iteration/while_loop.rs

@ -1,5 +1,6 @@
use crate::syntax::ast::{expression::Expression, statement::Statement, ContainsSymbol};
use boa_interner::{Interner, ToInternedString};
use boa_interner::{Interner, ToIndentedString, ToInternedString};
/// The `while` statement creates a loop that executes a specified statement as long as the
/// test condition evaluates to `true`.
///
@ -19,14 +20,8 @@ pub struct WhileLoop {
}
impl WhileLoop {
pub fn condition(&self) -> &Expression {
&self.condition
}
pub fn body(&self) -> &Statement {
&self.body
}
/// Creates a `WhileLoop` AST node.
#[inline]
pub fn new(condition: Expression, body: Statement) -> Self {
Self {
condition,
@ -34,15 +29,19 @@ impl WhileLoop {
}
}
/// Converts the while loop to a string with the given indentation.
pub(crate) 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)
)
/// Gets the condition of the while loop.
#[inline]
pub fn condition(&self) -> &Expression {
&self.condition
}
/// Gets the body of the while loop.
#[inline]
pub fn body(&self) -> &Statement {
&self.body
}
#[inline]
pub(crate) fn contains_arguments(&self) -> bool {
self.condition.contains_arguments() || self.body.contains_arguments()
}
@ -53,13 +52,18 @@ impl WhileLoop {
}
}
impl ToInternedString for WhileLoop {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
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)
}

6
boa_engine/src/syntax/ast/statement/labelled.rs

@ -1,8 +1,6 @@
use boa_interner::{Interner, Sym, ToInternedString};
use crate::syntax::ast::{function::Function, ContainsSymbol};
use super::Statement;
use crate::syntax::ast::{function::Function, ContainsSymbol};
use boa_interner::{Interner, Sym, ToIndentedString, ToInternedString};
/// The set of AST nodes that can be preceded by a label, as defined by the [spec].
///

46
boa_engine/src/syntax/ast/statement/mod.rs

@ -22,7 +22,7 @@ pub use self::{
throw::Throw,
};
use boa_interner::{Interner, ToInternedString};
use boa_interner::{Interner, ToIndentedString, ToInternedString};
use rustc_hash::FxHashSet;
use tap::Tap;
@ -98,27 +98,6 @@ pub enum Statement {
}
impl Statement {
/// Creates a string of the value of the node with the given indentation. For example, an
/// indent level of 2 would produce this:
///
/// ```js
/// function hello() {
/// console.log("hello");
/// }
/// hello();
/// a = 2;
/// ```
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
let mut buf = match *self {
Self::Block(_) => String::new(),
_ => " ".repeat(indentation),
};
buf.push_str(&self.to_no_indent_string(interner, indentation));
buf
}
/// Implements the display formatting with indentation.
///
/// This will not prefix the value with any indentation. If you want to prefix this with proper
@ -302,8 +281,25 @@ impl Statement {
}
}
impl ToInternedString for Statement {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
impl ToIndentedString for Statement {
/// Creates a string of the value of the node with the given indentation. For example, an
/// indent level of 2 would produce this:
///
/// ```js
/// function hello() {
/// console.log("hello");
/// }
/// hello();
/// a = 2;
/// ```
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
let mut buf = match *self {
Self::Block(_) => String::new(),
_ => " ".repeat(indentation),
};
buf.push_str(&self.to_no_indent_string(interner, indentation));
buf
}
}

45
boa_engine/src/syntax/ast/statement/switch/mod.rs

@ -1,7 +1,7 @@
//! Switch node.
//!
use crate::syntax::ast::{expression::Expression, statement::Statement, StatementList};
use boa_interner::{Interner, ToInternedString};
use boa_interner::{Interner, ToIndentedString, ToInternedString};
use super::ContainsSymbol;
@ -17,16 +17,19 @@ pub struct Case {
impl Case {
/// Creates a `Case` AST node.
#[inline]
pub fn new(condition: Expression, body: StatementList) -> Self {
Self { condition, body }
}
/// Gets the condition of the case.
#[inline]
pub fn condition(&self) -> &Expression {
&self.condition
}
/// Gets the statement listin the body of the case.
#[inline]
pub fn body(&self) -> &StatementList {
&self.body
}
@ -73,6 +76,7 @@ pub struct Switch {
impl Switch {
/// Creates a `Switch` AST node.
#[inline]
pub fn new(val: Expression, cases: Box<[Case]>, default: Option<StatementList>) -> Self {
Self {
val,
@ -82,22 +86,38 @@ impl Switch {
}
/// Gets the value to switch.
#[inline]
pub fn val(&self) -> &Expression {
&self.val
}
/// Gets the list of cases for the switch statement.
#[inline]
pub fn cases(&self) -> &[Case] {
&self.cases
}
/// Gets the default statement list, if any.
#[inline]
pub fn default(&self) -> Option<&StatementList> {
self.default.as_ref()
}
/// Implements the display formatting with indentation.
pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
#[inline]
pub(crate) fn contains_arguments(&self) -> bool {
self.val.contains_arguments()
|| self.cases.iter().any(Case::contains_arguments)
|| matches!(self.default, Some(ref stmts) if stmts.contains_arguments())
}
#[inline]
pub(crate) fn contains(&self, symbol: ContainsSymbol) -> bool {
self.val.contains(symbol) || self.cases.iter().any(|case| case.contains(symbol))
}
}
impl ToIndentedString for Switch {
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
let indent = " ".repeat(indentation);
let mut buf = format!("switch ({}) {{\n", self.val().to_interned_string(interner));
for e in self.cases().iter() {
@ -119,27 +139,10 @@ impl Switch {
buf
}
#[inline]
pub(crate) fn contains_arguments(&self) -> bool {
self.val.contains_arguments()
|| self.cases.iter().any(Case::contains_arguments)
|| matches!(self.default, Some(ref stmts) if stmts.contains_arguments())
}
#[inline]
pub(crate) fn contains(&self, symbol: ContainsSymbol) -> bool {
self.val.contains(symbol) || self.cases.iter().any(|case| case.contains(symbol))
}
}
impl ToInternedString for Switch {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
}
}
impl From<Switch> for Statement {
#[inline]
fn from(switch: Switch) -> Self {
Self::Switch(switch)
}

39
boa_engine/src/syntax/ast/statement/try/mod.rs

@ -3,7 +3,7 @@ use crate::syntax::ast::{
statement::{Block, Statement},
statement_list::StatementListItem,
};
use boa_interner::{Interner, ToInternedString};
use boa_interner::{Interner, ToIndentedString, ToInternedString};
use super::ContainsSymbol;
@ -33,6 +33,7 @@ pub struct Try {
impl Try {
/// Creates a new `Try` AST node.
#[inline]
pub(in crate::syntax) fn new(
block: Block,
catch: Option<Catch>,
@ -51,16 +52,19 @@ impl Try {
}
/// Gets the `try` block.
#[inline]
pub fn block(&self) -> &Block {
&self.block
}
/// Gets the `catch` block, if any.
#[inline]
pub fn catch(&self) -> Option<&Catch> {
self.catch.as_ref()
}
/// Gets the `finally` block, if any.
#[inline]
pub fn finally(&self) -> Option<&Block> {
self.finally.as_ref().map(Finally::block)
}
@ -78,9 +82,10 @@ impl Try {
|| matches!(self.catch, Some(ref catch) if catch.contains(symbol))
|| matches!(self.finally, Some(ref finally) if finally.contains(symbol))
}
}
/// Implements the display formatting with indentation.
pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
impl ToIndentedString for Try {
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
let mut buf = format!(
"{}try {}",
" ".repeat(indentation),
@ -98,13 +103,8 @@ impl Try {
}
}
impl ToInternedString for Try {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
}
}
impl From<Try> for Statement {
#[inline]
fn from(try_catch: Try) -> Self {
Self::Try(try_catch)
}
@ -120,16 +120,19 @@ pub struct Catch {
impl Catch {
/// Creates a new catch block.
#[inline]
pub(in crate::syntax) fn new(parameter: Option<Binding>, block: Block) -> Self {
Self { parameter, block }
}
/// Gets the parameter of the catch block.
#[inline]
pub fn parameter(&self) -> Option<&Binding> {
self.parameter.as_ref()
}
/// Retrieves the catch execution block.
#[inline]
pub fn block(&self) -> &Block {
&self.block
}
@ -151,9 +154,10 @@ impl Catch {
.iter()
.any(|stmt| stmt.contains(symbol))
}
}
/// Implements the display formatting with indentation.
pub(super) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
impl ToIndentedString for Catch {
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
let mut buf = " catch".to_owned();
if let Some(ref param) = self.parameter {
buf.push_str(&format!("({})", param.to_interned_string(interner)));
@ -167,12 +171,6 @@ impl Catch {
}
}
impl ToInternedString for Catch {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
}
}
/// Finally block.
#[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq)]
@ -182,6 +180,7 @@ pub struct Finally {
impl Finally {
/// Gets the finally block.
#[inline]
pub fn block(&self) -> &Block {
&self.block
}
@ -203,9 +202,10 @@ impl Finally {
.iter()
.any(|stmt| stmt.contains(symbol))
}
}
/// Implements the display formatting with indentation.
pub(super) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
impl ToIndentedString for Finally {
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
format!(
" finally {}",
self.block.to_indented_string(interner, indentation)
@ -214,6 +214,7 @@ impl Finally {
}
impl From<Block> for Finally {
#[inline]
fn from(block: Block) -> Self {
Self { block }
}

118
boa_engine/src/syntax/ast/statement_list/mod.rs

@ -1,13 +1,10 @@
//! Statement list node.
use std::cmp::Ordering;
use super::{declaration::Binding, Declaration};
use crate::syntax::ast::{expression::Identifier, statement::Statement, ContainsSymbol};
use boa_interner::{Interner, ToInternedString};
use boa_interner::{Interner, ToIndentedString};
use rustc_hash::FxHashSet;
use super::{declaration::Binding, Declaration};
use std::cmp::Ordering;
#[cfg(test)]
mod tests;
@ -33,21 +30,45 @@ impl StatementListItem {
(_, _) => Ordering::Equal,
}
}
}
impl From<Statement> for StatementListItem {
fn from(stmt: Statement) -> Self {
StatementListItem::Statement(stmt)
#[inline]
pub(crate) fn var_declared_names(&self, vars: &mut FxHashSet<Identifier>) {
match self {
StatementListItem::Statement(stmt) => stmt.var_declared_names(vars),
StatementListItem::Declaration(_) => {}
}
}
}
impl From<Declaration> for StatementListItem {
fn from(decl: Declaration) -> Self {
StatementListItem::Declaration(decl)
/// Returns true if the node contains a identifier reference named 'arguments'.
///
/// More information:
/// - [ECMAScript specification][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-static-semantics-containsarguments
#[inline]
pub(crate) fn contains_arguments(&self) -> bool {
match self {
StatementListItem::Statement(stmt) => stmt.contains_arguments(),
StatementListItem::Declaration(decl) => decl.contains_arguments(),
}
}
/// Returns `true` if the node contains the given token.
///
/// More information:
/// - [ECMAScript specification][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-static-semantics-contains
#[inline]
pub(crate) fn contains(&self, symbol: ContainsSymbol) -> bool {
match self {
StatementListItem::Statement(stmt) => stmt.contains(symbol),
StatementListItem::Declaration(decl) => decl.contains(symbol),
}
}
}
impl StatementListItem {
impl ToIndentedString for StatementListItem {
/// Creates a string of the value of the node with the given indentation. For example, an
/// indent level of 2 would produce this:
///
@ -72,40 +93,19 @@ impl StatementListItem {
buf
}
}
pub(crate) fn var_declared_names(&self, vars: &mut FxHashSet<Identifier>) {
match self {
StatementListItem::Statement(stmt) => stmt.var_declared_names(vars),
StatementListItem::Declaration(_) => {}
}
}
/// Returns true if the node contains a identifier reference named 'arguments'.
///
/// More information:
/// - [ECMAScript specification][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-static-semantics-containsarguments
impl From<Statement> for StatementListItem {
#[inline]
pub(crate) fn contains_arguments(&self) -> bool {
match self {
StatementListItem::Statement(stmt) => stmt.contains_arguments(),
StatementListItem::Declaration(decl) => decl.contains_arguments(),
}
fn from(stmt: Statement) -> Self {
StatementListItem::Statement(stmt)
}
}
/// Returns `true` if the node contains the given token.
///
/// More information:
/// - [ECMAScript specification][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-static-semantics-contains
impl From<Declaration> for StatementListItem {
#[inline]
pub(crate) fn contains(&self, symbol: ContainsSymbol) -> bool {
match self {
StatementListItem::Statement(stmt) => stmt.contains(symbol),
StatementListItem::Declaration(decl) => decl.contains(symbol),
}
fn from(decl: Declaration) -> Self {
StatementListItem::Declaration(decl)
}
}
@ -141,19 +141,7 @@ impl StatementList {
self.strict = strict;
}
/// Implements the display formatting with indentation.
pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
let mut buf = String::new();
// Print statements
for item in self.statements.iter() {
// We rely on the node to add the correct indent.
buf.push_str(&item.to_indented_string(interner, indentation));
buf.push('\n');
}
buf
}
#[inline]
pub(crate) fn var_declared_names(&self, vars: &mut FxHashSet<Identifier>) {
for stmt in &*self.statements {
stmt.var_declared_names(vars);
@ -250,6 +238,7 @@ impl StatementList {
}
impl From<Box<[StatementListItem]>> for StatementList {
#[inline]
fn from(stm: Box<[StatementListItem]>) -> Self {
Self {
statements: stm,
@ -259,6 +248,7 @@ impl From<Box<[StatementListItem]>> for StatementList {
}
impl From<Vec<StatementListItem>> for StatementList {
#[inline]
fn from(stm: Vec<StatementListItem>) -> Self {
Self {
statements: stm.into(),
@ -267,8 +257,16 @@ impl From<Vec<StatementListItem>> for StatementList {
}
}
impl ToInternedString for StatementList {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
impl ToIndentedString for StatementList {
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
let mut buf = String::new();
// Print statements
for item in self.statements.iter() {
// We rely on the node to add the correct indent.
buf.push_str(&item.to_indented_string(interner, indentation));
buf.push('\n');
}
buf
}
}

3
boa_engine/src/syntax/parser/expression/tests.rs

@ -148,8 +148,7 @@ fn check_numeric_operations() {
ArithmeticOp::Div.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(),
))
.into()]
))]
.into(),
)))
.into()],

12
boa_interner/src/lib.rs

@ -409,6 +409,12 @@ impl Interner {
}
}
/// Implements the display formatting with indentation.
pub trait ToIndentedString {
/// Converts the element to a string using an interner, with the given indentation.
fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String;
}
/// Converts a given element to a string using an interner.
pub trait ToInternedString {
/// Converts a given element to a string using an interner.
@ -417,9 +423,9 @@ pub trait ToInternedString {
impl<T> ToInternedString for T
where
T: std::fmt::Display,
T: ToIndentedString,
{
fn to_interned_string(&self, _interner: &Interner) -> String {
self.to_string()
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
}
}

Loading…
Cancel
Save