From 100e16deec90463b20ad8ce004b4cbb61aa77b4a Mon Sep 17 00:00:00 2001 From: jedel1043 Date: Mon, 24 Oct 2022 14:00:17 -0500 Subject: [PATCH] Document the AST --- boa_engine/src/bytecompiler/mod.rs | 24 +- boa_engine/src/lib.rs | 4 +- boa_engine/src/syntax/ast/declaration/mod.rs | 19 ++ .../src/syntax/ast/declaration/variable.rs | 25 +- .../src/syntax/ast/expression/access.rs | 59 ++--- .../src/syntax/ast/expression/identifier.rs | 7 +- .../syntax/ast/expression/literal/template.rs | 9 + boa_engine/src/syntax/ast/expression/mod.rs | 16 +- .../ast/expression/operator/assign/mod.rs | 119 +++++---- .../ast/expression/operator/binary/mod.rs | 30 ++- .../ast/expression/operator/conditional.rs | 9 +- .../src/syntax/ast/expression/operator/mod.rs | 18 +- .../ast/expression/operator/unary/mod.rs | 27 +- .../src/syntax/ast/expression/spread.rs | 13 +- .../syntax/ast/expression/tagged_template.rs | 7 + boa_engine/src/syntax/ast/expression/yield.rs | 2 + .../src/syntax/ast/function/arrow_function.rs | 10 +- .../src/syntax/ast/function/async_function.rs | 13 +- .../syntax/ast/function/async_generator.rs | 9 +- boa_engine/src/syntax/ast/function/class.rs | 27 +- .../src/syntax/ast/function/generator.rs | 13 +- boa_engine/src/syntax/ast/function/mod.rs | 34 ++- .../src/syntax/ast/function/parameters.rs | 10 +- boa_engine/src/syntax/ast/keyword.rs | 46 ++-- boa_engine/src/syntax/ast/mod.rs | 24 +- boa_engine/src/syntax/ast/pattern.rs | 246 +++++++++--------- boa_engine/src/syntax/ast/position.rs | 16 +- boa_engine/src/syntax/ast/property.rs | 6 +- boa_engine/src/syntax/ast/punctuator.rs | 13 +- .../ast/statement/iteration/continue.rs | 1 + .../ast/statement/iteration/for_in_loop.rs | 7 + .../ast/statement/iteration/for_loop.rs | 14 +- .../ast/statement/iteration/for_of_loop.rs | 17 +- .../src/syntax/ast/statement/iteration/mod.rs | 35 ++- .../src/syntax/ast/statement/labelled.rs | 4 +- boa_engine/src/syntax/ast/statement/mod.rs | 22 +- boa_engine/src/syntax/ast/statement/return.rs | 4 +- .../src/syntax/ast/statement/switch/mod.rs | 8 + boa_engine/src/syntax/ast/statement/throw.rs | 1 + .../src/syntax/ast/statement/try/mod.rs | 4 +- .../src/syntax/ast/statement_list/mod.rs | 8 + boa_engine/src/syntax/parser/error.rs | 7 +- .../expression/assignment/conditional.rs | 2 +- .../expression/assignment/exponentiation.rs | 2 +- .../parser/expression/assignment/mod.rs | 2 +- .../src/syntax/parser/expression/mod.rs | 2 +- .../async_function_expression/tests.rs | 3 +- .../async_generator_expression/tests.rs | 3 +- .../primary/function_expression/tests.rs | 3 +- .../primary/generator_expression/tests.rs | 3 +- .../syntax/parser/expression/primary/mod.rs | 8 +- .../src/syntax/parser/expression/tests.rs | 4 +- .../src/syntax/parser/expression/unary.rs | 2 +- .../src/syntax/parser/expression/update.rs | 2 +- .../src/syntax/parser/function/tests.rs | 5 +- .../syntax/parser/statement/block/tests.rs | 5 +- .../parser/statement/break_stm/tests.rs | 3 +- .../parser/statement/continue_stm/tests.rs | 3 +- .../src/syntax/parser/statement/if_stm/mod.rs | 3 +- .../statement/iteration/for_statement.rs | 2 +- .../parser/statement/iteration/tests.rs | 6 +- boa_engine/src/syntax/parser/statement/mod.rs | 91 +++---- .../syntax/parser/statement/try_stm/tests.rs | 13 +- boa_engine/src/syntax/parser/tests.rs | 9 +- 64 files changed, 675 insertions(+), 488 deletions(-) diff --git a/boa_engine/src/bytecompiler/mod.rs b/boa_engine/src/bytecompiler/mod.rs index 560c6beb0f3..5399f80cfcf 100644 --- a/boa_engine/src/bytecompiler/mod.rs +++ b/boa_engine/src/bytecompiler/mod.rs @@ -8,9 +8,9 @@ use crate::{ access::{PrivatePropertyAccess, PropertyAccess, PropertyAccessField}, literal::{self, TemplateElement}, operator::{ - assign::{op::AssignOp, AssignTarget}, - binary::op::{ArithmeticOp, BinaryOp, BitwiseOp, LogicalOp, RelationalOp}, - unary::op::UnaryOp, + assign::{AssignOp, AssignTarget}, + binary::{ArithmeticOp, BinaryOp, BitwiseOp, LogicalOp, RelationalOp}, + unary::UnaryOp, }, Call, Identifier, New, }, @@ -18,10 +18,10 @@ use crate::{ ArrowFunction, AsyncFunction, AsyncGenerator, Class, ClassElement, FormalParameterList, Function, Generator, }, - pattern::{Pattern, PatternArrayElement, PatternObjectElement}, + pattern::{ArrayPatternElement, ObjectPatternElement, Pattern}, property::{MethodDefinition, PropertyDefinition, PropertyName}, statement::{ - iteration::{for_loop::ForLoopInitializer, IterableLoopInitializer}, + iteration::{ForLoopInitializer, IterableLoopInitializer}, Block, DoWhileLoop, ForInLoop, ForLoop, ForOfLoop, LabelledItem, WhileLoop, }, Declaration, Expression, Statement, StatementList, StatementListItem, @@ -1221,7 +1221,7 @@ impl<'b> ByteCompiler<'b> { use_expr, )?, Expression::Conditional(op) => { - self.compile_expr(op.cond(), true)?; + self.compile_expr(op.condition(), true)?; let jelse = self.jump_if_false(); self.compile_expr(op.if_true(), true)?; let exit = self.jump(); @@ -2453,14 +2453,12 @@ impl<'b> ByteCompiler<'b> { let rest_exits = pattern.has_rest(); for binding in pattern.bindings() { - use PatternObjectElement::{ - AssignmentPropertyAccess, AssignmentRestPropertyAccess, Empty, Pattern, + use ObjectPatternElement::{ + AssignmentPropertyAccess, AssignmentRestPropertyAccess, Pattern, RestProperty, SingleName, }; match binding { - // ObjectBindingPattern : { } - Empty => {} // SingleNameBinding : BindingIdentifier Initializer[opt] SingleName { ident, @@ -2605,14 +2603,12 @@ impl<'b> ByteCompiler<'b> { self.emit_opcode(Opcode::InitIterator); for binding in pattern.bindings().iter() { - use PatternArrayElement::{ - Elision, Empty, Pattern, PatternRest, PropertyAccess, PropertyAccessRest, + use ArrayPatternElement::{ + Elision, Pattern, PatternRest, PropertyAccess, PropertyAccessRest, SingleName, SingleNameRest, }; match binding { - // ArrayBindingPattern : [ ] - Empty => {} // ArrayBindingPattern : [ Elision ] Elision => { self.emit_opcode(Opcode::IteratorNext); diff --git a/boa_engine/src/lib.rs b/boa_engine/src/lib.rs index 684047661e5..a43985f72c6 100644 --- a/boa_engine/src/lib.rs +++ b/boa_engine/src/lib.rs @@ -40,7 +40,7 @@ unused_lifetimes, unreachable_pub, trivial_numeric_casts, - // rustdoc, + rustdoc::broken_intra_doc_links, missing_debug_implementations, missing_copy_implementations, deprecated_in_future, @@ -49,7 +49,7 @@ rust_2018_compatibility, rust_2018_idioms, future_incompatible, - nonstandard_style, + nonstandard_style )] #![allow( clippy::missing_inline_in_public_items, diff --git a/boa_engine/src/syntax/ast/declaration/mod.rs b/boa_engine/src/syntax/ast/declaration/mod.rs index 9dabe8ec5d4..1b9fb43b19a 100644 --- a/boa_engine/src/syntax/ast/declaration/mod.rs +++ b/boa_engine/src/syntax/ast/declaration/mod.rs @@ -1,3 +1,19 @@ +//! The [`Declaration`] Parse Node, as defined by the [spec]. +//! +//! Javascript declarations include: +//! - [Lexical][lex] declarations (`let`, `const`). +//! - [Function][fun] declarations (`function`, `async function`). +//! - [Class][class] declarations. +//! +//! See [*Difference between statements and declarations*][diff] for an explanation on why `Declaration`s +//! and `Statement`s are distinct nodes. +//! +//! [spec]: https://tc39.es/ecma262/#prod-Declaration +//! [lex]: https://tc39.es/ecma262/#prod-LexicalDeclaration +//! [fun]: https://tc39.es/ecma262/#prod-HoistableDeclaration +//! [class]: https://tc39.es/ecma262/#prod-ClassDeclaration +//! [diff]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements#difference_between_statements_and_declarations + use super::{ expression::Identifier, function::{AsyncFunction, AsyncGenerator, Class, Function, Generator}, @@ -10,6 +26,9 @@ mod variable; pub use variable::*; +/// The `Declaration` Parse Node. +/// +/// See the [module level documentation][self] for more information. #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub enum Declaration { diff --git a/boa_engine/src/syntax/ast/declaration/variable.rs b/boa_engine/src/syntax/ast/declaration/variable.rs index 6a4eeb03a8b..10fe4d4ad53 100644 --- a/boa_engine/src/syntax/ast/declaration/variable.rs +++ b/boa_engine/src/syntax/ast/declaration/variable.rs @@ -12,18 +12,34 @@ use boa_interner::{Interner, ToInternedString}; use super::Declaration; -/// A [`var`][var] declaration list, also called [`VariableDeclarationList`][vardecl] -/// in the spec. +/// A [`var`][var] statement, also called [`VariableStatement`][varstmt] in the spec. /// /// 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. /// +/// Although a bit confusing, `VarDeclaration`s are not considered [`Declaration`]s by the spec. +/// This is partly because it has very different semantics from `let` and `const` declarations, but +/// also because a `var` statement can be labelled just like any other [`Statement`]: +/// +/// ```javascript +/// label: var a = 5; +/// a; +/// ``` +/// +/// returns `5` as the value of the statement list, while: +/// +/// ```javascript +/// label: let a = 5; +/// a; +/// ``` +/// throws a `SyntaxError`. +/// /// `var` declarations, wherever they occur, are processed before any code is executed. This is /// called [hoisting]. /// /// [var]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var -/// [vardecl]: https://tc39.es/ecma262/#prod-VariableStatement +/// [varstmt]: https://tc39.es/ecma262/#prod-VariableStatement /// [hoisting]: https://developer.mozilla.org/en-US/docs/Glossary/Hoisting #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] @@ -155,6 +171,7 @@ impl ToInternedString for VariableList { } } +/// The error returned by the [`VariableList::try_from`] function. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct TryFromVariableListError(()); @@ -280,7 +297,9 @@ impl Variable { #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub enum Binding { + /// A single identifier binding. Identifier(Identifier), + /// A pattern binding. Pattern(Pattern), } diff --git a/boa_engine/src/syntax/ast/expression/access.rs b/boa_engine/src/syntax/ast/expression/access.rs index 9ce723a450d..46569bee0ee 100644 --- a/boa_engine/src/syntax/ast/expression/access.rs +++ b/boa_engine/src/syntax/ast/expression/access.rs @@ -1,10 +1,27 @@ +//! Property access expressions, as defined by the [spec]. +//! +//! [Property access expressions][access] provide two ways to access properties of an object: *dot notation* +//! and *bracket notation*. +//! - *Dot notation* is mostly used when the name of the property is static, and a valid Javascript +//! identifier e.g. `obj.prop`, `arr.$val`. +//! - *Bracket notation* is used when the name of the property is either variable, not a valid +//! identifier or a symbol e.g. `arr[var]`, `arr[5]`, `arr[Symbol.iterator]`. +//! +//! [spec]: https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-property-accessors +//! [access]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors + use crate::syntax::ast::{expression::Expression, ContainsSymbol}; use boa_interner::{Interner, Sym, ToInternedString}; +/// A property access field. +/// +/// See the [module level documentation][self] for more information. #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub enum PropertyAccessField { + /// A constant property field, such as `x.prop`. Const(Sym), + /// An expression property field, such as `x["val"]`. Expr(Box), } @@ -38,28 +55,9 @@ impl From for PropertyAccessField { } } -/// This property accessor provides access to an object's properties by using the -/// [bracket notation][mdn]. -/// -/// In the `object[property_name]` syntax, the `property_name` is just a string or -/// [Symbol][symbol]. So, it can be any string, including '1foo', '!bar!', or even ' ' (a -/// space). -/// -/// One can think of an object as an associative array (a.k.a. map, dictionary, hash, lookup -/// table). The keys in this array are the names of the object's properties. -/// -/// It's typical when speaking of an object's properties to make a distinction between -/// properties and methods. However, the property/method distinction is little more than a -/// convention. A method is simply a property that can be called (for example, if it has a -/// reference to a Function instance as its value). -/// -/// More information: -/// - [ECMAScript reference][spec] -/// - [MDN documentation][mdn] +/// A property access expression. /// -/// [spec]: https://tc39.es/ecma262/#sec-property-accessors -/// [symbol]: https://developer.mozilla.org/en-US/docs/Glossary/Symbol -/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_accessors#Bracket_notation +/// See the [module level documentation][self] for more information. #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub struct PropertyAccess { @@ -68,11 +66,13 @@ pub struct PropertyAccess { } impl PropertyAccess { + /// Gets the target object of the property access. #[inline] pub fn target(&self) -> &Expression { &self.target } + /// Gets the accessed field of the target object. #[inline] pub fn field(&self) -> &PropertyAccessField { &self.field @@ -121,14 +121,12 @@ impl From for Expression { } } -/// This property accessor provides access to an class object's private fields. +/// An access expression to a class object's [private fields][mdn]. /// -/// This expression can be described as ` MemberExpression.PrivateIdentifier` -/// Example: `this.#a` +/// Private property accesses differ slightly from plain property accesses, since the accessed +/// property must be prefixed by `#`, and the bracket notation is not allowed e.g. `this.#a`. /// -/// More information: -/// - [ECMAScript reference][spec] -/// - [MDN documentation][mdn] +/// This expression corresponds to the [`MemberExpression.PrivateIdentifier`][spec] production. /// /// [spec]: https://tc39.es/ecma262/#prod-MemberExpression /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields @@ -190,11 +188,10 @@ impl From for Expression { } } -/// The `super` keyword is used to access fields on an object's parent. +/// A property access of an object's parent, as defined by the [spec]. /// -/// More information: -/// - [ECMAScript reference][spec] -/// - [MDN documentation][mdn] +/// A `SuperPropertyAccess` is much like a regular [`PropertyAccess`], but where its `target` object +/// is not a regular object, but a reference to the parent object of the current object ([`super`][mdn]). /// /// [spec]: https://tc39.es/ecma262/#prod-SuperProperty /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super diff --git a/boa_engine/src/syntax/ast/expression/identifier.rs b/boa_engine/src/syntax/ast/expression/identifier.rs index 2efdeac9f24..716af6a9628 100644 --- a/boa_engine/src/syntax/ast/expression/identifier.rs +++ b/boa_engine/src/syntax/ast/expression/identifier.rs @@ -24,8 +24,11 @@ use super::Expression; /// /// [spec]: https://tc39.es/ecma262/#prod-Identifier /// [mdn]: https://developer.mozilla.org/en-US/docs/Glossary/Identifier -#[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "deser", serde(transparent))] +#[cfg_attr( + feature = "deser", + derive(serde::Serialize, serde::Deserialize), + serde(transparent) +)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[repr(transparent)] pub struct Identifier { diff --git a/boa_engine/src/syntax/ast/expression/literal/template.rs b/boa_engine/src/syntax/ast/expression/literal/template.rs index 57a0d0e0c5a..1f9dfac6489 100644 --- a/boa_engine/src/syntax/ast/expression/literal/template.rs +++ b/boa_engine/src/syntax/ast/expression/literal/template.rs @@ -30,14 +30,23 @@ impl From for Expression { } } +/// An element found within a [`TemplateLiteral`]. +/// +/// The [spec] doesn't define an element akin to `TemplateElement`. However, the AST defines this +/// node as the equivalent of the components found in a template literal. +/// +/// [spec]: https://tc39.es/ecma262/#sec-template-literals #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub enum TemplateElement { + /// A simple string. String(Sym), + /// An expression that is evaluated and replaced by its string representation. Expr(Expression), } impl TemplateLiteral { + /// Creates a new `TemplateLiteral` from a list of [`TemplateElement`]s. #[inline] pub fn new(elements: Box<[TemplateElement]>) -> Self { Self { elements } diff --git a/boa_engine/src/syntax/ast/expression/mod.rs b/boa_engine/src/syntax/ast/expression/mod.rs index 7f9fd2300a1..ec664d638b9 100644 --- a/boa_engine/src/syntax/ast/expression/mod.rs +++ b/boa_engine/src/syntax/ast/expression/mod.rs @@ -1,9 +1,20 @@ +//! The [`Expression`] Parse Node, as defined by the [spec]. +//! +//! Javascript expressions include: +//! - [Primary][primary] expressions (`this`, function expressions, literals). +//! - [Left hand side][lhs] expressions (accessors, `new` operator, `super`). +//! - [operator] expressions. +//! +//! [spec]: https://tc39.es/ecma262/#prod-Expression +//! [primary]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#primary_expressions +//! [lhs]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#left-hand-side_expressions + use boa_interner::{Interner, Sym, ToIndentedString, ToInternedString}; use self::{ access::{PrivatePropertyAccess, PropertyAccess, SuperPropertyAccess}, literal::{ArrayLiteral, Literal, ObjectLiteral, TemplateLiteral}, - operator::{conditional::Conditional, Assign, Binary, Unary}, + operator::{Assign, Binary, Conditional, Unary}, }; use super::{ @@ -32,6 +43,9 @@ pub mod access; pub mod literal; pub mod operator; +/// The `Expression` Parse Node. +/// +/// See the [module level documentation][self] for more information. #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Debug, Clone, PartialEq)] pub enum Expression { diff --git a/boa_engine/src/syntax/ast/expression/operator/assign/mod.rs b/boa_engine/src/syntax/ast/expression/operator/assign/mod.rs index 7a12785654c..e2d4776dc84 100644 --- a/boa_engine/src/syntax/ast/expression/operator/assign/mod.rs +++ b/boa_engine/src/syntax/ast/expression/operator/assign/mod.rs @@ -1,3 +1,19 @@ +//! Assignment expression nodes, as defined by the [spec]. +//! +//! An [assignment operator][mdn] assigns a value to its left operand based on the value of its right +//! operand. Almost any [`LeftHandSideExpression`][lhs] Parse Node can be the target of a simple +//! assignment expression (`=`). However, the compound assignment operations such as `%=` or `??=` +//! only allow ["simple"][simple] left hand side expressions as an assignment target. +//! +//! [spec]: https://tc39.es/ecma262/#prod-AssignmentExpression +//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators +//! [lhs]: https://tc39.es/ecma262/#prod-LeftHandSideExpression +//! [simple]: https://tc39.es/ecma262/#sec-static-semantics-assignmenttargettype + +mod op; + +pub use op::*; + use boa_interner::{Interner, Sym, ToInternedString}; use crate::syntax::{ @@ -9,38 +25,27 @@ use crate::syntax::{ Expression, }, pattern::{ - Pattern, PatternArray, PatternArrayElement, PatternObject, PatternObjectElement, + ArrayPattern, ArrayPatternElement, ObjectPattern, ObjectPatternElement, Pattern, }, property::{PropertyDefinition, PropertyName}, ContainsSymbol, }, parser::RESERVED_IDENTIFIERS_STRICT, }; - -pub mod op; - -/// An assignment operator assigns a value to its left operand based on the value of its right -/// operand. +/// An assignment operator expression. /// -/// Assignment operator (`=`), assigns the value of its right operand to its left operand. -/// -/// More information: -/// - [ECMAScript reference][spec] -/// - [MDN documentation][mdn] -/// -/// [spec]: https://tc39.es/ecma262/#prod-AssignmentExpression -/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators +/// See the [module level documentation][self] for more information. #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub struct Assign { - op: op::AssignOp, + op: AssignOp, lhs: Box, rhs: Box, } impl Assign { /// Creates an `Assign` AST Expression. - pub(in crate::syntax) fn new(op: op::AssignOp, lhs: AssignTarget, rhs: Expression) -> Self { + pub(in crate::syntax) fn new(op: AssignOp, lhs: AssignTarget, rhs: Expression) -> Self { Self { op, lhs: Box::new(lhs), @@ -50,7 +55,7 @@ impl Assign { /// Gets the operator of the assignment operation. #[inline] - pub fn op(&self) -> op::AssignOp { + pub fn op(&self) -> AssignOp { self.op } @@ -108,24 +113,27 @@ impl From for Expression { } } -/// This type represents all valid left-had-side expressions of an assignment operator. +/// The valid left-hand-side expressions of an assignment operator. Also called +/// [`LeftHandSideExpression`][spec] in the spec. /// -/// More information: -/// - [ECMAScript reference][spec] -/// -/// [spec]: https://tc39.es/ecma262/#prod-AssignmentExpression +/// [spec]: hhttps://tc39.es/ecma262/#prod-LeftHandSideExpression #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub enum AssignTarget { + /// A simple identifier, such as `a`. Identifier(Identifier), + /// A property access, such as `a.prop`. Property(PropertyAccess), + /// A private property access, such as `a.#priv`. PrivateProperty(PrivatePropertyAccess), + /// A `super` property access, such as `super.prop`. SuperProperty(SuperPropertyAccess), + /// A pattern assignment target, such as `{a, b, ...c}`. Pattern(Pattern), } impl AssignTarget { - /// Converts the left-hand-side Expression of an assignment expression into it's an [`AssignTarget`]. + /// Converts the left-hand-side Expression of an assignment expression into an [`AssignTarget`]. /// Returns `None` if the given Expression is an invalid left-hand-side for a assignment expression. pub(crate) fn from_expression( expression: &Expression, @@ -176,7 +184,7 @@ impl From for AssignTarget { pub(crate) fn object_decl_to_declaration_pattern( object: &ObjectLiteral, strict: bool, -) -> Option { +) -> Option { let mut bindings = Vec::new(); let mut excluded_keys = Vec::new(); for (i, property) in object.properties().iter().enumerate() { @@ -192,7 +200,7 @@ pub(crate) fn object_decl_to_declaration_pattern( } excluded_keys.push(*ident); - bindings.push(PatternObjectElement::SingleName { + bindings.push(ObjectPatternElement::SingleName { ident: *ident, name: PropertyName::Literal(ident.sym()), default_init: None, @@ -208,14 +216,14 @@ pub(crate) fn object_decl_to_declaration_pattern( } excluded_keys.push(*ident); - bindings.push(PatternObjectElement::SingleName { + bindings.push(ObjectPatternElement::SingleName { ident: *ident, name: PropertyName::Literal(*name), default_init: None, }); } (PropertyName::Literal(name), Expression::Identifier(ident)) => { - bindings.push(PatternObjectElement::SingleName { + bindings.push(ObjectPatternElement::SingleName { ident: *ident, name: PropertyName::Literal(*name), default_init: None, @@ -223,7 +231,7 @@ pub(crate) fn object_decl_to_declaration_pattern( } (PropertyName::Literal(name), Expression::ObjectLiteral(object)) => { let pattern = object_decl_to_declaration_pattern(object, strict)?.into(); - bindings.push(PatternObjectElement::Pattern { + bindings.push(ObjectPatternElement::Pattern { name: PropertyName::Literal(*name), pattern, default_init: None, @@ -231,7 +239,7 @@ pub(crate) fn object_decl_to_declaration_pattern( } (PropertyName::Literal(name), Expression::ArrayLiteral(array)) => { let pattern = array_decl_to_declaration_pattern(array, strict)?.into(); - bindings.push(PatternObjectElement::Pattern { + bindings.push(ObjectPatternElement::Pattern { name: PropertyName::Literal(*name), pattern, default_init: None, @@ -248,13 +256,13 @@ pub(crate) fn object_decl_to_declaration_pattern( return None; } excluded_keys.push(*ident); - bindings.push(PatternObjectElement::SingleName { + bindings.push(ObjectPatternElement::SingleName { ident: *ident, name: PropertyName::Literal(name), default_init: Some(assign.rhs().clone()), }); } else { - bindings.push(PatternObjectElement::SingleName { + bindings.push(ObjectPatternElement::SingleName { ident: *ident, name: PropertyName::Literal(name), default_init: Some(assign.rhs().clone()), @@ -265,14 +273,14 @@ pub(crate) fn object_decl_to_declaration_pattern( } } AssignTarget::Pattern(pattern) => { - bindings.push(PatternObjectElement::Pattern { + bindings.push(ObjectPatternElement::Pattern { name: name.clone(), pattern: pattern.clone(), default_init: Some(assign.rhs().clone()), }); } AssignTarget::Property(field) => { - bindings.push(PatternObjectElement::AssignmentPropertyAccess { + bindings.push(ObjectPatternElement::AssignmentPropertyAccess { name: name.clone(), access: field.clone(), default_init: Some(assign.rhs().clone()), @@ -283,14 +291,14 @@ pub(crate) fn object_decl_to_declaration_pattern( } }, (_, Expression::PropertyAccess(field)) => { - bindings.push(PatternObjectElement::AssignmentPropertyAccess { + bindings.push(ObjectPatternElement::AssignmentPropertyAccess { name: name.clone(), access: field.clone(), default_init: None, }); } (PropertyName::Computed(name), Expression::Identifier(ident)) => { - bindings.push(PatternObjectElement::SingleName { + bindings.push(ObjectPatternElement::SingleName { ident: *ident, name: PropertyName::Computed(name.clone()), default_init: None, @@ -301,13 +309,13 @@ pub(crate) fn object_decl_to_declaration_pattern( PropertyDefinition::SpreadObject(spread) => { match spread { Expression::Identifier(ident) => { - bindings.push(PatternObjectElement::RestProperty { + bindings.push(ObjectPatternElement::RestProperty { ident: *ident, excluded_keys: excluded_keys.clone(), }); } Expression::PropertyAccess(access) => { - bindings.push(PatternObjectElement::AssignmentRestPropertyAccess { + bindings.push(ObjectPatternElement::AssignmentRestPropertyAccess { access: access.clone(), excluded_keys: excluded_keys.clone(), }); @@ -324,7 +332,7 @@ pub(crate) fn object_decl_to_declaration_pattern( return None; } - bindings.push(PatternObjectElement::SingleName { + bindings.push(ObjectPatternElement::SingleName { ident: *ident, name: PropertyName::Literal(ident.sym()), default_init: Some(expr.clone()), @@ -332,17 +340,14 @@ pub(crate) fn object_decl_to_declaration_pattern( } } } - if object.properties().is_empty() { - bindings.push(PatternObjectElement::Empty); - } - Some(PatternObject::new(bindings.into())) + Some(ObjectPattern::new(bindings.into())) } /// Converts an array declaration into an array declaration pattern. pub(crate) fn array_decl_to_declaration_pattern( array: &ArrayLiteral, strict: bool, -) -> Option { +) -> Option { if array.has_trailing_comma_spread() { return None; } @@ -352,7 +357,7 @@ pub(crate) fn array_decl_to_declaration_pattern( let expr = if let Some(expr) = expr { expr } else { - bindings.push(PatternArrayElement::Elision); + bindings.push(ArrayPatternElement::Elision); continue; }; match expr { @@ -361,7 +366,7 @@ pub(crate) fn array_decl_to_declaration_pattern( return None; } - bindings.push(PatternArrayElement::SingleName { + bindings.push(ArrayPatternElement::SingleName { ident: *ident, default_init: None, }); @@ -369,20 +374,20 @@ pub(crate) fn array_decl_to_declaration_pattern( Expression::Spread(spread) => { match spread.val() { Expression::Identifier(ident) => { - bindings.push(PatternArrayElement::SingleNameRest { ident: *ident }); + bindings.push(ArrayPatternElement::SingleNameRest { ident: *ident }); } Expression::PropertyAccess(access) => { - bindings.push(PatternArrayElement::PropertyAccessRest { + bindings.push(ArrayPatternElement::PropertyAccessRest { access: access.clone(), }); } Expression::ArrayLiteral(array) => { let pattern = array_decl_to_declaration_pattern(array, strict)?.into(); - bindings.push(PatternArrayElement::PatternRest { pattern }); + bindings.push(ArrayPatternElement::PatternRest { pattern }); } Expression::ObjectLiteral(object) => { let pattern = object_decl_to_declaration_pattern(object, strict)?.into(); - bindings.push(PatternArrayElement::PatternRest { pattern }); + bindings.push(ArrayPatternElement::PatternRest { pattern }); } _ => return None, } @@ -392,25 +397,25 @@ pub(crate) fn array_decl_to_declaration_pattern( } Expression::Assign(assign) => match assign.lhs() { AssignTarget::Identifier(ident) => { - bindings.push(PatternArrayElement::SingleName { + bindings.push(ArrayPatternElement::SingleName { ident: *ident, default_init: Some(assign.rhs().clone()), }); } AssignTarget::Property(access) => { - bindings.push(PatternArrayElement::PropertyAccess { + bindings.push(ArrayPatternElement::PropertyAccess { access: access.clone(), }); } AssignTarget::Pattern(pattern) => match pattern { Pattern::Object(pattern) => { - bindings.push(PatternArrayElement::Pattern { + bindings.push(ArrayPatternElement::Pattern { pattern: Pattern::Object(pattern.clone()), default_init: Some(assign.rhs().clone()), }); } Pattern::Array(pattern) => { - bindings.push(PatternArrayElement::Pattern { + bindings.push(ArrayPatternElement::Pattern { pattern: Pattern::Array(pattern.clone()), default_init: Some(assign.rhs().clone()), }); @@ -420,25 +425,25 @@ pub(crate) fn array_decl_to_declaration_pattern( }, Expression::ArrayLiteral(array) => { let pattern = array_decl_to_declaration_pattern(array, strict)?.into(); - bindings.push(PatternArrayElement::Pattern { + bindings.push(ArrayPatternElement::Pattern { pattern, default_init: None, }); } Expression::ObjectLiteral(object) => { let pattern = object_decl_to_declaration_pattern(object, strict)?.into(); - bindings.push(PatternArrayElement::Pattern { + bindings.push(ArrayPatternElement::Pattern { pattern, default_init: None, }); } Expression::PropertyAccess(access) => { - bindings.push(PatternArrayElement::PropertyAccess { + bindings.push(ArrayPatternElement::PropertyAccess { access: access.clone(), }); } _ => return None, } } - Some(PatternArray::new(bindings.into())) + Some(ArrayPattern::new(bindings.into())) } diff --git a/boa_engine/src/syntax/ast/expression/operator/binary/mod.rs b/boa_engine/src/syntax/ast/expression/operator/binary/mod.rs index b90689c99a8..6b3ecca78a0 100644 --- a/boa_engine/src/syntax/ast/expression/operator/binary/mod.rs +++ b/boa_engine/src/syntax/ast/expression/operator/binary/mod.rs @@ -1,4 +1,21 @@ -pub mod op; +//! Binary expression nodes. +//! +//! A Binary expression comprises any operation between two expressions (excluding assignments), +//! such as: +//! - [Logic operations][logic] (`||`, `&&`). +//! - [Relational math][relat] (`==`, `<`). +//! - [Bit manipulation][bit] (`^`, `|`). +//! - [Arithmetic][arith] (`+`, `%`). +//! - The [comma operator][comma] (`,`) +//! +//! [logic]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#binary_logical_operators +//! [relat]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#relational_operators +//! [bit]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#binary_bitwise_operators +//! [arith]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#arithmetic_operators +//! [comma]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator + +mod op; +pub use op::*; use boa_interner::{Interner, ToInternedString}; @@ -6,21 +23,18 @@ use crate::syntax::ast::{expression::Expression, ContainsSymbol}; /// Binary operations require two operands, one before the operator and one after the operator. /// -/// More information: -/// - [MDN documentation][mdn] -/// -/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Operators +/// See the [module level documentation][self] for more information. #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub struct Binary { - op: op::BinaryOp, + op: BinaryOp, lhs: Box, rhs: Box, } impl Binary { /// Creates a `BinOp` AST Expression. - pub(in crate::syntax) fn new(op: op::BinaryOp, lhs: Expression, rhs: Expression) -> Self { + pub(in crate::syntax) fn new(op: BinaryOp, lhs: Expression, rhs: Expression) -> Self { Self { op, lhs: Box::new(lhs), @@ -30,7 +44,7 @@ impl Binary { /// Gets the binary operation of the Expression. #[inline] - pub fn op(&self) -> op::BinaryOp { + pub fn op(&self) -> BinaryOp { self.op } diff --git a/boa_engine/src/syntax/ast/expression/operator/conditional.rs b/boa_engine/src/syntax/ast/expression/operator/conditional.rs index b32d9291e73..6233bd4f745 100644 --- a/boa_engine/src/syntax/ast/expression/operator/conditional.rs +++ b/boa_engine/src/syntax/ast/expression/operator/conditional.rs @@ -24,22 +24,25 @@ pub struct Conditional { } impl Conditional { + /// Gets the condition of the `Conditional` expression. #[inline] - pub fn cond(&self) -> &Expression { + pub fn condition(&self) -> &Expression { &self.condition } + /// Gets the expression returned if `condition` is truthy. #[inline] pub fn if_true(&self) -> &Expression { &self.if_true } + /// Gets the expression returned if `condition` is falsy. #[inline] pub fn if_false(&self) -> &Expression { &self.if_false } - /// Creates a `ConditionalOp` AST Expression. + /// Creates a `Conditional` AST Expression. #[inline] pub fn new(condition: Expression, if_true: Expression, if_false: Expression) -> Self { Self { @@ -69,7 +72,7 @@ impl ToInternedString for Conditional { fn to_interned_string(&self, interner: &Interner) -> String { format!( "{} ? {} : {}", - self.cond().to_interned_string(interner), + self.condition().to_interned_string(interner), self.if_true().to_interned_string(interner), self.if_false().to_interned_string(interner) ) diff --git a/boa_engine/src/syntax/ast/expression/operator/mod.rs b/boa_engine/src/syntax/ast/expression/operator/mod.rs index 697dfbaa76f..4623c8ce99b 100644 --- a/boa_engine/src/syntax/ast/expression/operator/mod.rs +++ b/boa_engine/src/syntax/ast/expression/operator/mod.rs @@ -1,11 +1,23 @@ -//! Operator Expressions +//! Operator expression nodes. +//! +//! An [operator][op] expression is an expression that takes an operator (such as `+`, `typeof`, `+=`) +//! and one or more expressions and returns an expression as a result. +//! An operator expression can be any of the following: +//! +//! - A [`Unary`] expression. +//! - An [`Assign`] expression. +//! - A [`Binary`] expression. +//! - A [`Conditional`] expression. +//! +//! [op]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators + +mod conditional; pub mod assign; pub mod binary; -pub mod conditional; pub mod unary; -pub use self::{assign::Assign, binary::Binary, unary::Unary}; +pub use self::{assign::Assign, binary::Binary, conditional::Conditional, unary::Unary}; #[cfg(test)] mod tests; diff --git a/boa_engine/src/syntax/ast/expression/operator/unary/mod.rs b/boa_engine/src/syntax/ast/expression/operator/unary/mod.rs index 0f43bc2b7c8..e5caf9869ee 100644 --- a/boa_engine/src/syntax/ast/expression/operator/unary/mod.rs +++ b/boa_engine/src/syntax/ast/expression/operator/unary/mod.rs @@ -1,10 +1,25 @@ -pub mod op; +//! Unary expression nodes. +//! +//! A Binary expression comprises any operation applied to a single expression. Some examples include: +//! +//! - [Increment and decrement operations][inc] (`++`, `--`). +//! - The [`delete`][del] operator. +//! - The [bitwise NOT][not] operator (`~`). +//! +//! The full list of valid unary operators is defined in [`UnaryOp`]. +//! +//! [inc]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#increment_and_decrement +//! [del]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete +//! [not]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_NOT +mod op; + +pub use op::*; use boa_interner::{Interner, ToInternedString}; use crate::syntax::ast::{expression::Expression, ContainsSymbol}; -/// A unary operation is an operation with only one operand. +/// A unary expression is an operation with only one operand. /// /// More information: /// - [ECMAScript reference][spec] @@ -15,13 +30,13 @@ use crate::syntax::ast::{expression::Expression, ContainsSymbol}; #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub struct Unary { - op: op::UnaryOp, + op: UnaryOp, target: Box, } impl Unary { /// Creates a new `UnaryOp` AST Expression. - pub(in crate::syntax) fn new(op: op::UnaryOp, target: Expression) -> Self { + pub(in crate::syntax) fn new(op: UnaryOp, target: Expression) -> Self { Self { op, target: Box::new(target), @@ -30,7 +45,7 @@ impl Unary { /// Gets the unary operation of the Expression. #[inline] - pub fn op(&self) -> op::UnaryOp { + pub fn op(&self) -> UnaryOp { self.op } @@ -55,7 +70,7 @@ impl ToInternedString for Unary { #[inline] fn to_interned_string(&self, interner: &Interner) -> String { let space = match self.op { - op::UnaryOp::TypeOf | op::UnaryOp::Delete | op::UnaryOp::Void => " ", + UnaryOp::TypeOf | UnaryOp::Delete | UnaryOp::Void => " ", _ => "", }; format!( diff --git a/boa_engine/src/syntax/ast/expression/spread.rs b/boa_engine/src/syntax/ast/expression/spread.rs index 63082288759..b8c41c3de40 100644 --- a/boa_engine/src/syntax/ast/expression/spread.rs +++ b/boa_engine/src/syntax/ast/expression/spread.rs @@ -24,29 +24,32 @@ use super::Expression; #[cfg_attr(feature = "deser", serde(transparent))] #[derive(Clone, Debug, PartialEq)] pub struct Spread { - val: Box, + expression: Box, } impl Spread { + /// Gets the expression to be expanded by the spread operator. #[inline] pub fn val(&self) -> &Expression { - &self.val + &self.expression } /// Creates a `Spread` AST Expression. #[inline] pub fn new(val: Expression) -> Self { - Self { val: Box::new(val) } + Self { + expression: Box::new(val), + } } #[inline] pub(crate) fn contains_arguments(&self) -> bool { - self.val.contains_arguments() + self.expression.contains_arguments() } #[inline] pub(crate) fn contains(&self, symbol: ContainsSymbol) -> bool { - self.val.contains(symbol) + self.expression.contains(symbol) } } diff --git a/boa_engine/src/syntax/ast/expression/tagged_template.rs b/boa_engine/src/syntax/ast/expression/tagged_template.rs index 7f83218dfdc..d1400a6028a 100644 --- a/boa_engine/src/syntax/ast/expression/tagged_template.rs +++ b/boa_engine/src/syntax/ast/expression/tagged_template.rs @@ -4,6 +4,13 @@ use crate::syntax::ast::ContainsSymbol; use super::Expression; +/// A [`TaggedTemplate`][moz] expression, as defined by the [spec]. +/// +/// `TaggedTemplate`s are a type of template literals that are parsed by a custom function to generate +/// arbitrary objects from the inner strings and expressions. +/// +/// [moz]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates +/// [spec]: https://tc39.es/ecma262/#sec-tagged-templates #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub struct TaggedTemplate { diff --git a/boa_engine/src/syntax/ast/expression/yield.rs b/boa_engine/src/syntax/ast/expression/yield.rs index 79c1e255ba2..73b2e4bb7c6 100644 --- a/boa_engine/src/syntax/ast/expression/yield.rs +++ b/boa_engine/src/syntax/ast/expression/yield.rs @@ -20,11 +20,13 @@ pub struct Yield { } impl Yield { + /// Gets the expression of this `Yield` statement. #[inline] pub fn expr(&self) -> Option<&Expression> { self.expr.as_ref().map(Box::as_ref) } + /// Returns `true` if this `Yield` statement delegates to another generator or iterable object. #[inline] pub fn delegate(&self) -> bool { self.delegate diff --git a/boa_engine/src/syntax/ast/function/arrow_function.rs b/boa_engine/src/syntax/ast/function/arrow_function.rs index 1f78ee0ae39..930262b2f9a 100644 --- a/boa_engine/src/syntax/ast/function/arrow_function.rs +++ b/boa_engine/src/syntax/ast/function/arrow_function.rs @@ -6,17 +6,13 @@ use boa_interner::{Interner, ToIndentedString}; use super::FormalParameterList; -/// An arrow function expression is a syntactically compact alternative to a regular function -/// expression. +/// An arrow function expression, as defined by the [spec]. /// -/// Arrow function expressions are ill suited as methods, and they cannot be used as +/// An [arrow function][mdn] expression is a syntactically compact alternative to a regular function +/// expression. Arrow function expressions are ill suited as methods, and they cannot be used as /// constructors. Arrow functions cannot be used as constructors and will throw an error when /// used with new. /// -/// More information: -/// - [ECMAScript reference][spec] -/// - [MDN documentation][mdn] -/// /// [spec]: https://tc39.es/ecma262/#prod-ArrowFunction /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] diff --git a/boa_engine/src/syntax/ast/function/async_function.rs b/boa_engine/src/syntax/ast/function/async_function.rs index c0c18f29e24..c399f9c1d44 100644 --- a/boa_engine/src/syntax/ast/function/async_function.rs +++ b/boa_engine/src/syntax/ast/function/async_function.rs @@ -8,15 +8,14 @@ use boa_interner::{Interner, ToIndentedString}; use super::FormalParameterList; -/// An async function expression is very similar to an async function declaration except used within -/// a wider expression (for example during an assignment). +/// An async function definition, as defined by the [spec]. /// -/// More information: -/// - [ECMAScript reference][spec] -/// - [MDN documentation][mdn] +/// An [async function][mdn] is a function where await expressions are allowed within it. +/// The async and await keywords enable asynchronous programming on Javascript without the use +/// of promise chains. /// -/// [spec]: https://tc39.es/ecma262/#prod-AsyncFunctionExpression -/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/async_function +/// [spec]: https://tc39.es/ecma262/#sec-async-function-definitions +/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub struct AsyncFunction { diff --git a/boa_engine/src/syntax/ast/function/async_generator.rs b/boa_engine/src/syntax/ast/function/async_generator.rs index e2f1989491c..8c246f03ee7 100644 --- a/boa_engine/src/syntax/ast/function/async_generator.rs +++ b/boa_engine/src/syntax/ast/function/async_generator.rs @@ -8,12 +8,13 @@ use boa_interner::{Interner, ToIndentedString}; use super::FormalParameterList; -/// The `async function*` keyword can be used to define a generator function inside an expression. +/// An async generator definition, as defined by the [spec]. /// -/// More information: -/// - [ECMAScript reference][spec] +/// An [async generator][mdn] combines async functions with generators, making it possible to use +/// `await` and `yield` expressions within the definition of the function. /// -/// [spec]: https://tc39.es/ecma262/#prod-AsyncGeneratorExpression +/// [spec]: https://tc39.es/ecma262/#sec-async-generator-function-definitions +/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function* #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub struct AsyncGenerator { diff --git a/boa_engine/src/syntax/ast/function/class.rs b/boa_engine/src/syntax/ast/function/class.rs index 5aa8b9db31e..a9052778e33 100644 --- a/boa_engine/src/syntax/ast/function/class.rs +++ b/boa_engine/src/syntax/ast/function/class.rs @@ -7,24 +7,20 @@ use crate::{ expression::{Expression, Identifier}, join_nodes, property::{MethodDefinition, PropertyName}, - statement_list::StatementListItem, - ContainsSymbol, Declaration, StatementList, + ContainsSymbol, Declaration, StatementList, StatementListItem, }, }; use boa_interner::{Interner, Sym, ToIndentedString, ToInternedString}; use super::Function; -/// The `class` declaration defines a class with the specified methods, fields, and optional constructor. +/// A class declaration, as defined by the [spec]. /// +/// A [class][mdn] declaration defines a class with the specified methods, fields, and optional constructor. /// Classes can be used to create objects, which can also be created through literals (using `{}`). /// -/// More information: -/// - [ECMAScript reference][spec] -/// - [MDN documentation][mdn] -/// /// [spec]: https://tc39.es/ecma262/#sec-class-definitions -/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function +/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub struct Class { @@ -381,18 +377,31 @@ impl From for Declaration { } } -/// Class element types. +/// An element that can be within a [`Class`], as defined by the [spec]. +/// +/// [spec]: https://tc39.es/ecma262/#prod-ClassElement #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub enum ClassElement { + /// A method definition, including `get` and `set` accessors. MethodDefinition(PropertyName, MethodDefinition), + /// A static method definition, accessible from the class constructor object. StaticMethodDefinition(PropertyName, MethodDefinition), + /// A field definition. FieldDefinition(PropertyName, Option), + /// A static field definition, accessible from the class constructor object StaticFieldDefinition(PropertyName, Option), + /// A private method definition, only accessible inside the class declaration. PrivateMethodDefinition(Sym, MethodDefinition), + /// A private static method definition, only accessible from static methods and fields inside + /// the class declaration. PrivateStaticMethodDefinition(Sym, MethodDefinition), + /// A private field definition, only accessible inside the class declaration. PrivateFieldDefinition(Sym, Option), + /// A private static field definition, only accessible from static methods and fields inside the + /// class declaration. PrivateStaticFieldDefinition(Sym, Option), + /// A static block, where a class can have initialization logic for its static fields. StaticBlock(StatementList), } diff --git a/boa_engine/src/syntax/ast/function/generator.rs b/boa_engine/src/syntax/ast/function/generator.rs index d3aec682f6e..3219d262fbc 100644 --- a/boa_engine/src/syntax/ast/function/generator.rs +++ b/boa_engine/src/syntax/ast/function/generator.rs @@ -8,14 +8,15 @@ use boa_interner::{Interner, ToIndentedString}; use super::FormalParameterList; -/// The `function*` keyword can be used to define a generator function inside an expression. +/// A generator definition, as defined by the [spec]. /// -/// More information: -/// - [ECMAScript reference][spec] -/// - [MDN documentation][mdn] +/// [Generators][mdn] are "resumable functions", which can be suspended during execution and +/// resumed at any later time. The main feature of a generator are `yield` expressions, which +/// specifies the value returned when a generator is suspended, and the point from which +/// the execution will resume. /// -/// [spec]: https://tc39.es/ecma262/#prod-GeneratorExpression -/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function* +/// [spec]: https://tc39.es/ecma262/#sec-generator-function-definitions +/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function* #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub struct Generator { diff --git a/boa_engine/src/syntax/ast/function/mod.rs b/boa_engine/src/syntax/ast/function/mod.rs index 7cc8b2c0c89..9eb6328a637 100644 --- a/boa_engine/src/syntax/ast/function/mod.rs +++ b/boa_engine/src/syntax/ast/function/mod.rs @@ -1,3 +1,25 @@ +//! Functions and classes nodes, as defined by the [spec]. +//! +//! [Functions][func] are mainly subprograms that can be called by external code to execute a sequence of +//! statements (the *body* of the function). Javascript functions fall in several categories: +//! +//! - [`Function`]s. +//! - [`ArrowFunction`]s. +//! - [`Generator`]s. +//! - [`AsyncFunction`]s. +//! - [`AsyncGenerator`]s. +//! +//! All of them can be declared in either [declaration][decl] form or [expression][expr] form, +//! except from `ArrowFunction`s, which can only be declared in expression form. +//! +//! This module also contains [`Class`]es, which are templates for creating objects. Classes +//! can also be declared in either declaration or expression form. +//! +//! [spec]: https://tc39.es/ecma262/#sec-ecmascript-language-functions-and-classes +//! [func]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions +//! [decl]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function +//! [expr]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function + mod arrow_function; mod async_function; mod async_generator; @@ -20,22 +42,16 @@ use boa_interner::{Interner, ToIndentedString}; use super::expression::{Expression, Identifier}; use super::{ContainsSymbol, Declaration}; -/// The `function` expression defines a function with the specified parameters. -/// -/// A function created with a function expression is a `Function` object and has all the -/// properties, methods and behavior of `Function`. -/// -/// A function can also be created using a declaration (see function expression). +/// A function definition, as defined by the [spec]. /// /// By default, functions return `undefined`. To return any other value, the function must have /// a return statement that specifies the value to return. /// /// More information: -/// - [ECMAScript reference][spec] /// - [MDN documentation][mdn] /// -/// [spec]: https://tc39.es/ecma262/#sec-terms-and-definitions-function -/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function +/// [spec]: https://tc39.es/ecma262/#sec-function-definitions +/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub struct Function { diff --git a/boa_engine/src/syntax/ast/function/parameters.rs b/boa_engine/src/syntax/ast/function/parameters.rs index da450b7513b..a2d6785c063 100644 --- a/boa_engine/src/syntax/ast/function/parameters.rs +++ b/boa_engine/src/syntax/ast/function/parameters.rs @@ -11,10 +11,7 @@ use bitflags::bitflags; use boa_interner::{Interner, Sym, ToInternedString}; use rustc_hash::FxHashSet; -/// `FormalParameterList` is a list of `FormalParameter`s that describes the parameters of a function. -/// -/// More information: -/// - [ECMAScript reference][spec] +/// A list of `FormalParameter`s that describes the parameters of a function, as defined by the [spec]. /// /// [spec]: https://tc39.es/ecma262/#prod-FormalParameterList #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] @@ -279,7 +276,7 @@ impl FormalParameter { } } - /// Get the variable of the formal parameter + /// Gets the variable of the formal parameter pub fn variable(&self) -> &Variable { &self.variable } @@ -289,11 +286,12 @@ impl FormalParameter { self.variable.init() } - /// Gets wether the parameter is a rest parameter. + /// Returns `true` if the parameter is a rest parameter. pub fn is_rest_param(&self) -> bool { self.is_rest_param } + /// Returns `true` if the parameter is a simple [`Identifier`]. pub fn is_identifier(&self) -> bool { matches!(&self.variable.binding(), Binding::Identifier(_)) } diff --git a/boa_engine/src/syntax/ast/keyword.rs b/boa_engine/src/syntax/ast/keyword.rs index ef6ef20a3aa..9c605e3d6f6 100644 --- a/boa_engine/src/syntax/ast/keyword.rs +++ b/boa_engine/src/syntax/ast/keyword.rs @@ -1,29 +1,24 @@ -//! This module implements the `Keyword` structure, which represents reserved words of the JavaScript language. +//! The `Keyword` AST node, which represents reserved words of the JavaScript language. //! -//! More information: -//! - [ECMAScript reference][spec] -//! - [MDN documentation][mdn] +//! The [specification][spec] defines keywords as tokens that match an `IdentifierName`, but also +//! have special meaning in JavaScript. In JavaScript you cannot use these reserved words as variables, +//! labels, or function names. +//! +//! The [MDN documentation][mdn] contains a more extensive explanation about keywords. //! //! [spec]: https://tc39.es/ecma262/#sec-keywords-and-reserved-words //! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords use crate::{ string::utf16, - syntax::ast::expression::operator::binary::op::{BinaryOp, RelationalOp}, + syntax::ast::expression::operator::binary::{BinaryOp, RelationalOp}, }; use boa_interner::{Interner, Sym}; -use std::{convert::TryInto, error, fmt, str::FromStr}; +use std::{convert::TryFrom, error, fmt, str::FromStr}; -/// Keywords are tokens that have special meaning in JavaScript. -/// -/// In JavaScript you cannot use these reserved words as variables, labels, or function names. -/// -/// More information: -/// - [ECMAScript reference][spec] -/// - [MDN documentation][mdn] +/// List of keywords recognized by the JavaScript grammar. /// -/// [spec]: https://tc39.es/ecma262/#sec-keywords-and-reserved-words -/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords +/// See the [module-level documentation][self] for more details. #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum Keyword { @@ -482,7 +477,8 @@ pub enum Keyword { } impl Keyword { - /// Gets the keyword as a binary operation, if this keyword is the `in` keyword. + /// Gets the keyword as a binary operation, if this keyword is the `in` or the `instanceof` + /// keywords. pub fn as_binary_op(self) -> Option { match self { Self::In => Some(BinaryOp::Relational(RelationalOp::In)), @@ -538,6 +534,7 @@ impl Keyword { } } + // TODO: promote all keywords to statics inside Interner /// Converts the keyword to a symbol in the given interner. pub fn to_sym(self, interner: &mut Interner) -> Sym { let (utf8, utf16) = self.as_str(); @@ -545,14 +542,18 @@ impl Keyword { } } -impl TryInto for Keyword { +// TODO: Should use a proper Error +impl TryFrom for BinaryOp { type Error = String; - fn try_into(self) -> Result { - self.as_binary_op() - .ok_or_else(|| format!("No binary operation for {self}")) + + fn try_from(value: Keyword) -> Result { + value + .as_binary_op() + .ok_or_else(|| format!("No binary operation for {value}")) } } +/// The error type which is returned from parsing a [`str`] into a [`Keyword`]. #[derive(Debug, Clone, Copy)] pub struct KeywordError; impl fmt::Display for KeywordError { @@ -566,11 +567,6 @@ impl error::Error for KeywordError { fn description(&self) -> &str { "invalid token" } - - fn cause(&self) -> Option<&dyn error::Error> { - // Generic error, underlying cause isn't tracked. - None - } } impl FromStr for Keyword { type Err = KeywordError; diff --git a/boa_engine/src/syntax/ast/mod.rs b/boa_engine/src/syntax/ast/mod.rs index 249d950fef5..360f45a16d5 100644 --- a/boa_engine/src/syntax/ast/mod.rs +++ b/boa_engine/src/syntax/ast/mod.rs @@ -1,15 +1,29 @@ //! The Javascript Abstract Syntax Tree. +//! +//! This module contains representations of [**Parse Nodes**][grammar] as defined by the ECMAScript spec. +//! Some `Parse Node`s are not represented by Boa's AST, because a lot of grammar productions are +//! only used to throw [**Early Errors**][early], and don't influence the evaluation of the AST itself. +//! +//! Boa's AST is mainly split in three main components: [`Declaration`]s, [`Expression`]s and +//! [`Statement`]s, with [`StatementList`] being the primordial Parse Node that combines +//! all of them to create a proper AST. +//! +//! [grammar]: https://tc39.es/ecma262/#sec-syntactic-grammar +//! [early]: https://tc39.es/ecma262/#sec-static-semantic-rules + +#![deny(missing_docs)] + +mod position; +mod punctuator; +mod statement_list; pub mod declaration; pub mod expression; pub mod function; pub mod keyword; pub mod pattern; -pub mod position; pub mod property; -pub mod punctuator; pub mod statement; -pub mod statement_list; use boa_interner::{Interner, ToIndentedString, ToInternedString}; @@ -23,7 +37,9 @@ pub use self::{ statement_list::{StatementList, StatementListItem}, }; -/// Represents the possible symbols that can be use the the `contains` function. +/// Represents all the possible symbols searched for by the [`Contains`][contains] operation. +/// +/// [contains]: https://tc39.es/ecma262/#sec-syntax-directed-operations-contains #[derive(Clone, Copy, Debug, PartialEq)] pub(crate) enum ContainsSymbol { SuperProperty, diff --git a/boa_engine/src/syntax/ast/pattern.rs b/boa_engine/src/syntax/ast/pattern.rs index 180c53ae6f2..d1c58f6cb9b 100644 --- a/boa_engine/src/syntax/ast/pattern.rs +++ b/boa_engine/src/syntax/ast/pattern.rs @@ -1,3 +1,27 @@ +//! A pattern binding or assignment node. +//! +//! A [`Pattern`] Corresponds to the [`BindingPattern`][spec1] and the [`AssignmentPattern`][spec2] +//! nodes, each of which is used in different situations and have slightly different grammars. +//! For example, a variable declaration combined with a destructuring expression is a `BindingPattern`: +//! +//! ```Javascript +//! const obj = { a: 1, b: 2 }; +//! const { a, b } = obj; // BindingPattern +//! ``` +//! +//! On the other hand, a simple destructuring expression with already declared variables is called +//! an `AssignmentPattern`: +//! +//! ```Javascript +//! let a = 1; +//! let b = 3; +//! [a, b] = [b, a]; // AssignmentPattern +//! ``` +//! +//! [spec1]: https://tc39.es/ecma262/#prod-BindingPattern +//! [spec2]: https://tc39.es/ecma262/#prod-AssignmentPattern +//! [destr]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment + use boa_interner::{Interner, ToInternedString}; use super::{ @@ -9,41 +33,38 @@ use super::{ ContainsSymbol, Expression, }; -/// `Pattern` represents an object or array pattern. -/// -/// This enum mostly wraps the functionality of the specific binding pattern types. +/// An object or array pattern binding or assignment. /// -/// More information: -/// - [ECMAScript reference: 14.3.3 Destructuring Binding Patterns - `BindingPattern`][spec1] -/// -/// [spec1]: https://tc39.es/ecma262/#prod-BindingPattern +/// See the [module level documentation][self] for more information. #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub enum Pattern { - Object(PatternObject), - Array(PatternArray), + /// An object pattern (`let {a, b, c} = object`). + Object(ObjectPattern), + /// An array pattern (`[a, b, c] = array`). + Array(ArrayPattern), } -impl From for Pattern { - fn from(obj: PatternObject) -> Self { +impl From for Pattern { + fn from(obj: ObjectPattern) -> Self { Pattern::Object(obj) } } -impl From for Pattern { - fn from(obj: PatternArray) -> Self { +impl From for Pattern { + fn from(obj: ArrayPattern) -> Self { Pattern::Array(obj) } } -impl From> for Pattern { - fn from(elements: Vec) -> Self { - PatternObject::new(elements.into()).into() +impl From> for Pattern { + fn from(elements: Vec) -> Self { + ObjectPattern::new(elements.into()).into() } } -impl From> for Pattern { - fn from(elements: Vec) -> Self { - PatternArray::new(elements.into()).into() +impl From> for Pattern { + fn from(elements: Vec) -> Self { + ArrayPattern::new(elements.into()).into() } } @@ -97,25 +118,26 @@ impl Pattern { } } -/// `DeclarationPatternObject` represents an object binding pattern. +/// An object binding or assignment pattern. /// -/// This struct holds a list of bindings, and an optional initializer for the binding pattern. +/// Corresponds to the [`ObjectBindingPattern`][spec1] and the [`ObjectAssignmentPattern`][spec2] +/// Parse Nodes. /// -/// More information: -/// - [ECMAScript reference: 14.3.3 Destructuring Binding Patterns - `ObjectBindingPattern`][spec1] +/// For more information on what is a valid binding in an object pattern, see [`ObjectPatternElement`]. /// /// [spec1]: https://tc39.es/ecma262/#prod-ObjectBindingPattern +/// [spec2]: https://tc39.es/ecma262/#prod-ObjectAssignmentPattern #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] -pub struct PatternObject(Box<[PatternObjectElement]>); +pub struct ObjectPattern(Box<[ObjectPatternElement]>); -impl From> for PatternObject { - fn from(elements: Vec) -> Self { +impl From> for ObjectPattern { + fn from(elements: Vec) -> Self { Self(elements.into()) } } -impl ToInternedString for PatternObject { +impl ToInternedString for ObjectPattern { fn to_interned_string(&self, interner: &Interner) -> String { let mut buf = "{".to_owned(); for (i, binding) in self.0.iter().enumerate() { @@ -133,45 +155,33 @@ impl ToInternedString for PatternObject { } } -impl PatternObject { - /// Create a new object binding pattern. +impl ObjectPattern { + /// Creates a new object binding pattern. #[inline] - pub(in crate::syntax) fn new(bindings: Box<[PatternObjectElement]>) -> Self { + pub(in crate::syntax) fn new(bindings: Box<[ObjectPatternElement]>) -> Self { Self(bindings) } /// Gets the bindings for the object binding pattern. #[inline] - pub(crate) fn bindings(&self) -> &[PatternObjectElement] { + pub(crate) fn bindings(&self) -> &[ObjectPatternElement] { &self.0 } - // Returns if the object binding pattern has a rest element. + // Returns true if the object binding pattern has a rest element. #[inline] pub(crate) fn has_rest(&self) -> bool { matches!( self.0.last(), - Some(PatternObjectElement::RestProperty { .. }) + Some(ObjectPatternElement::RestProperty { .. }) ) } - /// 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 { - self.0.iter().any(PatternObjectElement::contains_arguments) + self.0.iter().any(ObjectPatternElement::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 { self.0.iter().any(|e| e.contains(symbol)) @@ -182,36 +192,37 @@ impl PatternObject { pub(crate) fn idents(&self) -> Vec { self.0 .iter() - .flat_map(PatternObjectElement::idents) + .flat_map(ObjectPatternElement::idents) .collect() } } -/// `DeclarationPatternArray` represents an array binding pattern. +/// An array binding or assignment pattern. /// -/// This struct holds a list of bindings, and an optional initializer for the binding pattern. +/// Corresponds to the [`ArrayBindingPattern`][spec1] and the [`ArrayAssignmentPattern`][spec2] +/// Parse Nodes. /// -/// More information: -/// - [ECMAScript reference: 14.3.3 Destructuring Binding Patterns - `ArrayBindingPattern`][spec1] +/// For more information on what is a valid binding in an array pattern, see [`ArrayPatternElement`]. /// /// [spec1]: https://tc39.es/ecma262/#prod-ArrayBindingPattern +/// [spec2]: https://tc39.es/ecma262/#prod-ArrayAssignmentPattern #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] -pub struct PatternArray(Box<[PatternArrayElement]>); +pub struct ArrayPattern(Box<[ArrayPatternElement]>); -impl From> for PatternArray { - fn from(elements: Vec) -> Self { +impl From> for ArrayPattern { + fn from(elements: Vec) -> Self { Self(elements.into()) } } -impl ToInternedString for PatternArray { +impl ToInternedString for ArrayPattern { fn to_interned_string(&self, interner: &Interner) -> String { let mut buf = "[".to_owned(); for (i, binding) in self.0.iter().enumerate() { if i == self.0.len() - 1 { match binding { - PatternArrayElement::Elision => { + ArrayPatternElement::Elision => { buf.push_str(&format!("{}, ", binding.to_interned_string(interner))); } _ => buf.push_str(&format!("{} ", binding.to_interned_string(interner))), @@ -225,36 +236,24 @@ impl ToInternedString for PatternArray { } } -impl PatternArray { - /// Create a new array binding pattern. +impl ArrayPattern { + /// Creates a new array binding pattern. #[inline] - pub(in crate::syntax) fn new(bindings: Box<[PatternArrayElement]>) -> Self { + pub(in crate::syntax) fn new(bindings: Box<[ArrayPatternElement]>) -> Self { Self(bindings) } /// Gets the bindings for the array binding pattern. #[inline] - pub(crate) fn bindings(&self) -> &[PatternArrayElement] { + pub(crate) fn bindings(&self) -> &[ArrayPatternElement] { &self.0 } - /// 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 { - self.0.iter().any(PatternArrayElement::contains_arguments) + self.0.iter().any(ArrayPatternElement::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 pub(crate) fn contains(&self, symbol: ContainsSymbol) -> bool { self.0.iter().any(|e| e.contains(symbol)) } @@ -264,23 +263,20 @@ impl PatternArray { pub(crate) fn idents(&self) -> Vec { self.0 .iter() - .flat_map(PatternArrayElement::idents) + .flat_map(ArrayPatternElement::idents) .collect() } } -/// `BindingPatternTypeObject` represents the different types of bindings that an object binding pattern may contain. +/// The different types of bindings that an [`ObjectPattern`] may contain. /// -/// More information: -/// - [ECMAScript reference: 14.3.3 Destructuring Binding Patterns - `ObjectBindingPattern`][spec1] +/// Corresponds to the [`BindingProperty`][spec1] and the [`AssignmentProperty`][spec2] nodes. /// -/// [spec1]: https://tc39.es/ecma262/#prod-ObjectBindingPattern +/// [spec1]: https://tc39.es/ecma262/#prod-BindingProperty +/// [spec2]: https://tc39.es/ecma262/#prod-AssignmentProperty #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] -pub enum PatternObjectElement { - /// Empty represents an empty object pattern e.g. `{ }`. - Empty, - +pub enum ObjectPatternElement { /// SingleName represents one of the following properties: /// /// - `SingleName` with an identifier and an optional default initializer. @@ -293,8 +289,11 @@ pub enum PatternObjectElement { /// [spec1]: https://tc39.es/ecma262/#prod-SingleNameBinding /// [spec2]: https://tc39.es/ecma262/#prod-BindingProperty SingleName { + /// The identifier name of the property to be destructured. name: PropertyName, + /// The variable name where the property value will be stored. ident: Identifier, + /// An optional default value for the variable, in case the property doesn't exist. default_init: Option, }, @@ -308,7 +307,9 @@ pub enum PatternObjectElement { /// /// [spec1]: https://tc39.es/ecma262/#prod-BindingRestProperty RestProperty { + /// The variable name where the unassigned properties will be stored. ident: Identifier, + /// A list of the excluded property keys that were already destructured. excluded_keys: Vec, }, @@ -322,8 +323,11 @@ pub enum PatternObjectElement { /// /// [spec]: https://tc39.es/ecma262/#prod-AssignmentProperty AssignmentPropertyAccess { + /// The identifier name of the property to be destructured. name: PropertyName, + /// The property access where the property value will be destructured. access: PropertyAccess, + /// An optional default value for the variable, in case the property doesn't exist. default_init: Option, }, @@ -337,7 +341,9 @@ pub enum PatternObjectElement { /// /// [spec]: https://tc39.es/ecma262/#prod-AssignmentRestProperty AssignmentRestPropertyAccess { + /// The property access where the unassigned properties will be stored. access: PropertyAccess, + /// A list of the excluded property keys that were already destructured. excluded_keys: Vec, }, @@ -351,23 +357,20 @@ pub enum PatternObjectElement { /// /// [spec1]: https://tc39.es/ecma262/#prod-BindingProperty Pattern { + /// The identifier name of the property to be destructured. name: PropertyName, + /// The pattern where the property value will be destructured. pattern: Pattern, + /// An optional default value for the variable, in case the property doesn't exist. default_init: Option, }, } -impl PatternObjectElement { - /// Returns true if the element contains a identifier reference named 'arguments'. - /// - /// More information: - /// - [ECMAScript specification][spec] - /// - /// [spec]: https://tc39.es/ecma262/#sec-static-semantics-containsarguments +impl ObjectPatternElement { #[inline] pub(crate) fn contains_arguments(&self) -> bool { match self { - PatternObjectElement::SingleName { + ObjectPatternElement::SingleName { name, default_init, .. } => { if let PropertyName::Computed(node) = name { @@ -381,12 +384,12 @@ impl PatternObjectElement { } } } - PatternObjectElement::AssignmentRestPropertyAccess { access, .. } => { + ObjectPatternElement::AssignmentRestPropertyAccess { access, .. } => { if access.target().contains_arguments() { return true; } } - PatternObjectElement::Pattern { + ObjectPatternElement::Pattern { name, pattern, default_init, @@ -410,12 +413,6 @@ impl PatternObjectElement { false } - /// Returns `true` if the node contains the given token. - /// - /// More information: - /// - [ECMAScript specification][spec] - /// - /// [spec]: https://tc39.es/ecma262/#sec-static-semantics-contains pub(crate) fn contains(&self, symbol: ContainsSymbol) -> bool { match self { Self::SingleName { @@ -469,10 +466,9 @@ impl PatternObjectElement { } } -impl ToInternedString for PatternObjectElement { +impl ToInternedString for ObjectPatternElement { fn to_interned_string(&self, interner: &Interner) -> String { match self { - Self::Empty => String::new(), Self::SingleName { ident, name, @@ -567,26 +563,15 @@ impl ToInternedString for PatternObjectElement { } } -/// `PatternTypeArray` represents the different types of bindings that an array binding pattern may contain. +/// The different types of bindings that an array binding pattern may contain. /// -/// More information: -/// - [ECMAScript reference: 14.3.3 Destructuring Binding Patterns - `ArrayBindingPattern`][spec1] +/// Corresponds to the [`BindingElement`][spec1] and the [`AssignmentElement`][spec2] nodes. /// -/// [spec1]: https://tc39.es/ecma262/#prod-ArrayBindingPattern +/// [spec1]: https://tc39.es/ecma262/#prod-BindingElement +/// [spec2]: https://tc39.es/ecma262/#prod-AssignmentElement #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] -pub enum PatternArrayElement { - /// Empty represents an empty array pattern e.g. `[ ]`. - /// - /// This may occur because the `Elision` and `BindingRestElement` in the first type of - /// array binding pattern are both optional. - /// - /// More information: - /// - [ECMAScript reference: 14.3.3 Destructuring Binding Patterns - ArrayBindingPattern][spec1] - /// - /// [spec1]: https://tc39.es/ecma262/#prod-ArrayBindingPattern - Empty, - +pub enum ArrayPatternElement { /// Elision represents the elision of an item in the array binding pattern. /// /// An `Elision` may occur at multiple points in the pattern and may be multiple elisions. @@ -605,7 +590,9 @@ pub enum PatternArrayElement { /// /// [spec1]: https://tc39.es/ecma262/#prod-SingleNameBinding SingleName { + /// The variable name where the index element will be stored. ident: Identifier, + /// An optional default value for the variable, in case the index element doesn't exist. default_init: Option, }, @@ -618,7 +605,10 @@ pub enum PatternArrayElement { /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#prod-AssignmentExpression - PropertyAccess { access: PropertyAccess }, + PropertyAccess { + /// The property access where the index element will be stored. + access: PropertyAccess, + }, /// Pattern represents a `Pattern` in an `Element` of an array pattern. /// @@ -629,7 +619,9 @@ pub enum PatternArrayElement { /// /// [spec1]: https://tc39.es/ecma262/#prod-BindingElement Pattern { + /// The pattern where the index element will be stored. pattern: Pattern, + /// An optional default value for the pattern, in case the index element doesn't exist. default_init: Option, }, @@ -639,7 +631,10 @@ pub enum PatternArrayElement { /// - [ECMAScript reference: 14.3.3 Destructuring Binding Patterns - BindingRestElement][spec1] /// /// [spec1]: https://tc39.es/ecma262/#prod-BindingRestElement - SingleNameRest { ident: Identifier }, + SingleNameRest { + /// The variable where the unassigned index elements will be stored. + ident: Identifier, + }, /// PropertyAccess represents a rest (spread operator) with a property accessor. /// @@ -650,7 +645,10 @@ pub enum PatternArrayElement { /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#prod-AssignmentExpression - PropertyAccessRest { access: PropertyAccess }, + PropertyAccessRest { + /// The property access where the unassigned index elements will be stored. + access: PropertyAccess, + }, /// PatternRest represents a `Pattern` in a `RestElement` of an array pattern. /// @@ -658,10 +656,13 @@ pub enum PatternArrayElement { /// - [ECMAScript reference: 14.3.3 Destructuring Binding Patterns - BindingRestElement][spec1] /// /// [spec1]: https://tc39.es/ecma262/#prod-BindingRestElement - PatternRest { pattern: Pattern }, + PatternRest { + /// The pattern where the unassigned index elements will be stored. + pattern: Pattern, + }, } -impl PatternArrayElement { +impl ArrayPatternElement { /// Returns true if the node contains a identifier reference named 'arguments'. /// /// More information: @@ -777,10 +778,9 @@ impl PatternArrayElement { } } -impl ToInternedString for PatternArrayElement { +impl ToInternedString for ArrayPatternElement { fn to_interned_string(&self, interner: &Interner) -> String { match self { - Self::Empty => String::new(), Self::Elision => " ".to_owned(), Self::SingleName { ident, diff --git a/boa_engine/src/syntax/ast/position.rs b/boa_engine/src/syntax/ast/position.rs index c7b2a293895..c133b132add 100644 --- a/boa_engine/src/syntax/ast/position.rs +++ b/boa_engine/src/syntax/ast/position.rs @@ -1,21 +1,12 @@ -//! This module implements the `Pos` structure, which represents a position in the source code. - use std::{cmp::Ordering, fmt, num::NonZeroU32}; -#[cfg(feature = "deser")] -use serde::{Deserialize, Serialize}; - /// A position in the JavaScript source code. /// /// Stores both the column number and the line number. /// -/// Note that spans are of the form [beginning, end) i.e. that the beginning position is inclusive -/// and the end position is exclusive. See test `check_positions` from `syntax/lexer/tests.rs` for -/// an example. -/// /// ## Similar Implementations /// [V8: Location](https://cs.chromium.org/chromium/src/v8/src/parsing/scanner.h?type=cs&q=isValid+Location&g=0&l=216) -#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub struct Position { /// Line number. @@ -57,7 +48,10 @@ impl fmt::Display for Position { /// A span in the JavaScript source code. /// /// Stores a start position and an end position. -#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))] +/// +/// Note that spans are of the form [start, end) i.e. that the start position is inclusive +/// and the end position is exclusive. +#[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Span { start: Position, diff --git a/boa_engine/src/syntax/ast/property.rs b/boa_engine/src/syntax/ast/property.rs index 975b66d206e..69421877435 100644 --- a/boa_engine/src/syntax/ast/property.rs +++ b/boa_engine/src/syntax/ast/property.rs @@ -1,3 +1,5 @@ +//! Property definition related types, used in object literals and class definitions. + use boa_interner::{Interner, Sym, ToInternedString}; use super::{ @@ -6,7 +8,7 @@ use super::{ ContainsSymbol, Expression, StatementList, }; -/// A JavaScript property is a characteristic of an object, often describing attributes associated with a data structure. +/// Describes the definition of a property within an object literal. /// /// A property has a name (a string) and a value (primitive, method, or object reference). /// Note that when we say that "a property holds an object", that is shorthand for "a property holds an object reference". @@ -65,7 +67,7 @@ pub enum PropertyDefinition { /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#Spread_properties SpreadObject(Expression), - /// Cover grammar for when an object literal is used as an object biding pattern. + /// Cover grammar for when an object literal is used as an object binding pattern. /// /// More information: /// - [ECMAScript reference][spec] diff --git a/boa_engine/src/syntax/ast/punctuator.rs b/boa_engine/src/syntax/ast/punctuator.rs index 05e90f5c3a8..f1e952ac4b7 100644 --- a/boa_engine/src/syntax/ast/punctuator.rs +++ b/boa_engine/src/syntax/ast/punctuator.rs @@ -1,4 +1,4 @@ -//! This module implements the `Punctuator`, which represents all punctuators used in JavaScript +//! The `Punctuator` enum, which contains all punctuators used in JavaScript. //! //! More information: //! - [ECMAScript Reference][spec] @@ -6,24 +6,21 @@ //! [spec]: https://tc39.es/ecma262/#prod-Punctuator use crate::syntax::ast::expression::operator::{ - assign::op::AssignOp, - binary::op::{ArithmeticOp, BinaryOp, BitwiseOp, LogicalOp, RelationalOp}, + assign::AssignOp, + binary::{ArithmeticOp, BinaryOp, BitwiseOp, LogicalOp, RelationalOp}, }; use std::{ convert::TryInto, fmt::{Display, Error, Formatter}, }; -#[cfg(feature = "deser")] -use serde::{Deserialize, Serialize}; - -/// The Punctuator enum describes all of the punctuators used in JavaScript. +/// All of the punctuators used in JavaScript. /// /// More information: /// - [ECMAScript Reference][spec] /// /// [spec]: https://tc39.es/ecma262/#prod-Punctuator -#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub enum Punctuator { /// `+` diff --git a/boa_engine/src/syntax/ast/statement/iteration/continue.rs b/boa_engine/src/syntax/ast/statement/iteration/continue.rs index ed5709294f9..61dffe70027 100644 --- a/boa_engine/src/syntax/ast/statement/iteration/continue.rs +++ b/boa_engine/src/syntax/ast/statement/iteration/continue.rs @@ -25,6 +25,7 @@ impl Continue { Self { label } } + /// Gets the label of this `Continue` statement. pub fn label(&self) -> Option { self.label } diff --git a/boa_engine/src/syntax/ast/statement/iteration/for_in_loop.rs b/boa_engine/src/syntax/ast/statement/iteration/for_in_loop.rs index 9b32cbd80d8..1a1bf84a5cf 100644 --- a/boa_engine/src/syntax/ast/statement/iteration/for_in_loop.rs +++ b/boa_engine/src/syntax/ast/statement/iteration/for_in_loop.rs @@ -5,6 +5,13 @@ use crate::syntax::ast::{ }; use boa_interner::{Interner, ToIndentedString, ToInternedString}; +/// A `for...in` loop statement, as defined by the [spec]. +/// +/// [`for...in`][forin] statements loop over all enumerable string properties of an object, including +/// inherited properties. +/// +/// [forin]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in +/// [spec]: https://tc39.es/ecma262/#prod-ForInOfStatement #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub struct ForInLoop { diff --git a/boa_engine/src/syntax/ast/statement/iteration/for_loop.rs b/boa_engine/src/syntax/ast/statement/iteration/for_loop.rs index d9ff5b7b7ad..8d7d242fc37 100644 --- a/boa_engine/src/syntax/ast/statement/iteration/for_loop.rs +++ b/boa_engine/src/syntax/ast/statement/iteration/for_loop.rs @@ -8,12 +8,11 @@ use boa_interner::{Interner, ToIndentedString, ToInternedString}; /// The `for` statement creates a loop that consists of three optional expressions. /// -/// A `for` loop repeats until a specified condition evaluates to `false`. +/// A [`for`][mdn] loop repeats until a specified condition evaluates to `false`. /// The JavaScript for loop is similar to the Java and C for loop. /// /// More information: /// - [ECMAScript reference][spec] -/// - [MDN documentation][mdn] /// /// [spec]: https://tc39.es/ecma262/#prod-ForDeclaration /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for @@ -163,11 +162,22 @@ impl InnerForLoop { } } +/// A [`ForLoop`] initializer, as defined by the [spec]. +/// +/// A `ForLoop` initializer differs a lot from an +/// [`IterableLoopInitializer`][super::IterableLoopInitializer], since it can contain any arbitrary +/// expression instead of only accessors and patterns. Additionally, it can also contain many variable +/// declarations instead of only one. +/// +/// [spec]: https://tc39.es/ecma262/#prod-ForStatement #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub enum ForLoopInitializer { + /// An expression initializer. Expression(Expression), + /// A var declaration initializer. Var(VarDeclaration), + /// A lexical declaration initializer. Lexical(LexicalDeclaration), } diff --git a/boa_engine/src/syntax/ast/statement/iteration/for_of_loop.rs b/boa_engine/src/syntax/ast/statement/iteration/for_of_loop.rs index 455ea3f000f..45d4a1c729d 100644 --- a/boa_engine/src/syntax/ast/statement/iteration/for_of_loop.rs +++ b/boa_engine/src/syntax/ast/statement/iteration/for_of_loop.rs @@ -5,10 +5,19 @@ use crate::syntax::ast::{ }; use boa_interner::{Interner, ToIndentedString, ToInternedString}; -#[cfg(feature = "deser")] -use serde::{Deserialize, Serialize}; - -#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))] +/// A `for...of` loop statement, as defined by the [spec]. +/// +/// [`for..of`][forof] statements loop over a sequence of values obtained from an iterable object (Array, +/// String, Map, generators). +/// +/// This type combines `for..of` and [`for await...of`][forawait] statements in a single structure, +/// since `for await...of` is essentially the same statement but with async iterable objects +/// as the source of iteration. +/// +/// [forof]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of +/// [spec]: https://tc39.es/ecma262/#prod-ForInOfStatement +/// [forawait]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of +#[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub struct ForOfLoop { init: IterableLoopInitializer, diff --git a/boa_engine/src/syntax/ast/statement/iteration/mod.rs b/boa_engine/src/syntax/ast/statement/iteration/mod.rs index 4c32e04d127..39da7bd8648 100644 --- a/boa_engine/src/syntax/ast/statement/iteration/mod.rs +++ b/boa_engine/src/syntax/ast/statement/iteration/mod.rs @@ -1,18 +1,23 @@ //! Iteration nodes -pub mod r#break; -pub mod r#continue; -pub mod do_while_loop; -pub mod for_in_loop; -pub mod for_loop; -pub mod for_of_loop; -pub mod while_loop; +mod r#break; +mod r#continue; +mod do_while_loop; +mod for_in_loop; +mod for_loop; +mod for_of_loop; +mod while_loop; use crate::syntax::ast::{declaration::Binding, expression::Identifier, pattern::Pattern}; pub use self::{ - do_while_loop::DoWhileLoop, for_in_loop::ForInLoop, for_loop::ForLoop, for_of_loop::ForOfLoop, - r#break::Break, r#continue::Continue, while_loop::WhileLoop, + do_while_loop::DoWhileLoop, + for_in_loop::ForInLoop, + for_loop::{ForLoop, ForLoopInitializer}, + for_of_loop::ForOfLoop, + r#break::Break, + r#continue::Continue, + while_loop::WhileLoop, }; use boa_interner::{Interner, Sym, ToInternedString}; @@ -21,14 +26,26 @@ use super::ContainsSymbol; #[cfg(test)] mod tests; +/// A `for-in`, `for-of` and `for-await-of` loop initializer. +/// +/// The [spec] specifies only single bindings for the listed types of loops, which makes us +/// unable to use plain `LexicalDeclaration`s or `VarStatement`s as initializers, since those +/// can have more than one binding. +/// +/// [spec]: https://tc39.es/ecma262/#prod-ForInOfStatement #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub enum IterableLoopInitializer { // TODO: This should also accept property accessors + /// An already declared variable. Identifier(Identifier), + /// A new var declaration. Var(Binding), + /// A new let declaration. Let(Binding), + /// A new const declaration. Const(Binding), + /// A pattern with already declared variables. Pattern(Pattern), } diff --git a/boa_engine/src/syntax/ast/statement/labelled.rs b/boa_engine/src/syntax/ast/statement/labelled.rs index 7f8ee21d997..d385e678728 100644 --- a/boa_engine/src/syntax/ast/statement/labelled.rs +++ b/boa_engine/src/syntax/ast/statement/labelled.rs @@ -2,7 +2,7 @@ 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]. +/// The set of Parse Nodes that can be preceded by a label, as defined by the [spec]. /// /// Semantically, a [`Labelled`] statement should only wrap [`Statement`] nodes. However, /// old ECMAScript implementations supported [labelled function declarations][label-fn] as an extension @@ -14,7 +14,9 @@ use boa_interner::{Interner, Sym, ToIndentedString, ToInternedString}; #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub enum LabelledItem { + /// A labelled [`Function`]. Function(Function), + /// A labelled [`Statement`]. Statement(Statement), } diff --git a/boa_engine/src/syntax/ast/statement/mod.rs b/boa_engine/src/syntax/ast/statement/mod.rs index 2b598f5a1d0..3c44c35adc0 100644 --- a/boa_engine/src/syntax/ast/statement/mod.rs +++ b/boa_engine/src/syntax/ast/statement/mod.rs @@ -1,16 +1,23 @@ -//! This module implements the `Statement` node. +//! The [`Statement`] Parse Node, as defined by the [spec]. +//! +//! Javascript [statements] are mainly composed of control flow operations, such as [`If`], +//! [`WhileLoop`], and [`Break`]. However, it also contains statements such as [`VarDeclaration`], +//! [`Block`] or [`Expression`] which are not strictly used for control flow. +//! +//! [spec]: https://tc39.es/ecma262/#prod-Statement +//! [statements]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements mod block; mod r#if; mod labelled; mod r#return; +mod switch; mod throw; +mod r#try; pub mod iteration; -pub mod switch; -pub mod r#try; -use self::iteration::{for_loop::ForLoopInitializer, IterableLoopInitializer}; +use self::iteration::{ForLoopInitializer, IterableLoopInitializer}; pub use self::{ block::Block, iteration::{Break, Continue, DoWhileLoop, ForInLoop, ForLoop, ForOfLoop, WhileLoop}, @@ -32,6 +39,9 @@ use super::{ ContainsSymbol, }; +/// The `Statement` Parse Node. +/// +/// See the [module level documentation][self] for more information. #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub enum Statement { @@ -41,9 +51,9 @@ pub enum Statement { /// See [`VarDeclaration`] Var(VarDeclaration), - /// A empty node. + /// An empty statement. /// - /// Empty statement do nothing, just return undefined. + /// Empty statements do nothing, just return undefined. /// /// More information: /// - [ECMAScript reference][spec] diff --git a/boa_engine/src/syntax/ast/statement/return.rs b/boa_engine/src/syntax/ast/statement/return.rs index 4254076c3b9..8a99661a272 100644 --- a/boa_engine/src/syntax/ast/statement/return.rs +++ b/boa_engine/src/syntax/ast/statement/return.rs @@ -7,8 +7,7 @@ use boa_interner::{Interner, ToInternedString}; /// Syntax: `return [expression];` /// /// `expression`: -/// > The expression whose value is to be returned. If omitted, `undefined` is returned -/// > instead. +/// > The expression whose value is to be returned. If omitted, `undefined` is returned instead. /// /// When a `return` statement is used in a function body, the execution of the function is /// stopped. If specified, a given value is returned to the function caller. @@ -26,6 +25,7 @@ pub struct Return { } impl Return { + /// Gets the expression value of this `Return` statement. pub fn expr(&self) -> Option<&Expression> { self.expr.as_ref() } diff --git a/boa_engine/src/syntax/ast/statement/switch/mod.rs b/boa_engine/src/syntax/ast/statement/switch/mod.rs index 564960d1970..4bda0249d5c 100644 --- a/boa_engine/src/syntax/ast/statement/switch/mod.rs +++ b/boa_engine/src/syntax/ast/statement/switch/mod.rs @@ -8,6 +8,14 @@ use super::ContainsSymbol; #[cfg(test)] mod tests; +/// A case clause inside a [`Switch`] statement, as defined by the [spec]. +/// +/// Even though every [`Case`] body is a [`StatementList`], it doesn't create a new lexical +/// environment. This means any variable declared in a `Case` will be considered as part of the +/// lexical environment of the parent [`Switch`] block. +/// +/// [spec]: https://tc39.es/ecma262/#prod-CaseClause +/// [truthy]: https://developer.mozilla.org/en-US/docs/Glossary/Truthy #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub struct Case { diff --git a/boa_engine/src/syntax/ast/statement/throw.rs b/boa_engine/src/syntax/ast/statement/throw.rs index 7020e143498..42e826baf8b 100644 --- a/boa_engine/src/syntax/ast/statement/throw.rs +++ b/boa_engine/src/syntax/ast/statement/throw.rs @@ -22,6 +22,7 @@ pub struct Throw { } impl Throw { + /// Gets the expression value of this `Throw` statement. pub fn expr(&self) -> &Expression { &self.expression } diff --git a/boa_engine/src/syntax/ast/statement/try/mod.rs b/boa_engine/src/syntax/ast/statement/try/mod.rs index bfbf0f4d579..503f9c71df8 100644 --- a/boa_engine/src/syntax/ast/statement/try/mod.rs +++ b/boa_engine/src/syntax/ast/statement/try/mod.rs @@ -1,7 +1,9 @@ +//! Error handling statements + use crate::syntax::ast::{ declaration::Binding, statement::{Block, Statement}, - statement_list::StatementListItem, + StatementListItem, }; use boa_interner::{Interner, ToIndentedString, ToInternedString}; diff --git a/boa_engine/src/syntax/ast/statement_list/mod.rs b/boa_engine/src/syntax/ast/statement_list/mod.rs index b52bae52565..f9f0f5297c7 100644 --- a/boa_engine/src/syntax/ast/statement_list/mod.rs +++ b/boa_engine/src/syntax/ast/statement_list/mod.rs @@ -9,10 +9,18 @@ use std::cmp::Ordering; #[cfg(test)] mod tests; +/// An item inside a [`StatementList`] Parse Node, as defined by the [spec]. +/// +/// Items in a `StatementList` can be either [`Declaration`]s (functions, classes, let/const declarations) +/// or [`Statement`]s (if, while, var statement). +/// +/// [spec]: https://tc39.es/ecma262/#prod-StatementListItem #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub enum StatementListItem { + /// See [`Statement`]. Statement(Statement), + /// See [`Declaration`]. Declaration(Declaration), } diff --git a/boa_engine/src/syntax/parser/error.rs b/boa_engine/src/syntax/parser/error.rs index 2a42aa3e13a..4f375dcdd12 100644 --- a/boa_engine/src/syntax/parser/error.rs +++ b/boa_engine/src/syntax/parser/error.rs @@ -1,8 +1,9 @@ //! Error and result implementation for the parser. -use crate::syntax::ast::position::Position; -use crate::syntax::ast::Span; -use crate::syntax::lexer::Error as LexError; +use crate::syntax::{ + ast::{Position, Span}, + lexer::Error as LexError, +}; use std::fmt; /// Result of a parsing operation. diff --git a/boa_engine/src/syntax/parser/expression/assignment/conditional.rs b/boa_engine/src/syntax/parser/expression/assignment/conditional.rs index 5fc9316b317..eff99da0b03 100644 --- a/boa_engine/src/syntax/parser/expression/assignment/conditional.rs +++ b/boa_engine/src/syntax/parser/expression/assignment/conditional.rs @@ -9,7 +9,7 @@ use crate::syntax::{ ast::{ - expression::{operator::conditional::Conditional, Identifier}, + expression::{operator::Conditional, Identifier}, Expression, Punctuator, }, lexer::TokenKind, diff --git a/boa_engine/src/syntax/parser/expression/assignment/exponentiation.rs b/boa_engine/src/syntax/parser/expression/assignment/exponentiation.rs index 8ef936a5c11..62384234285 100644 --- a/boa_engine/src/syntax/parser/expression/assignment/exponentiation.rs +++ b/boa_engine/src/syntax/parser/expression/assignment/exponentiation.rs @@ -11,7 +11,7 @@ use super::ParseError; use crate::syntax::{ ast::{ expression::{ - operator::{binary::op::ArithmeticOp, Binary}, + operator::{binary::ArithmeticOp, Binary}, Identifier, }, Expression, Keyword, Punctuator, diff --git a/boa_engine/src/syntax/parser/expression/assignment/mod.rs b/boa_engine/src/syntax/parser/expression/assignment/mod.rs index c4dfe9c836f..71e7fc51f27 100644 --- a/boa_engine/src/syntax/parser/expression/assignment/mod.rs +++ b/boa_engine/src/syntax/parser/expression/assignment/mod.rs @@ -16,7 +16,7 @@ use crate::syntax::{ ast::{ self, expression::{ - operator::assign::{op::AssignOp, Assign, AssignTarget}, + operator::assign::{Assign, AssignOp, AssignTarget}, Identifier, }, Expression, Keyword, Punctuator, diff --git a/boa_engine/src/syntax/parser/expression/mod.rs b/boa_engine/src/syntax/parser/expression/mod.rs index 4a32573f130..fbd3475d88a 100644 --- a/boa_engine/src/syntax/parser/expression/mod.rs +++ b/boa_engine/src/syntax/parser/expression/mod.rs @@ -24,7 +24,7 @@ use crate::syntax::{ self, expression::{ operator::{ - binary::op::{BinaryOp, LogicalOp}, + binary::{BinaryOp, LogicalOp}, Binary, }, Identifier, diff --git a/boa_engine/src/syntax/parser/expression/primary/async_function_expression/tests.rs b/boa_engine/src/syntax/parser/expression/primary/async_function_expression/tests.rs index 8d6f92df67f..069d803ea86 100644 --- a/boa_engine/src/syntax/parser/expression/primary/async_function_expression/tests.rs +++ b/boa_engine/src/syntax/parser/expression/primary/async_function_expression/tests.rs @@ -4,8 +4,7 @@ use crate::syntax::{ expression::literal::Literal, function::{AsyncFunction, FormalParameterList}, statement::Return, - statement_list::StatementListItem, - Statement, + Statement, StatementListItem, }, parser::tests::check_parser, }; diff --git a/boa_engine/src/syntax/parser/expression/primary/async_generator_expression/tests.rs b/boa_engine/src/syntax/parser/expression/primary/async_generator_expression/tests.rs index d66e1e7048b..57c3a17de21 100644 --- a/boa_engine/src/syntax/parser/expression/primary/async_generator_expression/tests.rs +++ b/boa_engine/src/syntax/parser/expression/primary/async_generator_expression/tests.rs @@ -6,8 +6,7 @@ use crate::syntax::{ expression::literal::Literal, function::{AsyncGenerator, FormalParameterList}, statement::Return, - statement_list::StatementListItem, - Declaration, Statement, + Declaration, Statement, StatementListItem, }, parser::tests::check_parser, }; diff --git a/boa_engine/src/syntax/parser/expression/primary/function_expression/tests.rs b/boa_engine/src/syntax/parser/expression/primary/function_expression/tests.rs index 5ccacc1bf8b..1f273b75e48 100644 --- a/boa_engine/src/syntax/parser/expression/primary/function_expression/tests.rs +++ b/boa_engine/src/syntax/parser/expression/primary/function_expression/tests.rs @@ -4,8 +4,7 @@ use crate::syntax::{ expression::literal::Literal, function::{FormalParameterList, Function}, statement::Return, - statement_list::StatementListItem, - Declaration, Statement, + Declaration, Statement, StatementListItem, }, parser::tests::check_parser, }; diff --git a/boa_engine/src/syntax/parser/expression/primary/generator_expression/tests.rs b/boa_engine/src/syntax/parser/expression/primary/generator_expression/tests.rs index 257ed070e5a..2fb521e60ef 100644 --- a/boa_engine/src/syntax/parser/expression/primary/generator_expression/tests.rs +++ b/boa_engine/src/syntax/parser/expression/primary/generator_expression/tests.rs @@ -3,8 +3,7 @@ use crate::syntax::{ declaration::{LexicalDeclaration, Variable}, expression::{literal::Literal, Yield}, function::{FormalParameterList, Generator}, - statement_list::StatementListItem, - Declaration, Expression, Statement, + Declaration, Expression, Statement, StatementListItem, }, parser::tests::check_parser, }; diff --git a/boa_engine/src/syntax/parser/expression/primary/mod.rs b/boa_engine/src/syntax/parser/expression/primary/mod.rs index c3a93677c63..843726386fc 100644 --- a/boa_engine/src/syntax/parser/expression/primary/mod.rs +++ b/boa_engine/src/syntax/parser/expression/primary/mod.rs @@ -37,12 +37,12 @@ use crate::syntax::{ array_decl_to_declaration_pattern, object_decl_to_declaration_pattern, AssignTarget, }, - binary::op::BinaryOp, + binary::BinaryOp, }, Call, Identifier, New, }, function::{FormalParameter, FormalParameterList}, - pattern::{Pattern, PatternArrayElement, PatternObjectElement}, + pattern::{ArrayPatternElement, ObjectPatternElement, Pattern}, Keyword, Punctuator, Span, }, lexer::{token::Numeric, InputElement, Token, TokenKind}, @@ -319,8 +319,8 @@ where #[derive(Debug)] enum InnerExpression { Expression(ast::Expression), - SpreadObject(Vec), - SpreadArray(Vec), + SpreadObject(Vec), + SpreadArray(Vec), SpreadBinding(Identifier), } diff --git a/boa_engine/src/syntax/parser/expression/tests.rs b/boa_engine/src/syntax/parser/expression/tests.rs index 8f6b9f3eff5..3356624ef06 100644 --- a/boa_engine/src/syntax/parser/expression/tests.rs +++ b/boa_engine/src/syntax/parser/expression/tests.rs @@ -4,8 +4,8 @@ use crate::syntax::{ expression::{ literal::Literal, operator::{ - assign::op::AssignOp, - binary::op::{ArithmeticOp, BitwiseOp, LogicalOp, RelationalOp}, + assign::AssignOp, + binary::{ArithmeticOp, BitwiseOp, LogicalOp, RelationalOp}, Assign, Binary, }, Call, Identifier, New, diff --git a/boa_engine/src/syntax/parser/expression/unary.rs b/boa_engine/src/syntax/parser/expression/unary.rs index 9c4590b8d2c..8d454b04523 100644 --- a/boa_engine/src/syntax/parser/expression/unary.rs +++ b/boa_engine/src/syntax/parser/expression/unary.rs @@ -10,7 +10,7 @@ use crate::syntax::{ ast::{ expression::{ - operator::{unary::op::UnaryOp, Unary}, + operator::{unary::UnaryOp, Unary}, Identifier, }, Expression, Keyword, Punctuator, diff --git a/boa_engine/src/syntax/parser/expression/update.rs b/boa_engine/src/syntax/parser/expression/update.rs index ee36510a9dd..bd0af16cd84 100644 --- a/boa_engine/src/syntax/parser/expression/update.rs +++ b/boa_engine/src/syntax/parser/expression/update.rs @@ -9,7 +9,7 @@ use super::left_hand_side::LeftHandSideExpression; use crate::syntax::{ ast::{ expression::{ - operator::{unary::op::UnaryOp, Unary}, + operator::{unary::UnaryOp, Unary}, Identifier, }, Expression, Punctuator, diff --git a/boa_engine/src/syntax/parser/function/tests.rs b/boa_engine/src/syntax/parser/function/tests.rs index c8563babd7f..867abe974c1 100644 --- a/boa_engine/src/syntax/parser/function/tests.rs +++ b/boa_engine/src/syntax/parser/function/tests.rs @@ -4,7 +4,7 @@ use crate::{ ast::{ declaration::{LexicalDeclaration, Variable}, expression::{ - operator::{binary::op::ArithmeticOp, Binary}, + operator::{binary::ArithmeticOp, Binary}, Identifier, }, function::{ @@ -12,8 +12,7 @@ use crate::{ Function, }, statement::Return, - statement_list::StatementListItem, - Declaration, Expression, Statement, StatementList, + Declaration, Expression, Statement, StatementList, StatementListItem, }, parser::tests::check_parser, Parser, diff --git a/boa_engine/src/syntax/parser/statement/block/tests.rs b/boa_engine/src/syntax/parser/statement/block/tests.rs index c097db178d0..e38fa4f90e7 100644 --- a/boa_engine/src/syntax/parser/statement/block/tests.rs +++ b/boa_engine/src/syntax/parser/statement/block/tests.rs @@ -7,13 +7,12 @@ use crate::syntax::{ declaration::{VarDeclaration, Variable}, expression::{ literal::Literal, - operator::{assign::op::AssignOp, unary::op::UnaryOp, Assign, Unary}, + operator::{assign::AssignOp, unary::UnaryOp, Assign, Unary}, Call, Identifier, }, function::{FormalParameterList, Function}, statement::{Block, Return}, - statement_list::StatementListItem, - Declaration, Expression, Statement, + Declaration, Expression, Statement, StatementListItem, }, parser::tests::check_parser, }; diff --git a/boa_engine/src/syntax/parser/statement/break_stm/tests.rs b/boa_engine/src/syntax/parser/statement/break_stm/tests.rs index e03aa7ed6e1..824648a82b1 100644 --- a/boa_engine/src/syntax/parser/statement/break_stm/tests.rs +++ b/boa_engine/src/syntax/parser/statement/break_stm/tests.rs @@ -2,8 +2,7 @@ use crate::syntax::{ ast::{ expression::literal::Literal, statement::{Block, Break, WhileLoop}, - statement_list::StatementListItem, - Statement, + Statement, StatementListItem, }, parser::tests::check_parser, }; diff --git a/boa_engine/src/syntax/parser/statement/continue_stm/tests.rs b/boa_engine/src/syntax/parser/statement/continue_stm/tests.rs index 9bf64ff18cb..7f83ae3e079 100644 --- a/boa_engine/src/syntax/parser/statement/continue_stm/tests.rs +++ b/boa_engine/src/syntax/parser/statement/continue_stm/tests.rs @@ -2,8 +2,7 @@ use crate::syntax::{ ast::{ expression::literal::Literal, statement::{Block, Continue, WhileLoop}, - statement_list::StatementListItem, - Statement, + Statement, StatementListItem, }, parser::tests::check_parser, }; diff --git a/boa_engine/src/syntax/parser/statement/if_stm/mod.rs b/boa_engine/src/syntax/parser/statement/if_stm/mod.rs index c8b4c7b9227..79a56b92149 100644 --- a/boa_engine/src/syntax/parser/statement/if_stm/mod.rs +++ b/boa_engine/src/syntax/parser/statement/if_stm/mod.rs @@ -4,8 +4,7 @@ mod tests; use crate::syntax::{ ast::{ statement::{Block, If}, - statement_list::StatementListItem, - Declaration, Keyword, Punctuator, + Declaration, Keyword, Punctuator, StatementListItem, }, lexer::TokenKind, parser::{ diff --git a/boa_engine/src/syntax/parser/statement/iteration/for_statement.rs b/boa_engine/src/syntax/parser/statement/iteration/for_statement.rs index 86de3fd56e2..ea0d4e9dda9 100644 --- a/boa_engine/src/syntax/parser/statement/iteration/for_statement.rs +++ b/boa_engine/src/syntax/parser/statement/iteration/for_statement.rs @@ -14,7 +14,7 @@ use crate::syntax::{ array_decl_to_declaration_pattern, object_decl_to_declaration_pattern, }, statement::{ - iteration::{for_loop::ForLoopInitializer, IterableLoopInitializer}, + iteration::{ForLoopInitializer, IterableLoopInitializer}, ForInLoop, ForLoop, ForOfLoop, }, Keyword, Position, Punctuator, diff --git a/boa_engine/src/syntax/parser/statement/iteration/tests.rs b/boa_engine/src/syntax/parser/statement/iteration/tests.rs index 28d5fd8aeb9..efbf6481750 100644 --- a/boa_engine/src/syntax/parser/statement/iteration/tests.rs +++ b/boa_engine/src/syntax/parser/statement/iteration/tests.rs @@ -5,14 +5,12 @@ use crate::syntax::{ access::PropertyAccess, literal::Literal, operator::{ - assign::op::AssignOp, binary::op::RelationalOp, unary::op::UnaryOp, Assign, Binary, - Unary, + assign::AssignOp, binary::RelationalOp, unary::UnaryOp, Assign, Binary, Unary, }, Call, Identifier, }, statement::{Block, Break, DoWhileLoop, WhileLoop}, - statement_list::StatementListItem, - Expression, Statement, + Expression, Statement, StatementListItem, }, parser::tests::{check_invalid, check_parser}, }; diff --git a/boa_engine/src/syntax/parser/statement/mod.rs b/boa_engine/src/syntax/parser/statement/mod.rs index 5ef647ef76a..846116b625b 100644 --- a/boa_engine/src/syntax/parser/statement/mod.rs +++ b/boa_engine/src/syntax/parser/statement/mod.rs @@ -43,7 +43,7 @@ use super::{ use crate::syntax::{ ast::{ self, - pattern::{PatternArray, PatternArrayElement, PatternObjectElement}, + pattern::{ArrayPattern, ArrayPatternElement, ObjectPatternElement}, Keyword, Punctuator, }, lexer::{Error as LexError, InputElement, Token, TokenKind}, @@ -51,7 +51,7 @@ use crate::syntax::{ }; use boa_interner::Interner; use boa_profiler::Profiler; -use std::{io::Read, vec}; +use std::io::Read; pub(in crate::syntax::parser) use declaration::ClassTail; pub(in crate::syntax) use declaration::PrivateElement; @@ -394,7 +394,7 @@ impl TokenParser for ObjectBindingPattern where R: Read, { - type Output = Vec; + type Output = Vec; fn parse(self, cursor: &mut Cursor, interner: &mut Interner) -> ParseResult { let _timer = Profiler::global().start_event("ObjectBindingPattern", "Parsing"); @@ -407,7 +407,6 @@ where let mut patterns = Vec::new(); let mut property_names = Vec::new(); - let mut rest_property_name = None; loop { let next_token_is_colon = *cursor @@ -423,7 +422,7 @@ where "object binding pattern", interner, )?; - break; + return Ok(patterns); } TokenKind::Punctuator(Punctuator::Spread) => { cursor.expect( @@ -431,16 +430,18 @@ where "object binding pattern", interner, )?; - rest_property_name = Some( - BindingIdentifier::new(self.allow_yield, self.allow_await) - .parse(cursor, interner)?, - ); + let ident = BindingIdentifier::new(self.allow_yield, self.allow_await) + .parse(cursor, interner)?; cursor.expect( TokenKind::Punctuator(Punctuator::CloseBlock), "object binding pattern", interner, )?; - break; + patterns.push(ObjectPatternElement::RestProperty { + ident, + excluded_keys: property_names, + }); + return Ok(patterns); } _ => { let is_property_name = match token.kind() { @@ -479,14 +480,14 @@ where self.allow_await, ) .parse(cursor, interner)?; - patterns.push(PatternObjectElement::Pattern { + patterns.push(ObjectPatternElement::Pattern { name: property_name, pattern: bindings.into(), default_init: Some(init), }); } _ => { - patterns.push(PatternObjectElement::Pattern { + patterns.push(ObjectPatternElement::Pattern { name: property_name, pattern: bindings.into(), default_init: None, @@ -512,17 +513,17 @@ where self.allow_await, ) .parse(cursor, interner)?; - patterns.push(PatternObjectElement::Pattern { + patterns.push(ObjectPatternElement::Pattern { name: property_name, - pattern: PatternArray::new(bindings.into()) + pattern: ArrayPattern::new(bindings.into()) .into(), default_init: Some(init), }); } _ => { - patterns.push(PatternObjectElement::Pattern { + patterns.push(ObjectPatternElement::Pattern { name: property_name, - pattern: PatternArray::new(bindings.into()) + pattern: ArrayPattern::new(bindings.into()) .into(), default_init: None, }); @@ -547,14 +548,14 @@ where self.allow_await, ) .parse(cursor, interner)?; - patterns.push(PatternObjectElement::SingleName { + patterns.push(ObjectPatternElement::SingleName { ident, name: property_name, default_init: Some(init), }); } _ => { - patterns.push(PatternObjectElement::SingleName { + patterns.push(ObjectPatternElement::SingleName { ident, name: property_name, default_init: None, @@ -578,14 +579,14 @@ where self.allow_await, ) .parse(cursor, interner)?; - patterns.push(PatternObjectElement::SingleName { + patterns.push(ObjectPatternElement::SingleName { ident: name, name: name.sym().into(), default_init: Some(init), }); } _ => { - patterns.push(PatternObjectElement::SingleName { + patterns.push(ObjectPatternElement::SingleName { ident: name, name: name.sym().into(), default_init: None, @@ -606,25 +607,6 @@ where } } } - - if let Some(rest) = rest_property_name { - if patterns.is_empty() { - Ok(vec![PatternObjectElement::RestProperty { - ident: rest, - excluded_keys: property_names, - }]) - } else { - patterns.push(PatternObjectElement::RestProperty { - ident: rest, - excluded_keys: property_names, - }); - Ok(patterns) - } - } else if patterns.is_empty() { - Ok(vec![PatternObjectElement::Empty]) - } else { - Ok(patterns) - } } } @@ -658,7 +640,7 @@ impl TokenParser for ArrayBindingPattern where R: Read, { - type Output = Vec; + type Output = Vec; fn parse(self, cursor: &mut Cursor, interner: &mut Interner) -> ParseResult { let _timer = Profiler::global().start_event("ArrayBindingPattern", "Parsing"); @@ -684,7 +666,7 @@ where "array binding pattern", interner, )?; - break; + return Ok(patterns); } TokenKind::Punctuator(Punctuator::Comma) => { cursor.expect( @@ -693,7 +675,7 @@ where interner, )?; if last_elision_or_first { - patterns.push(PatternArrayElement::Elision); + patterns.push(ArrayPatternElement::Elision); } else { last_elision_or_first = true; } @@ -715,14 +697,14 @@ where let bindings = ObjectBindingPattern::new(self.allow_yield, self.allow_await) .parse(cursor, interner)?; - patterns.push(PatternArrayElement::PatternRest { + patterns.push(ArrayPatternElement::PatternRest { pattern: bindings.into(), }); } TokenKind::Punctuator(Punctuator::OpenBracket) => { let bindings = Self::new(self.allow_yield, self.allow_await) .parse(cursor, interner)?; - patterns.push(PatternArrayElement::PatternRest { + patterns.push(ArrayPatternElement::PatternRest { pattern: bindings.into(), }); } @@ -730,7 +712,7 @@ where let rest_property_name = BindingIdentifier::new(self.allow_yield, self.allow_await) .parse(cursor, interner)?; - patterns.push(PatternArrayElement::SingleNameRest { + patterns.push(ArrayPatternElement::SingleNameRest { ident: rest_property_name, }); } @@ -741,7 +723,8 @@ where "array binding pattern", interner, )?; - break; + + return Ok(patterns); } TokenKind::Punctuator(Punctuator::OpenBlock) => { last_elision_or_first = false; @@ -758,13 +741,13 @@ where let default_init = Initializer::new(None, true, self.allow_yield, self.allow_await) .parse(cursor, interner)?; - patterns.push(PatternArrayElement::Pattern { + patterns.push(ArrayPatternElement::Pattern { pattern: bindings.into(), default_init: Some(default_init), }); } _ => { - patterns.push(PatternArrayElement::Pattern { + patterns.push(ArrayPatternElement::Pattern { pattern: bindings.into(), default_init: None, }); @@ -786,13 +769,13 @@ where let default_init = Initializer::new(None, true, self.allow_yield, self.allow_await) .parse(cursor, interner)?; - patterns.push(PatternArrayElement::Pattern { + patterns.push(ArrayPatternElement::Pattern { pattern: bindings.into(), default_init: Some(default_init), }); } _ => { - patterns.push(PatternArrayElement::Pattern { + patterns.push(ArrayPatternElement::Pattern { pattern: bindings.into(), default_init: None, }); @@ -817,13 +800,13 @@ where self.allow_await, ) .parse(cursor, interner)?; - patterns.push(PatternArrayElement::SingleName { + patterns.push(ArrayPatternElement::SingleName { ident, default_init: Some(default_init), }); } _ => { - patterns.push(PatternArrayElement::SingleName { + patterns.push(ArrayPatternElement::SingleName { ident, default_init: None, }); @@ -840,14 +823,12 @@ where interner, )?; if last_elision_or_first { - patterns.push(PatternArrayElement::Elision); + patterns.push(ArrayPatternElement::Elision); } else { last_elision_or_first = true; } } } } - - Ok(patterns) } } diff --git a/boa_engine/src/syntax/parser/statement/try_stm/tests.rs b/boa_engine/src/syntax/parser/statement/try_stm/tests.rs index ee1f2c10f7d..c789ffb126b 100644 --- a/boa_engine/src/syntax/parser/statement/try_stm/tests.rs +++ b/boa_engine/src/syntax/parser/statement/try_stm/tests.rs @@ -4,11 +4,10 @@ use crate::syntax::{ ast::{ declaration::{VarDeclaration, Variable}, expression::{literal::Literal, Identifier}, - pattern::{Pattern, PatternArrayElement, PatternObjectElement}, + pattern::{ArrayPatternElement, ObjectPatternElement, Pattern}, property::PropertyName, statement::{Block, Catch, Finally, Try}, - statement_list::StatementListItem, - Statement, + Statement, StatementListItem, }, parser::tests::{check_invalid, check_parser}, }; @@ -190,12 +189,12 @@ fn check_inline_with_binding_pattern_object() { Some(Catch::new( Some( Pattern::from(vec![ - PatternObjectElement::SingleName { + ObjectPatternElement::SingleName { ident: a.into(), name: PropertyName::Literal(a), default_init: None, }, - PatternObjectElement::SingleName { + ObjectPatternElement::SingleName { ident: interner.get_or_intern_static("c", utf16!("c")).into(), name: PropertyName::Literal( interner.get_or_intern_static("b", utf16!("b")), @@ -224,11 +223,11 @@ fn check_inline_with_binding_pattern_array() { Some(Catch::new( Some( Pattern::from(vec![ - PatternArrayElement::SingleName { + ArrayPatternElement::SingleName { ident: interner.get_or_intern_static("a", utf16!("a")).into(), default_init: None, }, - PatternArrayElement::SingleName { + ArrayPatternElement::SingleName { ident: interner.get_or_intern_static("b", utf16!("b")).into(), default_init: None, }, diff --git a/boa_engine/src/syntax/parser/tests.rs b/boa_engine/src/syntax/parser/tests.rs index 9433c7c7dee..1f92e7fc5c9 100644 --- a/boa_engine/src/syntax/parser/tests.rs +++ b/boa_engine/src/syntax/parser/tests.rs @@ -12,9 +12,9 @@ use crate::{ access::PropertyAccess, literal::{Literal, ObjectLiteral}, operator::{ - assign::op::AssignOp, - binary::op::{ArithmeticOp, BinaryOp, LogicalOp, RelationalOp}, - unary::op::UnaryOp, + assign::AssignOp, + binary::{ArithmeticOp, BinaryOp, LogicalOp, RelationalOp}, + unary::UnaryOp, Assign, Binary, Unary, }, Call, Identifier, New, @@ -24,8 +24,7 @@ use crate::{ }, property::PropertyDefinition, statement::{If, Return}, - statement_list::StatementListItem, - Expression, Statement, StatementList, + Expression, Statement, StatementList, StatementListItem, }, Context, };