Browse Source

Merge Const/Let/Var DeclList into DeclarationList (#1181)

pull/1208/head
0x7D2B 4 years ago committed by GitHub
parent
commit
ea8d9a2458
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 142
      boa/src/syntax/ast/node/declaration/const_decl_list/mod.rs
  2. 139
      boa/src/syntax/ast/node/declaration/let_decl_list/mod.rs
  3. 228
      boa/src/syntax/ast/node/declaration/mod.rs
  4. 147
      boa/src/syntax/ast/node/declaration/var_decl_list/mod.rs
  5. 16
      boa/src/syntax/ast/node/mod.rs
  6. 82
      boa/src/syntax/parser/expression/primary/async_function_expression/tests.rs
  7. 73
      boa/src/syntax/parser/expression/primary/function_expression/tests.rs
  8. 81
      boa/src/syntax/parser/expression/primary/object_initializer/tests.rs
  9. 264
      boa/src/syntax/parser/function/tests.rs
  10. 31
      boa/src/syntax/parser/statement/block/tests.rs
  11. 15
      boa/src/syntax/parser/statement/declaration/lexical.rs
  12. 103
      boa/src/syntax/parser/statement/declaration/tests.rs
  13. 26
      boa/src/syntax/parser/statement/iteration/tests.rs
  14. 16
      boa/src/syntax/parser/statement/switch/tests.rs
  15. 33
      boa/src/syntax/parser/statement/try_stm/tests.rs
  16. 12
      boa/src/syntax/parser/statement/variable/mod.rs
  17. 109
      boa/src/syntax/parser/tests.rs

142
boa/src/syntax/ast/node/declaration/const_decl_list/mod.rs

@ -1,142 +0,0 @@
use crate::{
environment::lexical_environment::VariableScope,
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::{join_nodes, Identifier, Node},
Context, Result, Value,
};
use std::fmt;
#[cfg(feature = "deser")]
use serde::{Deserialize, Serialize};
/// The `const` statements are block-scoped, much like variables defined using the `let`
/// keyword.
///
/// This declaration creates a constant whose scope can be either global or local to the block
/// in which it is declared. Global constants do not become properties of the window object,
/// unlike var variables.
///
/// An initializer for a constant is required. You must specify its value in the same statement
/// in which it's declared. (This makes sense, given that it can't be changed later.)
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-let-and-const-declarations
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
/// [identifier]: https://developer.mozilla.org/en-US/docs/Glossary/identifier
/// [expression]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Expressions
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct ConstDeclList {
#[cfg_attr(feature = "deser", serde(flatten))]
list: Box<[ConstDecl]>,
}
impl Executable for ConstDeclList {
fn run(&self, context: &mut Context) -> Result<Value> {
for decl in self.as_ref() {
let val = if let Some(init) = decl.init() {
init.run(context)?
} else {
return context.throw_syntax_error("missing = in const declaration");
};
context
.realm_mut()
.environment
.create_immutable_binding(decl.name().to_owned(), false, VariableScope::Block)
.map_err(|e| e.to_error(context))?;
context
.realm_mut()
.environment
.initialize_binding(decl.name(), val)
.map_err(|e| e.to_error(context))?;
}
Ok(Value::undefined())
}
}
impl<T> From<T> for ConstDeclList
where
T: Into<Box<[ConstDecl]>>,
{
fn from(list: T) -> Self {
Self { list: list.into() }
}
}
impl From<ConstDecl> for ConstDeclList {
fn from(decl: ConstDecl) -> Self {
Self {
list: Box::new([decl]),
}
}
}
impl AsRef<[ConstDecl]> for ConstDeclList {
fn as_ref(&self) -> &[ConstDecl] {
&self.list
}
}
impl fmt::Display for ConstDeclList {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if !self.list.is_empty() {
write!(f, "const ")?;
join_nodes(f, &self.list)
} else {
Ok(())
}
}
}
impl From<ConstDeclList> for Node {
fn from(list: ConstDeclList) -> Self {
Self::ConstDeclList(list)
}
}
/// Individual constant declaration.
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct ConstDecl {
name: Identifier,
init: Option<Node>,
}
impl fmt::Display for ConstDecl {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.name, f)?;
if let Some(ref init) = self.init {
write!(f, " = {}", init)?;
}
Ok(())
}
}
impl ConstDecl {
/// Creates a new variable declaration.
pub(in crate::syntax) fn new<N, I>(name: N, init: Option<I>) -> Self
where
N: Into<Identifier>,
I: Into<Node>,
{
Self {
name: name.into(),
init: init.map(|n| n.into()),
}
}
/// Gets the name of the variable.
pub fn name(&self) -> &str {
self.name.as_ref()
}
/// Gets the initialization node for the variable, if any.
pub fn init(&self) -> &Option<Node> {
&self.init
}
}

139
boa/src/syntax/ast/node/declaration/let_decl_list/mod.rs

@ -1,139 +0,0 @@
use crate::{
environment::lexical_environment::VariableScope,
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::{join_nodes, Identifier, Node},
Context, Result, Value,
};
use std::fmt;
#[cfg(feature = "deser")]
use serde::{Deserialize, Serialize};
/// The `let` statement declares a block scope local variable, optionally initializing it to a
/// value.
///
///
/// `let` allows you to declare variables that are limited to a scope of a block statement, or
/// expression on which it is used, unlike the `var` keyword, which defines a variable
/// globally, or locally to an entire function regardless of block scope.
///
/// Just like const the `let` does not create properties of the window object when declared
/// globally (in the top-most scope).
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-let-and-const-declarations
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct LetDeclList {
#[cfg_attr(feature = "deser", serde(flatten))]
list: Box<[LetDecl]>,
}
impl Executable for LetDeclList {
fn run(&self, context: &mut Context) -> Result<Value> {
for var in self.as_ref() {
let val = match var.init() {
Some(v) => v.run(context)?,
None => Value::undefined(),
};
context
.realm_mut()
.environment
.create_mutable_binding(var.name().to_owned(), false, VariableScope::Block)
.map_err(|e| e.to_error(context))?;
context
.realm_mut()
.environment
.initialize_binding(var.name(), val)
.map_err(|e| e.to_error(context))?;
}
Ok(Value::undefined())
}
}
impl<T> From<T> for LetDeclList
where
T: Into<Box<[LetDecl]>>,
{
fn from(list: T) -> Self {
Self { list: list.into() }
}
}
impl From<LetDecl> for LetDeclList {
fn from(decl: LetDecl) -> Self {
Self {
list: Box::new([decl]),
}
}
}
impl AsRef<[LetDecl]> for LetDeclList {
fn as_ref(&self) -> &[LetDecl] {
&self.list
}
}
impl fmt::Display for LetDeclList {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if !self.list.is_empty() {
write!(f, "let ")?;
join_nodes(f, &self.list)
} else {
Ok(())
}
}
}
impl From<LetDeclList> for Node {
fn from(list: LetDeclList) -> Self {
Self::LetDeclList(list)
}
}
/// Individual constant declaration.
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct LetDecl {
name: Identifier,
init: Option<Node>,
}
impl fmt::Display for LetDecl {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.name, f)?;
if let Some(ref init) = self.init {
write!(f, " = {}", init)?;
}
Ok(())
}
}
impl LetDecl {
/// Creates a new variable declaration.
pub(in crate::syntax) fn new<N, I>(name: N, init: I) -> Self
where
N: Into<Identifier>,
I: Into<Option<Node>>,
{
Self {
name: name.into(),
init: init.into(),
}
}
/// Gets the name of the variable.
pub fn name(&self) -> &str {
self.name.as_ref()
}
/// Gets the initialization node for the variable, if any.
pub fn init(&self) -> Option<&Node> {
self.init.as_ref()
}
}

228
boa/src/syntax/ast/node/declaration/mod.rs

@ -1,24 +1,232 @@
//! Declaration nodes
use crate::{
environment::lexical_environment::VariableScope,
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::{join_nodes, Identifier, Node},
Context, Result, Value,
};
use std::fmt;
#[cfg(feature = "deser")]
use serde::{Deserialize, Serialize};
pub mod arrow_function_decl;
pub mod async_function_decl;
pub mod async_function_expr;
pub mod const_decl_list;
pub mod function_decl;
pub mod function_expr;
pub mod let_decl_list;
pub mod var_decl_list;
pub use self::{
arrow_function_decl::ArrowFunctionDecl,
async_function_decl::AsyncFunctionDecl,
async_function_expr::AsyncFunctionExpr,
const_decl_list::{ConstDecl, ConstDeclList},
function_decl::FunctionDecl,
arrow_function_decl::ArrowFunctionDecl, async_function_decl::AsyncFunctionDecl,
async_function_expr::AsyncFunctionExpr, function_decl::FunctionDecl,
function_expr::FunctionExpr,
let_decl_list::{LetDecl, LetDeclList},
var_decl_list::{VarDecl, VarDeclList},
};
#[cfg(test)]
mod tests;
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub enum DeclarationList {
/// The `const` statements are block-scoped, much like variables defined using the `let`
/// keyword.
///
/// This declaration creates a constant whose scope can be either global or local to the block
/// in which it is declared. Global constants do not become properties of the window object,
/// unlike var variables.
///
/// An initializer for a constant is required. You must specify its value in the same statement
/// in which it's declared. (This makes sense, given that it can't be changed later.)
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-let-and-const-declarations
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
/// [identifier]: https://developer.mozilla.org/en-US/docs/Glossary/identifier
/// [expression]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Expressions
Const(Box<[Declaration]>),
/// The `let` statement declares a block scope local variable, optionally initializing it to a
/// value.
///
///
/// `let` allows you to declare variables that are limited to a scope of a block statement, or
/// expression on which it is used, unlike the `var` keyword, which defines a variable
/// globally, or locally to an entire function regardless of block scope.
///
/// Just like const the `let` does not create properties of the window object when declared
/// globally (in the top-most scope).
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-let-and-const-declarations
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
Let(Box<[Declaration]>),
/// The `var` statement declares a variable, optionally initializing it to a value.
///
/// var declarations, wherever they occur, are processed before any code is executed. This is
/// called hoisting, and is discussed further below.
///
/// The scope of a variable declared with var is its current execution context, which is either
/// the enclosing function or, for variables declared outside any function, global. If you
/// re-declare a JavaScript variable, it will not lose its value.
///
/// Assigning a value to an undeclared variable implicitly creates it as a global variable (it
/// becomes a property of the global object) when the assignment is executed.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#prod-VariableStatement
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
Var(Box<[Declaration]>),
}
impl Executable for DeclarationList {
fn run(&self, context: &mut Context) -> Result<Value> {
for decl in self.as_ref() {
use DeclarationList::*;
let val = match decl.init() {
None if self.is_const() => {
return context.throw_syntax_error("missing = in const declaration")
}
Some(init) => init.run(context)?,
None => Value::undefined(),
};
let environment = &mut context.realm_mut().environment;
if self.is_var() && environment.has_binding(decl.name()) {
if decl.init().is_some() {
environment
.set_mutable_binding(decl.name(), val, true)
.map_err(|e| e.to_error(context))?;
}
continue;
}
match &self {
Const(_) => environment
.create_immutable_binding(decl.name().to_owned(), false, VariableScope::Block)
.map_err(|e| e.to_error(context))?,
Let(_) => environment
.create_mutable_binding(decl.name().to_owned(), false, VariableScope::Block)
.map_err(|e| e.to_error(context))?,
Var(_) => environment
.create_mutable_binding(decl.name().to_owned(), false, VariableScope::Function)
.map_err(|e| e.to_error(context))?,
}
context
.realm_mut()
.environment
.initialize_binding(decl.name(), val)
.map_err(|e| e.to_error(context))?;
}
Ok(Value::undefined())
}
}
impl DeclarationList {
#[allow(dead_code)]
pub(in crate::syntax) fn is_let(&self) -> bool {
matches!(self, Self::Let(_))
}
pub(in crate::syntax) fn is_const(&self) -> bool {
matches!(self, Self::Const(_))
}
pub(in crate::syntax) fn is_var(&self) -> bool {
matches!(self, Self::Var(_))
}
}
impl AsRef<[Declaration]> for DeclarationList {
fn as_ref(&self) -> &[Declaration] {
use DeclarationList::*;
match self {
Var(list) | Const(list) | Let(list) => list,
}
}
}
impl fmt::Display for DeclarationList {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if !self.as_ref().is_empty() {
use DeclarationList::*;
match &self {
Let(_) => write!(f, "let ")?,
Const(_) => write!(f, "const ")?,
Var(_) => write!(f, "var ")?,
}
join_nodes(f, self.as_ref())
} else {
Ok(())
}
}
}
impl From<DeclarationList> for Node {
fn from(list: DeclarationList) -> Self {
use DeclarationList::*;
match &list {
Let(_) => Node::LetDeclList(list),
Const(_) => Node::ConstDeclList(list),
Var(_) => Node::VarDeclList(list),
}
}
}
impl Into<Box<[Declaration]>> for Declaration {
fn into(self) -> Box<[Declaration]> {
Box::new([self])
}
}
/// Individual declaration.
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct Declaration {
name: Identifier,
init: Option<Node>,
}
impl fmt::Display for Declaration {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.name, f)?;
if let Some(ref init) = self.init {
write!(f, " = {}", init)?;
}
Ok(())
}
}
impl Declaration {
/// Creates a new variable declaration.
pub(in crate::syntax) fn new<N, I>(name: N, init: I) -> Self
where
N: Into<Identifier>,
I: Into<Option<Node>>,
{
Self {
name: name.into(),
init: init.into(),
}
}
/// Gets the name of the variable.
pub fn name(&self) -> &str {
self.name.as_ref()
}
/// Gets the initialization node for the variable, if any.
pub fn init(&self) -> Option<&Node> {
self.init.as_ref()
}
}

147
boa/src/syntax/ast/node/declaration/var_decl_list/mod.rs

@ -1,147 +0,0 @@
use crate::{
environment::lexical_environment::VariableScope,
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::{join_nodes, Identifier, Node},
Context, Result, Value,
};
use std::fmt;
#[cfg(feature = "deser")]
use serde::{Deserialize, Serialize};
/// The `var` statement declares a variable, optionally initializing it to a value.
///
/// var declarations, wherever they occur, are processed before any code is executed. This is
/// called hoisting, and is discussed further below.
///
/// The scope of a variable declared with var is its current execution context, which is either
/// the enclosing function or, for variables declared outside any function, global. If you
/// re-declare a JavaScript variable, it will not lose its value.
///
/// Assigning a value to an undeclared variable implicitly creates it as a global variable (it
/// becomes a property of the global object) when the assignment is executed.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#prod-VariableStatement
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct VarDeclList {
#[cfg_attr(feature = "deser", serde(flatten))]
vars: Box<[VarDecl]>,
}
impl Executable for VarDeclList {
fn run(&self, context: &mut Context) -> Result<Value> {
for var in self.as_ref() {
let val = match var.init() {
Some(v) => v.run(context)?,
None => Value::undefined(),
};
let environment = &mut context.realm_mut().environment;
if environment.has_binding(var.name()) {
if var.init().is_some() {
environment
.set_mutable_binding(var.name(), val, true)
.map_err(|e| e.to_error(context))?;
}
} else {
environment
.create_mutable_binding(var.name().to_owned(), false, VariableScope::Function)
.map_err(|e| e.to_error(context))?;
let environment = &mut context.realm_mut().environment;
environment
.initialize_binding(var.name(), val)
.map_err(|e| e.to_error(context))?;
}
}
Ok(Value::undefined())
}
}
impl<T> From<T> for VarDeclList
where
T: Into<Box<[VarDecl]>>,
{
fn from(list: T) -> Self {
Self { vars: list.into() }
}
}
impl From<VarDecl> for VarDeclList {
fn from(decl: VarDecl) -> Self {
Self {
vars: Box::new([decl]),
}
}
}
impl AsRef<[VarDecl]> for VarDeclList {
fn as_ref(&self) -> &[VarDecl] {
&self.vars
}
}
impl fmt::Display for VarDeclList {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if !self.vars.is_empty() {
write!(f, "var ")?;
join_nodes(f, &self.vars)
} else {
Ok(())
}
}
}
impl From<VarDeclList> for Node {
fn from(list: VarDeclList) -> Self {
Self::VarDeclList(list)
}
}
/// Individual variable declaration.
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct VarDecl {
name: Identifier,
init: Option<Node>,
}
impl fmt::Display for VarDecl {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.name, f)?;
if let Some(ref init) = self.init {
write!(f, " = {}", init)?;
}
Ok(())
}
}
impl VarDecl {
/// Creates a new variable declaration.
pub(in crate::syntax) fn new<N, I>(name: N, init: I) -> Self
where
N: Into<Identifier>,
I: Into<Option<Node>>,
{
Self {
name: name.into(),
init: init.into(),
}
}
/// Gets the name of the variable.
pub fn name(&self) -> &str {
self.name.as_ref()
}
/// Gets the initialization node for the variable, if any.
pub fn init(&self) -> Option<&Node> {
self.init.as_ref()
}
}

16
boa/src/syntax/ast/node/mod.rs

@ -29,8 +29,8 @@ pub use self::{
call::Call,
conditional::{ConditionalOp, If},
declaration::{
ArrowFunctionDecl, AsyncFunctionDecl, AsyncFunctionExpr, ConstDecl, ConstDeclList,
FunctionDecl, FunctionExpr, LetDecl, LetDeclList, VarDecl, VarDeclList,
ArrowFunctionDecl, AsyncFunctionDecl, AsyncFunctionExpr, Declaration, DeclarationList,
FunctionDecl, FunctionExpr,
},
field::{GetConstField, GetField},
identifier::Identifier,
@ -108,8 +108,8 @@ pub enum Node {
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Literals
Const(Const),
/// A constant declaration list. [More information](./declaration/struct.ConstDeclList.html).
ConstDeclList(ConstDeclList),
/// A constant declaration list. [More information](./declaration/enum.DeclarationList.html#variant.Const).
ConstDeclList(DeclarationList),
/// A continue statement. [More information](./iteration/struct.Continue.html).
Continue(Continue),
@ -141,8 +141,8 @@ pub enum Node {
/// An 'if' statement. [More information](./conditional/struct.If.html).
If(If),
/// A `let` declaration list. [More information](./declaration/struct.LetDeclList.html).
LetDeclList(LetDeclList),
/// A `let` declaration list. [More information](./declaration/enum.DeclarationList.html#variant.Let).
LetDeclList(DeclarationList),
/// A local identifier node. [More information](./identifier/struct.Identifier.html).
Identifier(Identifier),
@ -191,8 +191,8 @@ pub enum Node {
/// Unary operation node. [More information](./operator/struct.UnaryOp.html)
UnaryOp(UnaryOp),
/// Array declaration node. [More information](./declaration/struct.VarDeclList.html).
VarDeclList(VarDeclList),
/// Array declaration node. [More information](./declaration/enum.DeclarationList.html#variant.Var).
VarDeclList(DeclarationList),
/// A 'while {...}' node. [More information](./iteration/struct.WhileLoop.html).
WhileLoop(WhileLoop),

82
boa/src/syntax/parser/expression/primary/async_function_expression/tests.rs

@ -1,6 +1,6 @@
use crate::syntax::{
ast::{
node::{AsyncFunctionExpr, ConstDecl, ConstDeclList, Return, StatementList},
node::{AsyncFunctionExpr, Declaration, DeclarationList, Return, StatementList},
Const,
},
parser::tests::check_parser,
@ -11,19 +11,24 @@ use crate::syntax::{
fn check_async_expression() {
check_parser(
"const add = async function() {
return 1;
return 1;
};
",
vec![ConstDeclList::from(vec![ConstDecl::new(
"add",
Some(
AsyncFunctionExpr::new::<Option<Box<str>>, _, StatementList>(
None,
[],
vec![Return::new::<_, _, Option<Box<str>>>(Const::from(1), None).into()].into(),
vec![DeclarationList::Const(
vec![Declaration::new(
"add",
Some(
AsyncFunctionExpr::new::<Option<Box<str>>, _, StatementList>(
None,
[],
vec![Return::new::<_, _, Option<Box<str>>>(Const::from(1), None).into()]
.into(),
)
.into(),
),
),
)])
)]
.into(),
)
.into()],
);
}
@ -33,33 +38,44 @@ fn check_nested_async_expression() {
check_parser(
"const a = async function() {
const b = async function() {
return 1;
return 1;
};
};
",
vec![ConstDeclList::from(vec![ConstDecl::new(
"a",
Some(
AsyncFunctionExpr::new::<Option<Box<str>>, _, StatementList>(
None,
[],
vec![ConstDeclList::from(vec![ConstDecl::new(
"b",
Some(
AsyncFunctionExpr::new::<Option<Box<str>>, _, StatementList>(
None,
[],
vec![Return::new::<_, _, Option<Box<str>>>(Const::from(1), None)
.into()]
.into(),
),
),
)])
.into()]
vec![DeclarationList::Const(
vec![Declaration::new(
"a",
Some(
AsyncFunctionExpr::new::<Option<Box<str>>, _, StatementList>(
None,
[],
vec![DeclarationList::Const(
vec![Declaration::new(
"b",
Some(
AsyncFunctionExpr::new::<Option<Box<str>>, _, StatementList>(
None,
[],
vec![Return::new::<_, _, Option<Box<str>>>(
Const::from(1),
None,
)
.into()]
.into(),
)
.into(),
),
)]
.into(),
)
.into()]
.into(),
)
.into(),
),
),
)])
)]
.into(),
)
.into()],
);
}

73
boa/src/syntax/parser/expression/primary/function_expression/tests.rs

@ -1,6 +1,6 @@
use crate::syntax::{
ast::{
node::{ConstDecl, ConstDeclList, FunctionExpr, Return, StatementList},
node::{Declaration, DeclarationList, FunctionExpr, Return, StatementList},
Const,
},
parser::tests::check_parser,
@ -14,14 +14,21 @@ fn check_function_expression() {
return 1;
};
",
vec![ConstDeclList::from(vec![ConstDecl::new(
"add",
Some(FunctionExpr::new::<Option<Box<str>>, _, StatementList>(
None,
[],
vec![Return::new::<_, _, Option<Box<str>>>(Const::from(1), None).into()].into(),
)),
)])
vec![DeclarationList::Const(
vec![Declaration::new(
"add",
Some(
FunctionExpr::new::<Option<Box<str>>, _, StatementList>(
None,
[],
vec![Return::new::<_, _, Option<Box<str>>>(Const::from(1), None).into()]
.into(),
)
.into(),
),
)]
.into(),
)
.into()],
);
}
@ -31,28 +38,44 @@ fn check_nested_function_expression() {
check_parser(
"const a = function() {
const b = function() {
return 1;
return 1;
};
};
",
vec![ConstDeclList::from(vec![ConstDecl::new(
"a",
Some(FunctionExpr::new::<Option<Box<str>>, _, StatementList>(
None,
[],
vec![ConstDeclList::from(vec![ConstDecl::new(
"b",
Some(FunctionExpr::new::<Option<Box<str>>, _, StatementList>(
vec![DeclarationList::Const(
vec![Declaration::new(
"a",
Some(
FunctionExpr::new::<Option<Box<str>>, _, StatementList>(
None,
[],
vec![Return::new::<_, _, Option<Box<str>>>(Const::from(1), None).into()]
vec![DeclarationList::Const(
vec![Declaration::new(
"b",
Some(
FunctionExpr::new::<Option<Box<str>>, _, StatementList>(
None,
[],
vec![Return::new::<_, _, Option<Box<str>>>(
Const::from(1),
None,
)
.into()]
.into(),
)
.into(),
),
)]
.into(),
)),
)])
.into()]
.into(),
)),
)])
)
.into()]
.into(),
)
.into(),
),
)]
.into(),
)
.into()],
);
}

81
boa/src/syntax/parser/expression/primary/object_initializer/tests.rs

@ -1,8 +1,8 @@
use crate::syntax::{
ast::{
node::{
ConstDecl, ConstDeclList, FormalParameter, FunctionExpr, MethodDefinitionKind, Object,
PropertyDefinition,
Declaration, DeclarationList, FormalParameter, FunctionExpr, MethodDefinitionKind,
Object, PropertyDefinition,
},
Const,
},
@ -23,10 +23,13 @@ fn check_object_literal() {
b: false,
};
",
vec![ConstDeclList::from(vec![ConstDecl::new(
"x",
Some(Object::from(object_properties)),
)])
vec![DeclarationList::Const(
vec![Declaration::new(
"x",
Some(Object::from(object_properties).into()),
)]
.into(),
)
.into()],
);
}
@ -49,10 +52,13 @@ fn check_object_short_function() {
b() {},
};
",
vec![ConstDeclList::from(vec![ConstDecl::new(
"x",
Some(Object::from(object_properties)),
)])
vec![DeclarationList::Const(
vec![Declaration::new(
"x",
Some(Object::from(object_properties).into()),
)]
.into(),
)
.into()],
);
}
@ -79,10 +85,13 @@ fn check_object_short_function_arguments() {
b(test) {}
};
",
vec![ConstDeclList::from(vec![ConstDecl::new(
"x",
Some(Object::from(object_properties)),
)])
vec![DeclarationList::Const(
vec![Declaration::new(
"x",
Some(Object::from(object_properties).into()),
)]
.into(),
)
.into()],
);
}
@ -104,10 +113,13 @@ fn check_object_getter() {
get b() {}
};
",
vec![ConstDeclList::from(vec![ConstDecl::new(
"x",
Some(Object::from(object_properties)),
)])
vec![DeclarationList::Const(
vec![Declaration::new(
"x",
Some(Object::from(object_properties).into()),
)]
.into(),
)
.into()],
);
}
@ -133,10 +145,13 @@ fn check_object_setter() {
set b(test) {}
};
",
vec![ConstDeclList::from(vec![ConstDecl::new(
"x",
Some(Object::from(object_properties)),
)])
vec![DeclarationList::Const(
vec![Declaration::new(
"x",
Some(Object::from(object_properties).into()),
)]
.into(),
)
.into()],
);
}
@ -154,10 +169,13 @@ fn check_object_short_function_get() {
get() {}
};
",
vec![ConstDeclList::from(vec![ConstDecl::new(
"x",
Some(Object::from(object_properties)),
)])
vec![DeclarationList::Const(
vec![Declaration::new(
"x",
Some(Object::from(object_properties).into()),
)]
.into(),
)
.into()],
);
}
@ -175,10 +193,13 @@ fn check_object_short_function_set() {
set() {}
};
",
vec![ConstDeclList::from(vec![ConstDecl::new(
"x",
Some(Object::from(object_properties)),
)])
vec![DeclarationList::Const(
vec![Declaration::new(
"x",
Some(Object::from(object_properties).into()),
)]
.into(),
)
.into()],
);
}

264
boa/src/syntax/parser/function/tests.rs

@ -1,7 +1,7 @@
use crate::syntax::{
ast::node::{
ArrowFunctionDecl, BinOp, FormalParameter, FunctionDecl, Identifier, LetDecl, LetDeclList,
Node, Return,
ArrowFunctionDecl, BinOp, Declaration, DeclarationList, FormalParameter, FunctionDecl,
Identifier, Node, Return,
},
ast::op::NumOp,
parser::tests::check_parser,
@ -182,20 +182,23 @@ fn check_arrow_empty_return_semicolon_insertion() {
fn check_arrow_assignment() {
check_parser(
"let foo = (a) => { return a };",
vec![LetDeclList::from(vec![LetDecl::new::<_, Option<Node>>(
Identifier::from("foo"),
Some(
ArrowFunctionDecl::new(
vec![FormalParameter::new("a", None, false)],
vec![Return::new::<Node, Option<_>, Option<_>>(
Some(Identifier::from("a").into()),
None,
vec![DeclarationList::Let(
vec![Declaration::new(
Identifier::from("foo"),
Some(
ArrowFunctionDecl::new(
vec![FormalParameter::new("a", None, false)],
vec![Return::new::<Node, Option<_>, Option<_>>(
Some(Identifier::from("a").into()),
None,
)
.into()],
)
.into()],
)
.into(),
),
)])
.into(),
),
)]
.into(),
)
.into()],
);
}
@ -204,20 +207,23 @@ fn check_arrow_assignment() {
fn check_arrow_assignment_nobrackets() {
check_parser(
"let foo = (a) => a;",
vec![LetDeclList::from(vec![LetDecl::new::<_, Option<Node>>(
Identifier::from("foo"),
Some(
ArrowFunctionDecl::new(
vec![FormalParameter::new("a", None, false)],
vec![Return::new::<Node, Option<_>, Option<_>>(
Some(Identifier::from("a").into()),
None,
vec![DeclarationList::Let(
vec![Declaration::new(
Identifier::from("foo"),
Some(
ArrowFunctionDecl::new(
vec![FormalParameter::new("a", None, false)],
vec![Return::new::<Node, Option<_>, Option<_>>(
Some(Identifier::from("a").into()),
None,
)
.into()],
)
.into()],
)
.into(),
),
)])
.into(),
),
)]
.into(),
)
.into()],
);
}
@ -226,20 +232,23 @@ fn check_arrow_assignment_nobrackets() {
fn check_arrow_assignment_noparenthesis() {
check_parser(
"let foo = a => { return a };",
vec![LetDeclList::from(vec![LetDecl::new::<_, Option<Node>>(
Identifier::from("foo"),
Some(
ArrowFunctionDecl::new(
vec![FormalParameter::new("a", None, false)],
vec![Return::new::<Node, Option<_>, Option<_>>(
Some(Identifier::from("a").into()),
None,
vec![DeclarationList::Let(
vec![Declaration::new(
Identifier::from("foo"),
Some(
ArrowFunctionDecl::new(
vec![FormalParameter::new("a", None, false)],
vec![Return::new::<Node, Option<_>, Option<_>>(
Some(Identifier::from("a").into()),
None,
)
.into()],
)
.into()],
)
.into(),
),
)])
.into(),
),
)]
.into(),
)
.into()],
);
}
@ -248,20 +257,23 @@ fn check_arrow_assignment_noparenthesis() {
fn check_arrow_assignment_noparenthesis_nobrackets() {
check_parser(
"let foo = a => a;",
vec![LetDeclList::from(vec![LetDecl::new::<_, Option<Node>>(
Identifier::from("foo"),
Some(
ArrowFunctionDecl::new(
vec![FormalParameter::new("a", None, false)],
vec![Return::new::<Node, Option<_>, Option<_>>(
Some(Identifier::from("a").into()),
None,
vec![DeclarationList::Let(
vec![Declaration::new(
Identifier::from("foo"),
Some(
ArrowFunctionDecl::new(
vec![FormalParameter::new("a", None, false)],
vec![Return::new::<Node, Option<_>, Option<_>>(
Some(Identifier::from("a").into()),
None,
)
.into()],
)
.into()],
)
.into(),
),
)])
.into(),
),
)]
.into(),
)
.into()],
);
}
@ -270,23 +282,26 @@ fn check_arrow_assignment_noparenthesis_nobrackets() {
fn check_arrow_assignment_2arg() {
check_parser(
"let foo = (a, b) => { return a };",
vec![LetDeclList::from(vec![LetDecl::new::<_, Option<Node>>(
Identifier::from("foo"),
Some(
ArrowFunctionDecl::new(
vec![
FormalParameter::new("a", None, false),
FormalParameter::new("b", None, false),
],
vec![Return::new::<Node, Option<_>, Option<_>>(
Some(Identifier::from("a").into()),
None,
vec![DeclarationList::Let(
vec![Declaration::new(
Identifier::from("foo"),
Some(
ArrowFunctionDecl::new(
vec![
FormalParameter::new("a", None, false),
FormalParameter::new("b", None, false),
],
vec![Return::new::<Node, Option<_>, Option<_>>(
Some(Identifier::from("a").into()),
None,
)
.into()],
)
.into()],
)
.into(),
),
)])
.into(),
),
)]
.into(),
)
.into()],
);
}
@ -295,23 +310,26 @@ fn check_arrow_assignment_2arg() {
fn check_arrow_assignment_2arg_nobrackets() {
check_parser(
"let foo = (a, b) => a;",
vec![LetDeclList::from(vec![LetDecl::new::<_, Option<Node>>(
Identifier::from("foo"),
Some(
ArrowFunctionDecl::new(
vec![
FormalParameter::new("a", None, false),
FormalParameter::new("b", None, false),
],
vec![Return::new::<Node, Option<_>, Option<_>>(
Some(Identifier::from("a").into()),
None,
vec![DeclarationList::Let(
vec![Declaration::new(
Identifier::from("foo"),
Some(
ArrowFunctionDecl::new(
vec![
FormalParameter::new("a", None, false),
FormalParameter::new("b", None, false),
],
vec![Return::new::<Node, Option<_>, Option<_>>(
Some(Identifier::from("a").into()),
None,
)
.into()],
)
.into()],
)
.into(),
),
)])
.into(),
),
)]
.into(),
)
.into()],
);
}
@ -320,24 +338,27 @@ fn check_arrow_assignment_2arg_nobrackets() {
fn check_arrow_assignment_3arg() {
check_parser(
"let foo = (a, b, c) => { return a };",
vec![LetDeclList::from(vec![LetDecl::new::<_, Option<Node>>(
Identifier::from("foo"),
Some(
ArrowFunctionDecl::new(
vec![
FormalParameter::new("a", None, false),
FormalParameter::new("b", None, false),
FormalParameter::new("c", None, false),
],
vec![Return::new::<Node, Option<_>, Option<_>>(
Some(Identifier::from("a").into()),
None,
vec![DeclarationList::Let(
vec![Declaration::new(
Identifier::from("foo"),
Some(
ArrowFunctionDecl::new(
vec![
FormalParameter::new("a", None, false),
FormalParameter::new("b", None, false),
FormalParameter::new("c", None, false),
],
vec![Return::new::<Node, Option<_>, Option<_>>(
Some(Identifier::from("a").into()),
None,
)
.into()],
)
.into()],
)
.into(),
),
)])
.into(),
),
)]
.into(),
)
.into()],
);
}
@ -346,24 +367,27 @@ fn check_arrow_assignment_3arg() {
fn check_arrow_assignment_3arg_nobrackets() {
check_parser(
"let foo = (a, b, c) => a;",
vec![LetDeclList::from(vec![LetDecl::new::<_, Option<Node>>(
Identifier::from("foo"),
Some(
ArrowFunctionDecl::new(
vec![
FormalParameter::new("a", None, false),
FormalParameter::new("b", None, false),
FormalParameter::new("c", None, false),
],
vec![Return::new::<Node, Option<_>, Option<_>>(
Some(Identifier::from("a").into()),
None,
vec![DeclarationList::Let(
vec![Declaration::new(
Identifier::from("foo"),
Some(
ArrowFunctionDecl::new(
vec![
FormalParameter::new("a", None, false),
FormalParameter::new("b", None, false),
FormalParameter::new("c", None, false),
],
vec![Return::new::<Node, Option<_>, Option<_>>(
Some(Identifier::from("a").into()),
None,
)
.into()],
)
.into()],
)
.into(),
),
)])
.into(),
),
)]
.into(),
)
.into()],
);
}

31
boa/src/syntax/parser/statement/block/tests.rs

@ -3,8 +3,8 @@
use crate::syntax::{
ast::{
node::{
Assign, Block, Call, FunctionDecl, Identifier, Node, Return, UnaryOp, VarDecl,
VarDeclList,
Assign, Block, Call, Declaration, DeclarationList, FunctionDecl, Identifier, Node,
Return, UnaryOp,
},
op, Const,
},
@ -33,7 +33,8 @@ fn non_empty() {
a++;
}",
vec![
VarDeclList::from(vec![VarDecl::new("a", Some(Const::from(10).into()))]).into(),
DeclarationList::Var(vec![Declaration::new("a", Some(Const::from(10).into()))].into())
.into(),
UnaryOp::new(op::UnaryOp::IncrementPost, Identifier::from("a")).into(),
],
);
@ -54,10 +55,13 @@ fn non_empty() {
vec![Return::new(Const::from(10), None).into()],
)
.into(),
VarDeclList::from(vec![VarDecl::new(
"a",
Node::from(Call::new(Identifier::from("hello"), vec![])),
)])
DeclarationList::Var(
vec![Declaration::new(
"a",
Node::from(Call::new(Identifier::from("hello"), vec![])),
)]
.into(),
)
.into(),
UnaryOp::new(op::UnaryOp::IncrementPost, Identifier::from("a")).into(),
],
@ -80,10 +84,13 @@ fn hoisting() {
vec![Return::new(Const::from(10), None).into()],
)
.into(),
VarDeclList::from(vec![VarDecl::new(
"a",
Node::from(Call::new(Identifier::from("hello"), vec![])),
)])
DeclarationList::Var(
vec![Declaration::new(
"a",
Node::from(Call::new(Identifier::from("hello"), vec![])),
)]
.into(),
)
.into(),
UnaryOp::new(op::UnaryOp::IncrementPost, Identifier::from("a")).into(),
],
@ -99,7 +106,7 @@ fn hoisting() {
vec![
Assign::new(Identifier::from("a"), Const::from(10)).into(),
UnaryOp::new(op::UnaryOp::IncrementPost, Identifier::from("a")).into(),
VarDeclList::from(vec![VarDecl::new("a", None)]).into(),
DeclarationList::Var(vec![Declaration::new("a", None)].into()).into(),
],
);
}

15
boa/src/syntax/parser/statement/declaration/lexical.rs

@ -11,7 +11,10 @@ use crate::syntax::lexer::TokenKind;
use crate::{
syntax::{
ast::{
node::{ConstDecl, ConstDeclList, LetDecl, LetDeclList, Node},
node::{
declaration::{Declaration, DeclarationList},
Node,
},
Keyword, Punctuator,
},
parser::{
@ -158,7 +161,7 @@ where
if self.is_const {
if self.const_init_required {
if init.is_some() {
const_decls.push(ConstDecl::new(ident, init));
const_decls.push(Declaration::new(ident, init));
} else {
return Err(ParseError::expected(
vec![TokenKind::Punctuator(Punctuator::Assign)],
@ -167,10 +170,10 @@ where
));
}
} else {
const_decls.push(ConstDecl::new(ident, init))
const_decls.push(Declaration::new(ident, init))
}
} else {
let_decls.push(LetDecl::new(ident, init));
let_decls.push(Declaration::new(ident, init));
}
match cursor.peek_semicolon()? {
@ -201,9 +204,9 @@ where
}
if self.is_const {
Ok(ConstDeclList::from(const_decls).into())
Ok(DeclarationList::Const(const_decls.into()).into())
} else {
Ok(LetDeclList::from(let_decls).into())
Ok(DeclarationList::Let(let_decls.into()).into())
}
}
}

103
boa/src/syntax/parser/statement/declaration/tests.rs

@ -1,6 +1,6 @@
use crate::syntax::{
ast::{
node::{ConstDecl, ConstDeclList, LetDecl, LetDeclList, Node, VarDecl, VarDeclList},
node::{Declaration, DeclarationList, Node},
Const,
},
parser::tests::{check_invalid, check_parser},
@ -11,7 +11,10 @@ use crate::syntax::{
fn var_declaration() {
check_parser(
"var a = 5;",
vec![VarDeclList::from(vec![VarDecl::new("a", Some(Const::from(5).into()))]).into()],
vec![
DeclarationList::Var(vec![Declaration::new("a", Some(Const::from(5).into()))].into())
.into(),
],
);
}
@ -20,12 +23,18 @@ fn var_declaration() {
fn var_declaration_keywords() {
check_parser(
"var yield = 5;",
vec![VarDeclList::from(vec![VarDecl::new("yield", Some(Const::from(5).into()))]).into()],
vec![DeclarationList::Var(
vec![Declaration::new("yield", Some(Const::from(5).into()))].into(),
)
.into()],
);
check_parser(
"var await = 5;",
vec![VarDeclList::from(vec![VarDecl::new("await", Some(Const::from(5).into()))]).into()],
vec![DeclarationList::Var(
vec![Declaration::new("await", Some(Const::from(5).into()))].into(),
)
.into()],
);
}
@ -34,7 +43,10 @@ fn var_declaration_keywords() {
fn var_declaration_no_spaces() {
check_parser(
"var a=5;",
vec![VarDeclList::from(vec![VarDecl::new("a", Some(Const::from(5).into()))]).into()],
vec![
DeclarationList::Var(vec![Declaration::new("a", Some(Const::from(5).into()))].into())
.into(),
],
);
}
@ -43,7 +55,7 @@ fn var_declaration_no_spaces() {
fn empty_var_declaration() {
check_parser(
"var a;",
vec![VarDeclList::from(vec![VarDecl::new("a", None)]).into()],
vec![DeclarationList::Var(vec![Declaration::new("a", None)].into()).into()],
);
}
@ -52,11 +64,14 @@ fn empty_var_declaration() {
fn multiple_var_declaration() {
check_parser(
"var a = 5, b, c = 6;",
vec![VarDeclList::from(vec![
VarDecl::new("a", Some(Const::from(5).into())),
VarDecl::new("b", None),
VarDecl::new("c", Some(Const::from(6).into())),
])
vec![DeclarationList::Var(
vec![
Declaration::new("a", Some(Const::from(5).into())),
Declaration::new("b", None),
Declaration::new("c", Some(Const::from(6).into())),
]
.into(),
)
.into()],
);
}
@ -66,7 +81,10 @@ fn multiple_var_declaration() {
fn let_declaration() {
check_parser(
"let a = 5;",
vec![LetDeclList::from(vec![LetDecl::new("a", Node::from(Const::from(5)))]).into()],
vec![
DeclarationList::Let(vec![Declaration::new("a", Node::from(Const::from(5)))].into())
.into(),
],
);
}
@ -75,12 +93,18 @@ fn let_declaration() {
fn let_declaration_keywords() {
check_parser(
"let yield = 5;",
vec![LetDeclList::from(vec![LetDecl::new("yield", Node::from(Const::from(5)))]).into()],
vec![DeclarationList::Let(
vec![Declaration::new("yield", Node::from(Const::from(5)))].into(),
)
.into()],
);
check_parser(
"let await = 5;",
vec![LetDeclList::from(vec![LetDecl::new("await", Node::from(Const::from(5)))]).into()],
vec![DeclarationList::Let(
vec![Declaration::new("await", Node::from(Const::from(5)))].into(),
)
.into()],
);
}
@ -89,7 +113,10 @@ fn let_declaration_keywords() {
fn let_declaration_no_spaces() {
check_parser(
"let a=5;",
vec![LetDeclList::from(vec![LetDecl::new("a", Node::from(Const::from(5)))]).into()],
vec![
DeclarationList::Let(vec![Declaration::new("a", Node::from(Const::from(5)))].into())
.into(),
],
);
}
@ -98,7 +125,7 @@ fn let_declaration_no_spaces() {
fn empty_let_declaration() {
check_parser(
"let a;",
vec![LetDeclList::from(vec![LetDecl::new("a", None)]).into()],
vec![DeclarationList::Let(vec![Declaration::new("a", None)].into()).into()],
);
}
@ -107,11 +134,14 @@ fn empty_let_declaration() {
fn multiple_let_declaration() {
check_parser(
"let a = 5, b, c = 6;",
vec![LetDeclList::from(vec![
LetDecl::new("a", Node::from(Const::from(5))),
LetDecl::new("b", None),
LetDecl::new("c", Node::from(Const::from(6))),
])
vec![DeclarationList::Let(
vec![
Declaration::new("a", Node::from(Const::from(5))),
Declaration::new("b", None),
Declaration::new("c", Node::from(Const::from(6))),
]
.into(),
)
.into()],
);
}
@ -121,7 +151,10 @@ fn multiple_let_declaration() {
fn const_declaration() {
check_parser(
"const a = 5;",
vec![ConstDeclList::from(ConstDecl::new("a", Some(Const::from(5)))).into()],
vec![DeclarationList::Const(
vec![Declaration::new("a", Node::from(Const::from(5)))].into(),
)
.into()],
);
}
@ -130,12 +163,18 @@ fn const_declaration() {
fn const_declaration_keywords() {
check_parser(
"const yield = 5;",
vec![ConstDeclList::from(ConstDecl::new("yield", Some(Const::from(5)))).into()],
vec![DeclarationList::Const(
vec![Declaration::new("yield", Node::from(Const::from(5)))].into(),
)
.into()],
);
check_parser(
"const await = 5;",
vec![ConstDeclList::from(ConstDecl::new("await", Some(Const::from(5)))).into()],
vec![DeclarationList::Const(
vec![Declaration::new("await", Node::from(Const::from(5)))].into(),
)
.into()],
);
}
@ -144,7 +183,10 @@ fn const_declaration_keywords() {
fn const_declaration_no_spaces() {
check_parser(
"const a=5;",
vec![ConstDeclList::from(ConstDecl::new("a", Some(Const::from(5)))).into()],
vec![DeclarationList::Const(
vec![Declaration::new("a", Node::from(Const::from(5)))].into(),
)
.into()],
);
}
@ -159,10 +201,13 @@ fn empty_const_declaration() {
fn multiple_const_declaration() {
check_parser(
"const a = 5, c = 6;",
vec![ConstDeclList::from(vec![
ConstDecl::new("a", Some(Const::from(5))),
ConstDecl::new("c", Some(Const::from(6))),
])
vec![DeclarationList::Const(
vec![
Declaration::new("a", Node::from(Const::from(5))),
Declaration::new("c", Node::from(Const::from(6))),
]
.into(),
)
.into()],
);
}

26
boa/src/syntax/parser/statement/iteration/tests.rs

@ -1,8 +1,8 @@
use crate::syntax::{
ast::{
node::{
field::GetConstField, BinOp, Block, Break, Call, DoWhileLoop, Identifier, UnaryOp,
VarDecl, VarDeclList, WhileLoop,
field::GetConstField, BinOp, Block, Break, Call, Declaration, DeclarationList,
DoWhileLoop, Identifier, UnaryOp, WhileLoop,
},
op::{self, AssignOp, CompOp},
Const,
@ -37,7 +37,8 @@ fn check_do_while_semicolon_insertion() {
r#"var i = 0;
do {console.log("hello");} while(i++ < 10) console.log("end");"#,
vec![
VarDeclList::from(vec![VarDecl::new("i", Some(Const::from(0).into()))]).into(),
DeclarationList::Var(vec![Declaration::new("i", Some(Const::from(0).into()))].into())
.into(),
DoWhileLoop::new(
Block::from(vec![Call::new(
GetConstField::new(Identifier::from("console"), "log"),
@ -68,7 +69,8 @@ fn check_do_while_semicolon_insertion_no_space() {
r#"var i = 0;
do {console.log("hello");} while(i++ < 10)console.log("end");"#,
vec![
VarDeclList::from(vec![VarDecl::new("i", Some(Const::from(0).into()))]).into(),
DeclarationList::Var(vec![Declaration::new("i", Some(Const::from(0).into()))].into())
.into(),
DoWhileLoop::new(
Block::from(vec![Call::new(
GetConstField::new(Identifier::from("console"), "log"),
@ -97,14 +99,14 @@ fn while_spaces() {
check_parser(
r#"
while
while
(
true
)
break;
"#,
@ -118,14 +120,14 @@ fn do_while_spaces() {
check_parser(
r#"
do
do
{
break;
}
while (true)
"#,

16
boa/src/syntax/parser/statement/switch/tests.rs

@ -1,6 +1,9 @@
use crate::syntax::{
ast::{
node::{Break, Call, Case, GetConstField, Identifier, LetDecl, LetDeclList, Node, Switch},
node::{
Break, Call, Case, Declaration, DeclarationList, GetConstField, Identifier, Node,
Switch,
},
Const,
},
parser::tests::{check_invalid, check_parser},
@ -16,7 +19,7 @@ fn check_switch_no_closeblock() {
case 10:
a = 20;
break;
"#,
);
}
@ -30,7 +33,7 @@ fn check_switch_case_unclosed() {
switch (a) {
case 10:
a = 20;
"#,
);
}
@ -110,9 +113,9 @@ fn check_seperated_switch() {
let s = r#"
let a = 10;
switch
switch
(a)
(a)
{
@ -148,7 +151,8 @@ fn check_seperated_switch() {
check_parser(
s,
vec![
LetDeclList::from(vec![LetDecl::new("a", Node::from(Const::from(10)))]).into(),
DeclarationList::Let(vec![Declaration::new("a", Node::from(Const::from(10)))].into())
.into(),
Switch::new(
Identifier::from("a"),
vec![

33
boa/src/syntax/parser/statement/try_stm/tests.rs

@ -1,6 +1,6 @@
use crate::syntax::{
ast::{
node::{Block, Catch, Finally, Identifier, Try, VarDecl, VarDeclList},
node::{Block, Catch, Declaration, DeclarationList, Finally, Identifier, Try},
Const,
},
parser::tests::{check_invalid, check_parser},
@ -19,7 +19,10 @@ fn check_inline_with_var_decl_inside_try() {
check_parser(
"try { var x = 1; } catch(e) {}",
vec![Try::new(
vec![VarDeclList::from(vec![VarDecl::new("x", Some(Const::from(1).into()))]).into()],
vec![DeclarationList::Var(
vec![Declaration::new("x", Some(Const::from(1).into()))].into(),
)
.into()],
Some(Catch::new("e", vec![])),
None,
)
@ -32,12 +35,16 @@ fn check_inline_with_var_decl_inside_catch() {
check_parser(
"try { var x = 1; } catch(e) { var x = 1; }",
vec![Try::new(
vec![VarDeclList::from(vec![VarDecl::new("x", Some(Const::from(1).into()))]).into()],
vec![DeclarationList::Var(
vec![Declaration::new("x", Some(Const::from(1).into()))].into(),
)
.into()],
Some(Catch::new(
"e",
vec![
VarDeclList::from(vec![VarDecl::new("x", Some(Const::from(1).into()))]).into(),
],
vec![DeclarationList::Var(
vec![Declaration::new("x", Some(Const::from(1).into()))].into(),
)
.into()],
)),
None,
)
@ -73,10 +80,9 @@ fn check_inline_with_empty_try_var_decl_in_finally() {
vec![Try::new(
vec![],
None,
Some(Finally::from(vec![VarDeclList::from(vec![VarDecl::new(
"x",
Some(Const::from(1).into()),
)])
Some(Finally::from(vec![DeclarationList::Var(
vec![Declaration::new("x", Some(Const::from(1).into()))].into(),
)
.into()])),
)
.into()],
@ -91,9 +97,10 @@ fn check_inline_empty_try_paramless_catch() {
Block::from(vec![]),
Some(Catch::new::<_, Identifier, _>(
None,
vec![
VarDeclList::from(vec![VarDecl::new("x", Some(Const::from(1).into()))]).into(),
],
vec![DeclarationList::Var(
vec![Declaration::new("x", Some(Const::from(1).into()))].into(),
)
.into()],
)),
None,
)

12
boa/src/syntax/parser/statement/variable/mod.rs

@ -3,7 +3,7 @@
use crate::{
syntax::{
ast::{
node::{VarDecl, VarDeclList},
node::{Declaration, DeclarationList},
Keyword, Punctuator,
},
lexer::TokenKind,
@ -52,7 +52,7 @@ impl<R> TokenParser<R> for VariableStatement
where
R: Read,
{
type Output = VarDeclList;
type Output = DeclarationList;
fn parse(self, cursor: &mut Cursor<R>) -> Result<Self::Output, ParseError> {
let _timer = BoaProfiler::global().start_event("VariableStatement", "Parsing");
@ -106,7 +106,7 @@ impl<R> TokenParser<R> for VariableDeclarationList
where
R: Read,
{
type Output = VarDeclList;
type Output = DeclarationList;
fn parse(self, cursor: &mut Cursor<R>) -> Result<Self::Output, ParseError> {
let mut list = Vec::new();
@ -127,7 +127,7 @@ where
}
}
Ok(VarDeclList::from(list))
Ok(DeclarationList::Var(list.into()))
}
}
@ -164,7 +164,7 @@ impl<R> TokenParser<R> for VariableDeclaration
where
R: Read,
{
type Output = VarDecl;
type Output = Declaration;
fn parse(self, cursor: &mut Cursor<R>) -> Result<Self::Output, ParseError> {
// TODO: BindingPattern
@ -181,6 +181,6 @@ where
None
};
Ok(VarDecl::new(name, init))
Ok(Declaration::new(name, init))
}
}

109
boa/src/syntax/parser/tests.rs

@ -3,9 +3,8 @@
use super::Parser;
use crate::syntax::ast::{
node::{
field::GetConstField, ArrowFunctionDecl, Assign, BinOp, Call, FormalParameter,
FunctionDecl, Identifier, If, LetDecl, LetDeclList, New, Node, Return, StatementList,
UnaryOp, VarDecl, VarDeclList,
field::GetConstField, ArrowFunctionDecl, Assign, BinOp, Call, Declaration, DeclarationList,
FormalParameter, FunctionDecl, Identifier, If, New, Node, Return, StatementList, UnaryOp,
},
op::{self, CompOp, LogOp, NumOp},
Const,
@ -74,10 +73,13 @@ fn hoisting() {
vec![Return::new(Const::from(10), None).into()],
)
.into(),
VarDeclList::from(vec![VarDecl::new(
"a",
Node::from(Call::new(Identifier::from("hello"), vec![])),
)])
DeclarationList::Var(
vec![Declaration::new(
"a",
Node::from(Call::new(Identifier::from("hello"), vec![])),
)]
.into(),
)
.into(),
UnaryOp::new(op::UnaryOp::IncrementPost, Identifier::from("a")).into(),
],
@ -92,7 +94,7 @@ fn hoisting() {
vec![
Assign::new(Identifier::from("a"), Const::from(10)).into(),
UnaryOp::new(op::UnaryOp::IncrementPost, Identifier::from("a")).into(),
VarDeclList::from(vec![VarDecl::new("a", None)]).into(),
DeclarationList::Var(vec![Declaration::new("a", None)].into()).into(),
],
);
}
@ -141,15 +143,21 @@ fn comment_semi_colon_insertion() {
check_parser(
s,
vec![
LetDeclList::from(vec![LetDecl::new::<&str, Option<Node>>(
"a",
Some(Const::Int(10).into()),
)])
DeclarationList::Let(
vec![Declaration::new::<&str, Option<Node>>(
"a",
Some(Const::Int(10).into()),
)]
.into(),
)
.into(),
LetDeclList::from(vec![LetDecl::new::<&str, Option<Node>>(
"b",
Some(Const::Int(20).into()),
)])
DeclarationList::Let(
vec![Declaration::new::<&str, Option<Node>>(
"b",
Some(Const::Int(20).into()),
)]
.into(),
)
.into(),
],
);
@ -167,15 +175,21 @@ fn multiline_comment_semi_colon_insertion() {
check_parser(
s,
vec![
LetDeclList::from(vec![LetDecl::new::<&str, Option<Node>>(
"a",
Some(Const::Int(10).into()),
)])
DeclarationList::Let(
vec![Declaration::new::<&str, Option<Node>>(
"a",
Some(Const::Int(10).into()),
)]
.into(),
)
.into(),
LetDeclList::from(vec![LetDecl::new::<&str, Option<Node>>(
"b",
Some(Const::Int(20).into()),
)])
DeclarationList::Let(
vec![Declaration::new::<&str, Option<Node>>(
"b",
Some(Const::Int(20).into()),
)]
.into(),
)
.into(),
],
);
@ -190,15 +204,21 @@ fn multiline_comment_no_lineterminator() {
check_parser(
s,
vec![
LetDeclList::from(vec![LetDecl::new::<&str, Option<Node>>(
"a",
Some(Const::Int(10).into()),
)])
DeclarationList::Let(
vec![Declaration::new::<&str, Option<Node>>(
"a",
Some(Const::Int(10).into()),
)]
.into(),
)
.into(),
LetDeclList::from(vec![LetDecl::new::<&str, Option<Node>>(
"b",
Some(Const::Int(20).into()),
)])
DeclarationList::Let(
vec![Declaration::new::<&str, Option<Node>>(
"b",
Some(Const::Int(20).into()),
)]
.into(),
)
.into(),
],
);
@ -216,10 +236,13 @@ fn assignment_line_terminator() {
check_parser(
s,
vec![
LetDeclList::from(vec![LetDecl::new::<&str, Option<Node>>(
"a",
Some(Const::Int(3).into()),
)])
DeclarationList::Let(
vec![Declaration::new::<&str, Option<Node>>(
"a",
Some(Const::Int(3).into()),
)]
.into(),
)
.into(),
Assign::new(Identifier::from("a"), Const::from(5)).into(),
],
@ -241,10 +264,13 @@ fn assignment_multiline_terminator() {
check_parser(
s,
vec![
LetDeclList::from(vec![LetDecl::new::<&str, Option<Node>>(
"a",
Some(Const::Int(3).into()),
)])
DeclarationList::Let(
vec![Declaration::new::<&str, Option<Node>>(
"a",
Some(Const::Int(3).into()),
)]
.into(),
)
.into(),
Assign::new(Identifier::from("a"), Const::from(5)).into(),
],
@ -302,7 +328,8 @@ fn empty_statement() {
",
vec![
Node::Empty,
VarDeclList::from(vec![VarDecl::new("a", Node::from(Const::from(10)))]).into(),
DeclarationList::Var(vec![Declaration::new("a", Node::from(Const::from(10)))].into())
.into(),
Node::If(If::new::<_, _, Node, _>(
Identifier::from("a"),
Node::Empty,

Loading…
Cancel
Save