Browse Source

Use function name from identifiers in assignment expressions (#1908)

Use function name from identifiers in assignment expressions, when a function expressions does not contain a name.
pull/1919/head
raskad 3 years ago
parent
commit
0027f26d21
  1. 18
      boa_engine/src/syntax/parser/expression/assignment/conditional.rs
  2. 17
      boa_engine/src/syntax/parser/expression/assignment/exponentiation.rs
  3. 9
      boa_engine/src/syntax/parser/expression/assignment/mod.rs
  4. 2
      boa_engine/src/syntax/parser/expression/await_expr.rs
  5. 10
      boa_engine/src/syntax/parser/expression/left_hand_side/member.rs
  6. 11
      boa_engine/src/syntax/parser/expression/left_hand_side/mod.rs
  7. 98
      boa_engine/src/syntax/parser/expression/mod.rs
  8. 21
      boa_engine/src/syntax/parser/expression/primary/async_function_expression/mod.rs
  9. 15
      boa_engine/src/syntax/parser/expression/primary/async_function_expression/tests.rs
  10. 28
      boa_engine/src/syntax/parser/expression/primary/async_generator_expression/mod.rs
  11. 15
      boa_engine/src/syntax/parser/expression/primary/async_generator_expression/tests.rs
  12. 30
      boa_engine/src/syntax/parser/expression/primary/function_expression/mod.rs
  13. 15
      boa_engine/src/syntax/parser/expression/primary/function_expression/tests.rs
  14. 28
      boa_engine/src/syntax/parser/expression/primary/generator_expression/mod.rs
  15. 10
      boa_engine/src/syntax/parser/expression/primary/generator_expression/tests.rs
  16. 19
      boa_engine/src/syntax/parser/expression/primary/mod.rs
  17. 10
      boa_engine/src/syntax/parser/expression/unary.rs
  18. 11
      boa_engine/src/syntax/parser/expression/update.rs

18
boa_engine/src/syntax/parser/expression/assignment/conditional.rs

@ -15,7 +15,7 @@ use crate::syntax::{
AllowAwait, AllowIn, AllowYield, Cursor, ParseResult, TokenParser,
},
};
use boa_interner::Interner;
use boa_interner::{Interner, Sym};
use boa_profiler::Profiler;
use std::io::Read;
@ -29,6 +29,7 @@ use std::io::Read;
/// [spec]: https://tc39.es/ecma262/#prod-ConditionalExpression
#[derive(Debug, Clone, Copy)]
pub(in crate::syntax::parser::expression) struct ConditionalExpression {
name: Option<Sym>,
allow_in: AllowIn,
allow_yield: AllowYield,
allow_await: AllowAwait,
@ -36,17 +37,20 @@ pub(in crate::syntax::parser::expression) struct ConditionalExpression {
impl ConditionalExpression {
/// Creates a new `ConditionalExpression` parser.
pub(in crate::syntax::parser::expression) fn new<I, Y, A>(
pub(in crate::syntax::parser::expression) fn new<N, I, Y, A>(
name: N,
allow_in: I,
allow_yield: Y,
allow_await: A,
) -> Self
where
N: Into<Option<Sym>>,
I: Into<AllowIn>,
Y: Into<AllowYield>,
A: Into<AllowAwait>,
{
Self {
name: name.into(),
allow_in: allow_in.into(),
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
@ -62,9 +66,13 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult {
let _timer = Profiler::global().start_event("ConditionalExpression", "Parsing");
let lhs = ShortCircuitExpression::new(self.allow_in, self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
let lhs = ShortCircuitExpression::new(
self.name,
self.allow_in,
self.allow_yield,
self.allow_await,
)
.parse(cursor, interner)?;
if let Some(tok) = cursor.peek(0, interner)? {
if tok.kind() == &TokenKind::Punctuator(Punctuator::Question) {

17
boa_engine/src/syntax/parser/expression/assignment/exponentiation.rs

@ -20,7 +20,7 @@ use crate::syntax::{
AllowAwait, AllowYield, Cursor, ParseResult, TokenParser,
},
};
use boa_interner::Interner;
use boa_interner::{Interner, Sym};
use boa_profiler::Profiler;
use std::io::Read;
@ -34,18 +34,25 @@ use std::io::Read;
/// [spec]: https://tc39.es/ecma262/#prod-ExponentiationExpression
#[derive(Debug, Clone, Copy)]
pub(in crate::syntax::parser::expression) struct ExponentiationExpression {
name: Option<Sym>,
allow_yield: AllowYield,
allow_await: AllowAwait,
}
impl ExponentiationExpression {
/// Creates a new `ExponentiationExpression` parser.
pub(in crate::syntax::parser::expression) fn new<Y, A>(allow_yield: Y, allow_await: A) -> Self
pub(in crate::syntax::parser::expression) fn new<N, Y, A>(
name: N,
allow_yield: Y,
allow_await: A,
) -> Self
where
N: Into<Option<Sym>>,
Y: Into<AllowYield>,
A: Into<AllowAwait>,
{
Self {
name: name.into(),
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
}
@ -83,12 +90,12 @@ where
let _timer = Profiler::global().start_event("ExponentiationExpression", "Parsing");
if is_unary_expression(cursor, interner)? {
return UnaryExpression::new(self.allow_yield, self.allow_await)
return UnaryExpression::new(self.name, self.allow_yield, self.allow_await)
.parse(cursor, interner);
}
let lhs =
UpdateExpression::new(self.allow_yield, self.allow_await).parse(cursor, interner)?;
let lhs = UpdateExpression::new(self.name, self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
if let Some(tok) = cursor.peek(0, interner)? {
if let TokenKind::Punctuator(Punctuator::Exp) = tok.kind() {
cursor.next(interner)?.expect("** token vanished"); // Consume the token.

9
boa_engine/src/syntax/parser/expression/assignment/mod.rs

@ -194,8 +194,13 @@ where
cursor.set_goal(InputElement::Div);
let mut lhs = ConditionalExpression::new(self.allow_in, self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
let mut lhs = ConditionalExpression::new(
self.name,
self.allow_in,
self.allow_yield,
self.allow_await,
)
.parse(cursor, interner)?;
// Review if we are trying to assign to an invalid left hand side expression.
// TODO: can we avoid cloning?

2
boa_engine/src/syntax/parser/expression/await_expr.rs

@ -57,7 +57,7 @@ where
"Await expression parsing",
interner,
)?;
let expr = UnaryExpression::new(self.allow_yield, true).parse(cursor, interner)?;
let expr = UnaryExpression::new(None, self.allow_yield, true).parse(cursor, interner)?;
Ok(expr.into())
}
}

10
boa_engine/src/syntax/parser/expression/left_hand_side/member.rs

@ -22,7 +22,7 @@ use crate::syntax::{
AllowAwait, AllowYield, Cursor, ParseError, ParseResult, TokenParser,
},
};
use boa_interner::Interner;
use boa_interner::{Interner, Sym};
use boa_profiler::Profiler;
use std::io::Read;
@ -34,18 +34,21 @@ use std::io::Read;
/// [spec]: https://tc39.es/ecma262/#prod-MemberExpression
#[derive(Debug, Clone, Copy)]
pub(super) struct MemberExpression {
name: Option<Sym>,
allow_yield: AllowYield,
allow_await: AllowAwait,
}
impl MemberExpression {
/// Creates a new `MemberExpression` parser.
pub(super) fn new<Y, A>(allow_yield: Y, allow_await: A) -> Self
pub(super) fn new<N, Y, A>(name: N, allow_yield: Y, allow_await: A) -> Self
where
N: Into<Option<Sym>>,
Y: Into<AllowYield>,
A: Into<AllowAwait>,
{
Self {
name: name.into(),
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
}
@ -79,7 +82,8 @@ where
Node::from(New::from(call_node))
} else {
PrimaryExpression::new(self.allow_yield, self.allow_await).parse(cursor, interner)?
PrimaryExpression::new(self.name, self.allow_yield, self.allow_await)
.parse(cursor, interner)?
};
while let Some(tok) = cursor.peek(0, interner)? {
match tok.kind() {

11
boa_engine/src/syntax/parser/expression/left_hand_side/mod.rs

@ -18,7 +18,7 @@ use crate::syntax::{
lexer::{InputElement, TokenKind},
parser::{AllowAwait, AllowYield, Cursor, ParseResult, TokenParser},
};
use boa_interner::Interner;
use boa_interner::{Interner, Sym};
use boa_profiler::Profiler;
use std::io::Read;
@ -32,18 +32,21 @@ use std::io::Read;
/// [spec]: https://tc39.es/ecma262/#prod-LeftHandSideExpression
#[derive(Debug, Clone, Copy)]
pub(super) struct LeftHandSideExpression {
name: Option<Sym>,
allow_yield: AllowYield,
allow_await: AllowAwait,
}
impl LeftHandSideExpression {
/// Creates a new `LeftHandSideExpression` parser.
pub(super) fn new<Y, A>(allow_yield: Y, allow_await: A) -> Self
pub(super) fn new<N, Y, A>(name: N, allow_yield: Y, allow_await: A) -> Self
where
N: Into<Option<Sym>>,
Y: Into<AllowYield>,
A: Into<AllowAwait>,
{
Self {
name: name.into(),
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
}
@ -62,8 +65,8 @@ where
cursor.set_goal(InputElement::TemplateTail);
// TODO: Implement NewExpression: new MemberExpression
let lhs =
MemberExpression::new(self.allow_yield, self.allow_await).parse(cursor, interner)?;
let lhs = MemberExpression::new(self.name, self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
if let Some(tok) = cursor.peek(0, interner)? {
if tok.kind() == &TokenKind::Punctuator(Punctuator::OpenParen) {
return CallExpression::new(self.allow_yield, self.allow_await, lhs)

98
boa_engine/src/syntax/parser/expression/mod.rs

@ -73,7 +73,7 @@ macro_rules! expression { ($name:ident, $lower:ident, [$( $op:path ),*], [$( $lo
{
type Output = Node;
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner)-> ParseResult {
fn parse(mut self, cursor: &mut Cursor<R>, interner: &mut Interner)-> ParseResult {
let _timer = Profiler::global().start_event(stringify!($name), "Parsing");
if $goal.is_some() {
@ -81,6 +81,7 @@ macro_rules! expression { ($name:ident, $lower:ident, [$( $op:path ),*], [$( $lo
}
let mut lhs = $lower::new($( self.$low_param ),*).parse(cursor, interner)?;
self.name = None;
while let Some(tok) = cursor.peek(0, interner)? {
match *tok.kind() {
TokenKind::Punctuator(op) if $( op == $op )||* => {
@ -160,6 +161,7 @@ expression!(
/// [spec]: https://tc39.es/ecma262/#prod-ShortCircuitExpression
#[derive(Debug, Clone, Copy)]
struct ShortCircuitExpression {
name: Option<Sym>,
allow_in: AllowIn,
allow_yield: AllowYield,
allow_await: AllowAwait,
@ -175,13 +177,15 @@ enum PreviousExpr {
impl ShortCircuitExpression {
/// Creates a new `ShortCircuitExpression` parser.
pub(super) fn new<I, Y, A>(allow_in: I, allow_yield: Y, allow_await: A) -> Self
pub(super) fn new<N, I, Y, A>(name: N, allow_in: I, allow_yield: Y, allow_await: A) -> Self
where
N: Into<Option<Sym>>,
I: Into<AllowIn>,
Y: Into<AllowYield>,
A: Into<AllowAwait>,
{
Self {
name: name.into(),
allow_in: allow_in.into(),
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
@ -189,18 +193,21 @@ impl ShortCircuitExpression {
}
}
fn with_previous<I, Y, A>(
fn with_previous<N, I, Y, A>(
name: N,
allow_in: I,
allow_yield: Y,
allow_await: A,
previous: PreviousExpr,
) -> Self
where
N: Into<Option<Sym>>,
I: Into<AllowIn>,
Y: Into<AllowYield>,
A: Into<AllowAwait>,
{
Self {
name: name.into(),
allow_in: allow_in.into(),
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
@ -219,7 +226,7 @@ where
let _timer = Profiler::global().start_event("ShortCircuitExpression", "Parsing");
let mut current_node =
BitwiseORExpression::new(self.allow_in, self.allow_yield, self.allow_await)
BitwiseORExpression::new(self.name, self.allow_in, self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
let mut previous = self.previous;
@ -235,9 +242,13 @@ where
}
let _next = cursor.next(interner)?.expect("'&&' expected");
previous = PreviousExpr::Logical;
let rhs =
BitwiseORExpression::new(self.allow_in, self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
let rhs = BitwiseORExpression::new(
self.name,
self.allow_in,
self.allow_yield,
self.allow_await,
)
.parse(cursor, interner)?;
current_node = BinOp::new(LogOp::And, current_node, rhs).into();
}
@ -252,6 +263,7 @@ where
let _next = cursor.next(interner)?.expect("'||' expected");
previous = PreviousExpr::Logical;
let rhs = Self::with_previous(
self.name,
self.allow_in,
self.allow_yield,
self.allow_await,
@ -271,9 +283,13 @@ where
}
let _next = cursor.next(interner)?.expect("'??' expected");
previous = PreviousExpr::Coalesce;
let rhs =
BitwiseORExpression::new(self.allow_in, self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
let rhs = BitwiseORExpression::new(
self.name,
self.allow_in,
self.allow_yield,
self.allow_await,
)
.parse(cursor, interner)?;
current_node = BinOp::new(LogOp::Coalesce, current_node, rhs).into();
}
_ => break,
@ -293,6 +309,7 @@ where
/// [spec]: https://tc39.es/ecma262/#prod-BitwiseORExpression
#[derive(Debug, Clone, Copy)]
struct BitwiseORExpression {
name: Option<Sym>,
allow_in: AllowIn,
allow_yield: AllowYield,
allow_await: AllowAwait,
@ -300,13 +317,15 @@ struct BitwiseORExpression {
impl BitwiseORExpression {
/// Creates a new `BitwiseORExpression` parser.
pub(super) fn new<I, Y, A>(allow_in: I, allow_yield: Y, allow_await: A) -> Self
pub(super) fn new<N, I, Y, A>(name: N, allow_in: I, allow_yield: Y, allow_await: A) -> Self
where
N: Into<Option<Sym>>,
I: Into<AllowIn>,
Y: Into<AllowYield>,
A: Into<AllowAwait>,
{
Self {
name: name.into(),
allow_in: allow_in.into(),
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
@ -318,7 +337,7 @@ expression!(
BitwiseORExpression,
BitwiseXORExpression,
[Punctuator::Or],
[allow_in, allow_yield, allow_await],
[name, allow_in, allow_yield, allow_await],
None::<InputElement>
);
@ -332,6 +351,7 @@ expression!(
/// [spec]: https://tc39.es/ecma262/#prod-BitwiseXORExpression
#[derive(Debug, Clone, Copy)]
struct BitwiseXORExpression {
name: Option<Sym>,
allow_in: AllowIn,
allow_yield: AllowYield,
allow_await: AllowAwait,
@ -339,13 +359,15 @@ struct BitwiseXORExpression {
impl BitwiseXORExpression {
/// Creates a new `BitwiseXORExpression` parser.
pub(super) fn new<I, Y, A>(allow_in: I, allow_yield: Y, allow_await: A) -> Self
pub(super) fn new<N, I, Y, A>(name: N, allow_in: I, allow_yield: Y, allow_await: A) -> Self
where
N: Into<Option<Sym>>,
I: Into<AllowIn>,
Y: Into<AllowYield>,
A: Into<AllowAwait>,
{
Self {
name: name.into(),
allow_in: allow_in.into(),
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
@ -357,7 +379,7 @@ expression!(
BitwiseXORExpression,
BitwiseANDExpression,
[Punctuator::Xor],
[allow_in, allow_yield, allow_await],
[name, allow_in, allow_yield, allow_await],
None::<InputElement>
);
@ -371,6 +393,7 @@ expression!(
/// [spec]: https://tc39.es/ecma262/#prod-BitwiseANDExpression
#[derive(Debug, Clone, Copy)]
struct BitwiseANDExpression {
name: Option<Sym>,
allow_in: AllowIn,
allow_yield: AllowYield,
allow_await: AllowAwait,
@ -378,13 +401,15 @@ struct BitwiseANDExpression {
impl BitwiseANDExpression {
/// Creates a new `BitwiseANDExpression` parser.
pub(super) fn new<I, Y, A>(allow_in: I, allow_yield: Y, allow_await: A) -> Self
pub(super) fn new<N, I, Y, A>(name: N, allow_in: I, allow_yield: Y, allow_await: A) -> Self
where
N: Into<Option<Sym>>,
I: Into<AllowIn>,
Y: Into<AllowYield>,
A: Into<AllowAwait>,
{
Self {
name: name.into(),
allow_in: allow_in.into(),
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
@ -396,7 +421,7 @@ expression!(
BitwiseANDExpression,
EqualityExpression,
[Punctuator::And],
[allow_in, allow_yield, allow_await],
[name, allow_in, allow_yield, allow_await],
None::<InputElement>
);
@ -410,6 +435,7 @@ expression!(
/// [spec]: https://tc39.es/ecma262/#sec-equality-operators
#[derive(Debug, Clone, Copy)]
struct EqualityExpression {
name: Option<Sym>,
allow_in: AllowIn,
allow_yield: AllowYield,
allow_await: AllowAwait,
@ -417,13 +443,15 @@ struct EqualityExpression {
impl EqualityExpression {
/// Creates a new `EqualityExpression` parser.
pub(super) fn new<I, Y, A>(allow_in: I, allow_yield: Y, allow_await: A) -> Self
pub(super) fn new<N, I, Y, A>(name: N, allow_in: I, allow_yield: Y, allow_await: A) -> Self
where
N: Into<Option<Sym>>,
I: Into<AllowIn>,
Y: Into<AllowYield>,
A: Into<AllowAwait>,
{
Self {
name: name.into(),
allow_in: allow_in.into(),
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
@ -440,7 +468,7 @@ expression!(
Punctuator::StrictEq,
Punctuator::StrictNotEq
],
[allow_in, allow_yield, allow_await],
[name, allow_in, allow_yield, allow_await],
None::<InputElement>
);
@ -454,6 +482,7 @@ expression!(
/// [spec]: https://tc39.es/ecma262/#sec-relational-operators
#[derive(Debug, Clone, Copy)]
struct RelationalExpression {
name: Option<Sym>,
allow_in: AllowIn,
allow_yield: AllowYield,
allow_await: AllowAwait,
@ -461,13 +490,15 @@ struct RelationalExpression {
impl RelationalExpression {
/// Creates a new `RelationalExpression` parser.
pub(super) fn new<I, Y, A>(allow_in: I, allow_yield: Y, allow_await: A) -> Self
pub(super) fn new<N, I, Y, A>(name: N, allow_in: I, allow_yield: Y, allow_await: A) -> Self
where
N: Into<Option<Sym>>,
I: Into<AllowIn>,
Y: Into<AllowYield>,
A: Into<AllowAwait>,
{
Self {
name: name.into(),
allow_in: allow_in.into(),
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
@ -484,8 +515,8 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult {
let _timer = Profiler::global().start_event("Relation Expression", "Parsing");
let mut lhs =
ShiftExpression::new(self.allow_yield, self.allow_await).parse(cursor, interner)?;
let mut lhs = ShiftExpression::new(self.name, self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
while let Some(tok) = cursor.peek(0, interner)? {
match *tok.kind() {
TokenKind::Punctuator(op)
@ -498,7 +529,7 @@ where
lhs = BinOp::new(
op.as_binop().expect("Could not get binary operation."),
lhs,
ShiftExpression::new(self.allow_yield, self.allow_await)
ShiftExpression::new(self.name, self.allow_yield, self.allow_await)
.parse(cursor, interner)?,
)
.into();
@ -511,7 +542,7 @@ where
lhs = BinOp::new(
op.as_binop().expect("Could not get binary operation."),
lhs,
ShiftExpression::new(self.allow_yield, self.allow_await)
ShiftExpression::new(self.name, self.allow_yield, self.allow_await)
.parse(cursor, interner)?,
)
.into();
@ -534,18 +565,21 @@ where
/// [spec]: https://tc39.es/ecma262/#sec-bitwise-shift-operators
#[derive(Debug, Clone, Copy)]
struct ShiftExpression {
name: Option<Sym>,
allow_yield: AllowYield,
allow_await: AllowAwait,
}
impl ShiftExpression {
/// Creates a new `ShiftExpression` parser.
pub(super) fn new<Y, A>(allow_yield: Y, allow_await: A) -> Self
pub(super) fn new<N, Y, A>(name: N, allow_yield: Y, allow_await: A) -> Self
where
N: Into<Option<Sym>>,
Y: Into<AllowYield>,
A: Into<AllowAwait>,
{
Self {
name: name.into(),
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
}
@ -560,7 +594,7 @@ expression!(
Punctuator::RightSh,
Punctuator::URightSh
],
[allow_yield, allow_await],
[name, allow_yield, allow_await],
None::<InputElement>
);
@ -576,18 +610,21 @@ expression!(
/// [spec]: https://tc39.es/ecma262/#sec-additive-operators
#[derive(Debug, Clone, Copy)]
struct AdditiveExpression {
name: Option<Sym>,
allow_yield: AllowYield,
allow_await: AllowAwait,
}
impl AdditiveExpression {
/// Creates a new `AdditiveExpression` parser.
pub(super) fn new<Y, A>(allow_yield: Y, allow_await: A) -> Self
pub(super) fn new<N, Y, A>(name: N, allow_yield: Y, allow_await: A) -> Self
where
N: Into<Option<Sym>>,
Y: Into<AllowYield>,
A: Into<AllowAwait>,
{
Self {
name: name.into(),
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
}
@ -598,7 +635,7 @@ expression!(
AdditiveExpression,
MultiplicativeExpression,
[Punctuator::Add, Punctuator::Sub],
[allow_yield, allow_await],
[name, allow_yield, allow_await],
None::<InputElement>
);
@ -614,18 +651,21 @@ expression!(
/// [spec]: https://tc39.es/ecma262/#sec-multiplicative-operators
#[derive(Debug, Clone, Copy)]
struct MultiplicativeExpression {
name: Option<Sym>,
allow_yield: AllowYield,
allow_await: AllowAwait,
}
impl MultiplicativeExpression {
/// Creates a new `MultiplicativeExpression` parser.
pub(super) fn new<Y, A>(allow_yield: Y, allow_await: A) -> Self
pub(super) fn new<N, Y, A>(name: N, allow_yield: Y, allow_await: A) -> Self
where
N: Into<Option<Sym>>,
Y: Into<AllowYield>,
A: Into<AllowAwait>,
{
Self {
name: name.into(),
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
}
@ -636,6 +676,6 @@ expression!(
MultiplicativeExpression,
ExponentiationExpression,
[Punctuator::Mul, Punctuator::Div, Punctuator::Mod],
[allow_yield, allow_await],
[name, allow_yield, allow_await],
Some(InputElement::Div)
);

21
boa_engine/src/syntax/parser/expression/primary/async_function_expression/mod.rs

@ -24,16 +24,19 @@ use std::io::Read;
/// [spec]: https://tc39.es/ecma262/#prod-AsyncFunctionExpression
#[derive(Debug, Clone, Copy)]
pub(super) struct AsyncFunctionExpression {
name: Option<Sym>,
allow_yield: AllowYield,
}
impl AsyncFunctionExpression {
/// Creates a new `AsyncFunctionExpression` parser.
pub(super) fn new<Y>(allow_yield: Y) -> Self
pub(super) fn new<N, Y>(name: N, allow_yield: Y) -> Self
where
N: Into<Option<Sym>>,
Y: Into<AllowYield>,
{
Self {
name: name.into(),
allow_yield: allow_yield.into(),
}
}
@ -54,15 +57,13 @@ where
cursor.peek_expect_no_lineterminator(0, "async function expression", interner)?;
cursor.expect(Keyword::Function, "async function expression", interner)?;
let tok = cursor.peek(0, interner)?;
let name = if let Some(token) = tok {
match token.kind() {
TokenKind::Punctuator(Punctuator::OpenParen) => None,
_ => Some(BindingIdentifier::new(self.allow_yield, true).parse(cursor, interner)?),
}
} else {
return Err(ParseError::AbruptEnd);
let name = match cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::Punctuator(Punctuator::OpenParen) => self.name,
_ => Some(BindingIdentifier::new(self.allow_yield, true).parse(cursor, interner)?),
};
// Early Error: If BindingIdentifier is present and the source code matching BindingIdentifier is strict mode code,

15
boa_engine/src/syntax/parser/expression/primary/async_function_expression/tests.rs

@ -14,6 +14,7 @@ use boa_interner::{Interner, Sym};
#[test]
fn check_async_expression() {
let mut interner = Interner::default();
let add = interner.get_or_intern_static("add");
check_parser(
"const add = async function() {
return 1;
@ -21,10 +22,10 @@ fn check_async_expression() {
",
vec![DeclarationList::Const(
vec![Declaration::new_with_identifier(
interner.get_or_intern_static("add"),
add,
Some(
AsyncFunctionExpr::new::<_, _, StatementList>(
None,
Some(add),
FormalParameterList::default(),
vec![Return::new::<_, _, Option<Sym>>(Const::from(1), None).into()].into(),
)
@ -41,6 +42,8 @@ fn check_async_expression() {
#[test]
fn check_nested_async_expression() {
let mut interner = Interner::default();
let a = interner.get_or_intern_static("a");
let b = interner.get_or_intern_static("b");
check_parser(
"const a = async function() {
const b = async function() {
@ -50,17 +53,17 @@ fn check_nested_async_expression() {
",
vec![DeclarationList::Const(
vec![Declaration::new_with_identifier(
interner.get_or_intern_static("a"),
a,
Some(
AsyncFunctionExpr::new::<_, _, StatementList>(
None,
Some(a),
FormalParameterList::default(),
vec![DeclarationList::Const(
vec![Declaration::new_with_identifier(
interner.get_or_intern_static("b"),
b,
Some(
AsyncFunctionExpr::new::<_, _, StatementList>(
None,
Some(b),
FormalParameterList::default(),
vec![Return::new::<_, _, Option<Sym>>(
Const::from(1),

28
boa_engine/src/syntax/parser/expression/primary/async_generator_expression/mod.rs

@ -30,7 +30,19 @@ use std::io::Read;
///
/// [spec]: https://tc39.es/ecma262/#prod-AsyncGeneratorExpression
#[derive(Debug, Clone, Copy)]
pub(super) struct AsyncGeneratorExpression;
pub(super) struct AsyncGeneratorExpression {
name: Option<Sym>,
}
impl AsyncGeneratorExpression {
/// Creates a new `AsyncGeneratorExpression` parser.
pub(in crate::syntax::parser) fn new<N>(name: N) -> Self
where
N: Into<Option<Sym>>,
{
Self { name: name.into() }
}
}
impl<R> TokenParser<R> for AsyncGeneratorExpression
where
@ -54,13 +66,13 @@ where
interner,
)?;
let name = if let Some(token) = cursor.peek(0, interner)? {
match token.kind() {
TokenKind::Punctuator(Punctuator::OpenParen) => None,
_ => Some(BindingIdentifier::new(true, true).parse(cursor, interner)?),
}
} else {
return Err(ParseError::AbruptEnd);
let name = match cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::Punctuator(Punctuator::OpenParen) => self.name,
_ => Some(BindingIdentifier::new(true, true).parse(cursor, interner)?),
};
// Early Error: If BindingIdentifier is present and the source code matching BindingIdentifier is strict

15
boa_engine/src/syntax/parser/expression/primary/async_generator_expression/tests.rs

@ -15,6 +15,7 @@ use boa_interner::{Interner, Sym};
#[test]
fn check_async_generator_expr() {
let mut interner = Interner::default();
let add = interner.get_or_intern_static("add");
check_parser(
"const add = async function*(){
return 1;
@ -22,10 +23,10 @@ fn check_async_generator_expr() {
",
vec![DeclarationList::Const(
vec![Declaration::new_with_identifier(
interner.get_or_intern_static("add"),
add,
Some(
AsyncGeneratorExpr::new::<_, _, StatementList>(
None,
Some(add),
FormalParameterList::default(),
vec![Return::new::<_, _, Option<Sym>>(Const::from(1), None).into()].into(),
)
@ -42,6 +43,8 @@ fn check_async_generator_expr() {
#[test]
fn check_nested_async_generator_expr() {
let mut interner = Interner::default();
let a = interner.get_or_intern_static("a");
let b = interner.get_or_intern_static("b");
check_parser(
"const a = async function*() {
const b = async function*() {
@ -51,17 +54,17 @@ fn check_nested_async_generator_expr() {
",
vec![DeclarationList::Const(
vec![Declaration::new_with_identifier(
interner.get_or_intern_static("a"),
a,
Some(
AsyncGeneratorExpr::new::<_, _, StatementList>(
None,
Some(a),
FormalParameterList::default(),
vec![DeclarationList::Const(
vec![Declaration::new_with_identifier(
interner.get_or_intern_static("b"),
b,
Some(
AsyncGeneratorExpr::new::<_, _, StatementList>(
None,
Some(b),
FormalParameterList::default(),
vec![Return::new::<_, _, Option<Sym>>(
Const::from(1),

30
boa_engine/src/syntax/parser/expression/primary/function_expression/mod.rs

@ -32,7 +32,19 @@ use std::io::Read;
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function
/// [spec]: https://tc39.es/ecma262/#prod-FunctionExpression
#[derive(Debug, Clone, Copy)]
pub(super) struct FunctionExpression;
pub(super) struct FunctionExpression {
name: Option<Sym>,
}
impl FunctionExpression {
/// Creates a new `FunctionExpression` parser.
pub(in crate::syntax::parser) fn new<N>(name: N) -> Self
where
N: Into<Option<Sym>>,
{
Self { name: name.into() }
}
}
impl<R> TokenParser<R> for FunctionExpression
where
@ -47,15 +59,15 @@ where
) -> Result<Self::Output, ParseError> {
let _timer = Profiler::global().start_event("FunctionExpression", "Parsing");
let name = if let Some(token) = cursor.peek(0, interner)? {
match token.kind() {
TokenKind::Identifier(_) | TokenKind::Keyword(Keyword::Yield | Keyword::Await) => {
Some(BindingIdentifier::new(false, false).parse(cursor, interner)?)
}
_ => None,
let name = match cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::Identifier(_) | TokenKind::Keyword(Keyword::Yield | Keyword::Await) => {
Some(BindingIdentifier::new(false, false).parse(cursor, interner)?)
}
} else {
None
_ => self.name,
};
// Early Error: If BindingIdentifier is present and the source code matching BindingIdentifier is strict mode code,

15
boa_engine/src/syntax/parser/expression/primary/function_expression/tests.rs

@ -13,6 +13,7 @@ use boa_interner::{Interner, Sym};
#[test]
fn check_function_expression() {
let mut interner = Interner::default();
let add = interner.get_or_intern_static("add");
check_parser(
"const add = function() {
return 1;
@ -20,10 +21,10 @@ fn check_function_expression() {
",
vec![DeclarationList::Const(
vec![Declaration::new_with_identifier(
interner.get_or_intern_static("add"),
add,
Some(
FunctionExpr::new::<_, _, StatementList>(
None,
Some(add),
FormalParameterList::default(),
vec![Return::new::<_, _, Option<Sym>>(Const::from(1), None).into()].into(),
)
@ -40,6 +41,8 @@ fn check_function_expression() {
#[test]
fn check_nested_function_expression() {
let mut interner = Interner::default();
let a = interner.get_or_intern_static("a");
let b = interner.get_or_intern_static("b");
check_parser(
"const a = function() {
const b = function() {
@ -49,17 +52,17 @@ fn check_nested_function_expression() {
",
vec![DeclarationList::Const(
vec![Declaration::new_with_identifier(
interner.get_or_intern_static("a"),
a,
Some(
FunctionExpr::new::<_, _, StatementList>(
None,
Some(a),
FormalParameterList::default(),
vec![DeclarationList::Const(
vec![Declaration::new_with_identifier(
interner.get_or_intern_static("b"),
b,
Some(
FunctionExpr::new::<_, _, StatementList>(
None,
Some(b),
FormalParameterList::default(),
vec![Return::new::<_, _, Option<Sym>>(
Const::from(1),

28
boa_engine/src/syntax/parser/expression/primary/generator_expression/mod.rs

@ -32,7 +32,19 @@ use std::io::Read;
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function*
/// [spec]: https://tc39.es/ecma262/#prod-GeneratorExpression
#[derive(Debug, Clone, Copy)]
pub(super) struct GeneratorExpression;
pub(super) struct GeneratorExpression {
name: Option<Sym>,
}
impl GeneratorExpression {
/// Creates a new `GeneratorExpression` parser.
pub(in crate::syntax::parser) fn new<N>(name: N) -> Self
where
N: Into<Option<Sym>>,
{
Self { name: name.into() }
}
}
impl<R> TokenParser<R> for GeneratorExpression
where
@ -53,13 +65,13 @@ where
interner,
)?;
let name = if let Some(token) = cursor.peek(0, interner)? {
match token.kind() {
TokenKind::Punctuator(Punctuator::OpenParen) => None,
_ => Some(BindingIdentifier::new(true, false).parse(cursor, interner)?),
}
} else {
return Err(ParseError::AbruptEnd);
let name = match cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::Punctuator(Punctuator::OpenParen) => self.name,
_ => Some(BindingIdentifier::new(true, false).parse(cursor, interner)?),
};
// Early Error: If BindingIdentifier is present and the source code matching BindingIdentifier is strict mode code,

10
boa_engine/src/syntax/parser/expression/primary/generator_expression/tests.rs

@ -12,6 +12,7 @@ use boa_interner::Interner;
#[test]
fn check_generator_function_expression() {
let mut interner = Interner::default();
let gen = interner.get_or_intern_static("gen");
check_parser(
"const gen = function*() {
yield 1;
@ -19,10 +20,10 @@ fn check_generator_function_expression() {
",
vec![DeclarationList::Const(
vec![Declaration::new_with_identifier(
interner.get_or_intern_static("gen"),
gen,
Some(
GeneratorExpr::new::<_, _, StatementList>(
None,
Some(gen),
FormalParameterList::default(),
vec![Yield::new(Const::from(1), false).into()].into(),
)
@ -39,6 +40,7 @@ fn check_generator_function_expression() {
#[test]
fn check_generator_function_delegate_yield_expression() {
let mut interner = Interner::default();
let gen = interner.get_or_intern_static("gen");
check_parser(
"const gen = function*() {
yield* 1;
@ -46,10 +48,10 @@ fn check_generator_function_delegate_yield_expression() {
",
vec![DeclarationList::Const(
vec![Declaration::new_with_identifier(
interner.get_or_intern_static("gen"),
gen,
Some(
GeneratorExpr::new::<_, _, StatementList>(
None,
Some(gen),
FormalParameterList::default(),
vec![Yield::new(Const::from(1), true).into()].into(),
)

19
boa_engine/src/syntax/parser/expression/primary/mod.rs

@ -50,18 +50,21 @@ pub(in crate::syntax::parser) use object_initializer::Initializer;
/// [spec]: https://tc39.es/ecma262/#prod-PrimaryExpression
#[derive(Debug, Clone, Copy)]
pub(super) struct PrimaryExpression {
name: Option<Sym>,
allow_yield: AllowYield,
allow_await: AllowAwait,
}
impl PrimaryExpression {
/// Creates a new `PrimaryExpression` parser.
pub(super) fn new<Y, A>(allow_yield: Y, allow_await: A) -> Self
pub(super) fn new<N, Y, A>(name: N, allow_yield: Y, allow_await: A) -> Self
where
N: Into<Option<Sym>>,
Y: Into<AllowYield>,
A: Into<AllowAwait>,
{
Self {
name: name.into(),
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
}
@ -86,26 +89,30 @@ where
TokenKind::Keyword(Keyword::Function) => {
let next_token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?;
if next_token.kind() == &TokenKind::Punctuator(Punctuator::Mul) {
GeneratorExpression.parse(cursor, interner).map(Node::from)
GeneratorExpression::new(self.name)
.parse(cursor, interner)
.map(Node::from)
} else {
FunctionExpression.parse(cursor, interner).map(Node::from)
FunctionExpression::new(self.name)
.parse(cursor, interner)
.map(Node::from)
}
}
TokenKind::Keyword(Keyword::Async) => {
let mul_peek = cursor.peek(1, interner)?.ok_or(ParseError::AbruptEnd)?;
if mul_peek.kind() == &TokenKind::Punctuator(Punctuator::Mul) {
AsyncGeneratorExpression
AsyncGeneratorExpression::new(self.name)
.parse(cursor, interner)
.map(Node::from)
} else {
AsyncFunctionExpression::new(self.allow_yield)
AsyncFunctionExpression::new(self.name, self.allow_yield)
.parse(cursor, interner)
.map(Node::from)
}
}
TokenKind::Punctuator(Punctuator::OpenParen) => {
cursor.set_goal(InputElement::RegExp);
let expr = Expression::new(None, true, self.allow_yield, self.allow_await)
let expr = Expression::new(self.name, true, self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
cursor.expect(Punctuator::CloseParen, "primary expression", interner)?;
Ok(expr)

10
boa_engine/src/syntax/parser/expression/unary.rs

@ -19,7 +19,7 @@ use crate::syntax::{
ParseResult, TokenParser,
},
};
use boa_interner::Interner;
use boa_interner::{Interner, Sym};
use boa_profiler::Profiler;
use std::io::Read;
@ -33,18 +33,21 @@ use std::io::Read;
/// [spec]: https://tc39.es/ecma262/#prod-UnaryExpression
#[derive(Debug, Clone, Copy)]
pub(in crate::syntax::parser) struct UnaryExpression {
name: Option<Sym>,
allow_yield: AllowYield,
allow_await: AllowAwait,
}
impl UnaryExpression {
/// Creates a new `UnaryExpression` parser.
pub(in crate::syntax::parser) fn new<Y, A>(allow_yield: Y, allow_await: A) -> Self
pub(in crate::syntax::parser) fn new<N, Y, A>(name: N, allow_yield: Y, allow_await: A) -> Self
where
N: Into<Option<Sym>>,
Y: Into<AllowYield>,
A: Into<AllowAwait>,
{
Self {
name: name.into(),
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
}
@ -102,7 +105,8 @@ where
cursor.next(interner)?.expect("! token vanished"); // Consume the token.
Ok(node::UnaryOp::new(UnaryOp::Not, self.parse(cursor, interner)?).into())
}
_ => UpdateExpression::new(self.allow_yield, self.allow_await).parse(cursor, interner),
_ => UpdateExpression::new(self.name, self.allow_yield, self.allow_await)
.parse(cursor, interner),
}
}
}

11
boa_engine/src/syntax/parser/expression/update.rs

@ -26,18 +26,21 @@ use std::io::Read;
/// [spec]: https://tc39.es/ecma262/#prod-UpdateExpression
#[derive(Debug, Clone, Copy)]
pub(super) struct UpdateExpression {
name: Option<Sym>,
allow_yield: AllowYield,
allow_await: AllowAwait,
}
impl UpdateExpression {
/// Creates a new `UpdateExpression` parser.
pub(super) fn new<Y, A>(allow_yield: Y, allow_await: A) -> Self
pub(super) fn new<N, Y, A>(name: N, allow_yield: Y, allow_await: A) -> Self
where
N: Into<Option<Sym>>,
Y: Into<AllowYield>,
A: Into<AllowAwait>,
{
Self {
name: name.into(),
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
}
@ -61,7 +64,7 @@ where
.expect("Punctuator::Inc token disappeared");
return Ok(node::UnaryOp::new(
UnaryOp::IncrementPre,
UnaryExpression::new(self.allow_yield, self.allow_await)
UnaryExpression::new(self.name, self.allow_yield, self.allow_await)
.parse(cursor, interner)?,
)
.into());
@ -72,7 +75,7 @@ where
.expect("Punctuator::Dec token disappeared");
return Ok(node::UnaryOp::new(
UnaryOp::DecrementPre,
UnaryExpression::new(self.allow_yield, self.allow_await)
UnaryExpression::new(self.name, self.allow_yield, self.allow_await)
.parse(cursor, interner)?,
)
.into());
@ -80,7 +83,7 @@ where
_ => {}
}
let lhs = LeftHandSideExpression::new(self.allow_yield, self.allow_await)
let lhs = LeftHandSideExpression::new(self.name, self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
let strict = cursor.strict_mode();
if let Some(tok) = cursor.peek(0, interner)? {

Loading…
Cancel
Save