Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Async Generator Parsing #1669

Merged
merged 45 commits into from
Oct 23, 2021
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
92e5a05
initial commit of attempt at AsyncGeneratorDeclaration and AsyncGener…
nekevss Oct 11, 2021
c80080c
fixed misspelled AsyncGeneratorDeclaration
nekevss Oct 12, 2021
059cd48
adding AsyncGeneratorDeclaration to hoistable
nekevss Oct 12, 2021
3a6ff05
removing unused Keyword from async_function_expression
nekevss Oct 12, 2021
86326c7
AsyncGeneratorExpr tests and cargo fmt
nekevss Oct 14, 2021
8b03415
fixing tests
nekevss Oct 15, 2021
94fbdad
added tests to mod and adding to module declarations
nekevss Oct 15, 2021
6dfeafe
Added AsyncGenerator and Async to MethodDefinitionKind
nekevss Oct 15, 2021
2b81c58
allwo await and yield set to true in async_gen_decl - cargo fmt
nekevss Oct 15, 2021
28b7e82
added new method kinds to object node
nekevss Oct 15, 2021
0bb3853
forgot cargo fmt
nekevss Oct 15, 2021
2b5ecb5
Added some better comments implementations
nekevss Oct 15, 2021
0391d57
added async and async generator methods to object_initializer
nekevss Oct 15, 2021
3124783
Added note to uniqueformalparameters:formalparameters error check
nekevss Oct 15, 2021
f47b79f
Opps, removed cursor ops that now happen before AsyncFunctionDeclarat…
nekevss Oct 15, 2021
557d5c0
made requested review changes
nekevss Oct 19, 2021
83e3092
initial commit of attempt at AsyncGeneratorDeclaration and AsyncGener…
nekevss Oct 11, 2021
408e3fc
fixed misspelled AsyncGeneratorDeclaration
nekevss Oct 12, 2021
f9b2183
adding AsyncGeneratorDeclaration to hoistable
nekevss Oct 12, 2021
6ff0cc6
removing unused Keyword from async_function_expression
nekevss Oct 12, 2021
adbcb41
AsyncGeneratorExpr tests and cargo fmt
nekevss Oct 14, 2021
3578a6e
fixing tests
nekevss Oct 15, 2021
d926ad2
added tests to mod and adding to module declarations
nekevss Oct 15, 2021
3dd5614
Added AsyncGenerator and Async to MethodDefinitionKind
nekevss Oct 15, 2021
ce04054
allwo await and yield set to true in async_gen_decl - cargo fmt
nekevss Oct 15, 2021
2ce5665
added new method kinds to object node
nekevss Oct 15, 2021
1f7cafc
forgot cargo fmt
nekevss Oct 15, 2021
a5d0c04
Added some better comments implementations
nekevss Oct 15, 2021
97e8eb3
added async and async generator methods to object_initializer
nekevss Oct 15, 2021
81418fa
Added note to uniqueformalparameters:formalparameters error check
nekevss Oct 15, 2021
3b2d110
Opps, removed cursor ops that now happen before AsyncFunctionDeclarat…
nekevss Oct 15, 2021
782541a
made requested review changes
nekevss Oct 19, 2021
7a43369
Merge branch 'impl-async-gen-parser' of https://github.com/nekevss/bo…
nekevss Oct 19, 2021
b37268a
fixing issue in async methods in object_initializer + tests
nekevss Oct 21, 2021
343d4f6
added a comment
nekevss Oct 21, 2021
74dedf8
Merge branch 'master' into impl-async-gen-parser
nekevss Oct 22, 2021
4cb76b2
review changes to match parser spec/clean up
nekevss Oct 23, 2021
a59405b
changes to comment blocks on async gen decl
nekevss Oct 23, 2021
35704be
cargo fmt
nekevss Oct 23, 2021
7abd657
Added to ByteCompiler & review changes
nekevss Oct 23, 2021
ac55423
Added TODO to PrimaryExpression
nekevss Oct 23, 2021
58b32dd
Removed inline attribute
nekevss Oct 23, 2021
5edcba5
Added more to comment blocks
nekevss Oct 23, 2021
7c89348
Update boa/src/syntax/ast/node/declaration/async_generator_expr/mod.rs
Razican Oct 23, 2021
1892ecd
Update boa/src/syntax/parser/statement/declaration/hoistable/async_ge…
Razican Oct 23, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions boa/src/bytecompiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,38 @@ impl ByteCompiler {
}
}
}
MethodDefinitionKind::Async => {
// TODO: Implement async
self.emit_opcode(Opcode::PushUndefined);
self.emit_opcode(Opcode::Swap);
match name {
PropertyName::Literal(name) => {
let index = self.get_or_insert_name(name);
self.emit(Opcode::SetPropertyByName, &[index])
}
PropertyName::Computed(name_node) => {
self.compile_stmt(name_node, true);
self.emit_opcode(Opcode::Swap);
self.emit_opcode(Opcode::SetPropertyByValue);
}
}
}
MethodDefinitionKind::AsyncGenerator => {
// TODO: Implement async generators
self.emit_opcode(Opcode::PushUndefined);
self.emit_opcode(Opcode::Swap);
match name {
PropertyName::Literal(name) => {
let index = self.get_or_insert_name(name);
self.emit(Opcode::SetPropertyByName, &[index])
}
PropertyName::Computed(name_node) => {
self.compile_stmt(name_node, true);
self.emit_opcode(Opcode::Swap);
self.emit_opcode(Opcode::SetPropertyByValue);
}
}
}
}
}
// TODO: Spread Object
Expand Down
94 changes: 94 additions & 0 deletions boa/src/syntax/ast/node/declaration/async_generator_decl/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
//! Async Generator Declaration
Razican marked this conversation as resolved.
Show resolved Hide resolved

use crate::{
exec::Executable,
syntax::ast::node::{join_nodes, FormalParameter, Node, StatementList},
BoaProfiler, Context, JsResult, JsValue,
};
use gc::{Finalize, Trace};
use std::fmt;

#[cfg(feature = "deser")]
use serde::{Deserialize, Serialize};

/// The 'async function*' defines an async generator function
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#prod-AsyncGeneratorMethod
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct AsyncGeneratorDecl {
name: Box<str>,
parameters: Box<[FormalParameter]>,
body: StatementList,
}

impl AsyncGeneratorDecl {
/// Creates a new async generator declaration.
pub(in crate::syntax) fn new<N, P, B>(name: N, parameters: P, body: B) -> Self
where
N: Into<Box<str>>,
P: Into<Box<[FormalParameter]>>,
B: Into<StatementList>,
{
Self {
name: name.into(),
parameters: parameters.into(),
body: body.into(),
}
}

/// Gets the name of the async function declaration.
pub fn name(&self) -> &str {
&self.name
}

/// Gets the list of parameters of the async function declaration.
pub fn parameters(&self) -> &[FormalParameter] {
&self.parameters
}

/// Gets the body of the async function declaration.
pub fn body(&self) -> &[Node] {
self.body.items()
}

/// Implements the display formatting with indentation.
pub(in crate::syntax::ast::node) fn display(
&self,
f: &mut fmt::Formatter<'_>,
indentation: usize,
) -> fmt::Result {
write!(f, "async function* {}(", self.name())?;
join_nodes(f, &self.parameters)?;
if self.body().is_empty() {
f.write_str(") {}")
} else {
f.write_str(") {\n")?;
self.body.display(f, indentation + 1)?;
write!(f, "{}}}", " ".repeat(indentation))
}
}
}

impl Executable for AsyncGeneratorDecl {
fn run(&self, _: &mut Context) -> JsResult<JsValue> {
let _timer = BoaProfiler::global().start_event("AsyncGeneratorDecl", "exec");
//TODO: Implement AsyncGeneratorDecl
Ok(JsValue::undefined())
}
}

impl From<AsyncGeneratorDecl> for Node {
fn from(decl: AsyncGeneratorDecl) -> Self {
Self::AsyncGeneratorDecl(decl)
}
}

impl fmt::Display for AsyncGeneratorDecl {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.display(f, 0)
}
}
106 changes: 106 additions & 0 deletions boa/src/syntax/ast/node/declaration/async_generator_expr/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//! Async Generator Expression

use crate::{
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::{join_nodes, FormalParameter, Node, StatementList},
Context, JsResult, JsValue,
};
use std::fmt;

#[cfg(feature = "deser")]
use serde::{Deserialize, Serialize};

raskad marked this conversation as resolved.
Show resolved Hide resolved
/// The `async function*` keyword can be used to define a generator function inside an expression.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#prod-AsyncGeneratorExpression

Razican marked this conversation as resolved.
Show resolved Hide resolved
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct AsyncGeneratorExpr {
name: Option<Box<str>>,
parameters: Box<[FormalParameter]>,
body: StatementList,
}

impl AsyncGeneratorExpr {
/// Creates a new async generator expression
pub(in crate::syntax) fn new<N, P, B>(name: N, parameters: P, body: B) -> Self
where
N: Into<Option<Box<str>>>,
P: Into<Box<[FormalParameter]>>,
B: Into<StatementList>,
{
Self {
name: name.into(),
parameters: parameters.into(),
body: body.into(),
}
}

/// Gets the name of the async generator expression
pub fn name(&self) -> Option<&str> {
self.name.as_ref().map(Box::as_ref)
}

/// Gets the list of parameters of the async generator expression
pub fn parameters(&self) -> &[FormalParameter] {
&self.parameters
}

/// Gets the body of the async generator expression
pub fn body(&self) -> &StatementList {
&self.body
}

pub(in crate::syntax::ast::node) fn display(
&self,
f: &mut fmt::Formatter<'_>,
indentation: usize,
) -> fmt::Result {
f.write_str("async function*")?;
if let Some(ref name) = self.name {
write!(f, " {}", name)?;
}
f.write_str("(")?;
join_nodes(f, &self.parameters)?;
f.write_str(") ")?;
self.display_block(f, indentation)
}

pub(in crate::syntax::ast::node) fn display_block(
&self,
f: &mut fmt::Formatter<'_>,
indentation: usize,
) -> fmt::Result {
if self.body().items().is_empty() {
f.write_str("{}")
} else {
f.write_str("{\n")?;
self.body.display(f, indentation + 1)?;
write!(f, "{}}}", " ".repeat(indentation))
}
}
}

impl Executable for AsyncGeneratorExpr {
fn run(&self, _context: &mut Context) -> JsResult<JsValue> {
//TODO: Implement AsyncGeneratorFunction
Ok(JsValue::undefined())
}
}

impl fmt::Display for AsyncGeneratorExpr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.display(f, 0)
}
}

impl From<AsyncGeneratorExpr> for Node {
fn from(expr: AsyncGeneratorExpr) -> Self {
Self::AsyncGeneratorExpr(expr)
}
}
5 changes: 4 additions & 1 deletion boa/src/syntax/ast/node/declaration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@ use serde::{Deserialize, Serialize};
pub mod arrow_function_decl;
pub mod async_function_decl;
pub mod async_function_expr;
pub mod async_generator_decl;
pub mod async_generator_expr;
pub mod function_decl;
pub mod function_expr;
pub mod generator_decl;
pub mod generator_expr;

pub use self::{
arrow_function_decl::ArrowFunctionDecl, async_function_decl::AsyncFunctionDecl,
async_function_expr::AsyncFunctionExpr, function_decl::FunctionDecl,
async_function_expr::AsyncFunctionExpr, async_generator_decl::AsyncGeneratorDecl,
async_generator_expr::AsyncGeneratorExpr, function_decl::FunctionDecl,
function_expr::FunctionExpr,
};

Expand Down
31 changes: 31 additions & 0 deletions boa/src/syntax/ast/node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub use self::{
call::Call,
conditional::{ConditionalOp, If},
declaration::{
async_generator_decl::AsyncGeneratorDecl, async_generator_expr::AsyncGeneratorExpr,
generator_decl::GeneratorDecl, generator_expr::GeneratorExpr, ArrowFunctionDecl,
AsyncFunctionDecl, AsyncFunctionExpr, Declaration, DeclarationList, FunctionDecl,
FunctionExpr,
Expand Down Expand Up @@ -82,6 +83,12 @@ pub enum Node {
/// An async function expression node. [More information](./declaration/struct.AsyncFunctionExpr.html).
AsyncFunctionExpr(AsyncFunctionExpr),

/// An async generator expression node.
AsyncGeneratorExpr(AsyncGeneratorExpr),

/// An async generator declaration node.
AsyncGeneratorDecl(AsyncGeneratorDecl),

/// An await expression node. [More information](./await_expr/struct.AwaitExpression.html).
AwaitExpr(AwaitExpr),

Expand Down Expand Up @@ -317,6 +324,8 @@ impl Node {
Self::Yield(ref y) => Display::fmt(y, f),
Self::GeneratorDecl(ref decl) => Display::fmt(decl, f),
Self::GeneratorExpr(ref expr) => expr.display(f, indentation),
Self::AsyncGeneratorExpr(ref expr) => expr.display(f, indentation),
Self::AsyncGeneratorDecl(ref decl) => decl.display(f, indentation),
}
}
}
Expand All @@ -327,6 +336,8 @@ impl Executable for Node {
match *self {
Node::AsyncFunctionDecl(ref decl) => decl.run(context),
Node::AsyncFunctionExpr(ref function_expr) => function_expr.run(context),
Node::AsyncGeneratorExpr(ref expr) => expr.run(context),
Node::AsyncGeneratorDecl(ref decl) => decl.run(context),
Node::AwaitExpr(ref expr) => expr.run(context),
Node::Call(ref call) => call.run(context),
Node::Const(Const::Null) => Ok(JsValue::null()),
Expand Down Expand Up @@ -625,6 +636,26 @@ pub enum MethodDefinitionKind {
/// [spec]: https://tc39.es/ecma262/#prod-MethodDefinition
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions#generator_methods
Generator,

/// Async generators can be used to define a method
///
/// More information
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#prod-AsyncGeneratorMethod
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions#async_generator_methods
AsyncGenerator,

/// Async function can be used to define a method
///
/// More information
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#prod-AsyncMethod
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions#async_methods
Async,
}

unsafe impl Trace for MethodDefinitionKind {
Expand Down
30 changes: 29 additions & 1 deletion boa/src/syntax/ast/node/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ impl Object {
match &kind {
MethodDefinitionKind::Get => write!(f, "get ")?,
MethodDefinitionKind::Set => write!(f, "set ")?,
MethodDefinitionKind::Ordinary | MethodDefinitionKind::Generator => (),
MethodDefinitionKind::Ordinary
| MethodDefinitionKind::Generator
| MethodDefinitionKind::Async
| MethodDefinitionKind::AsyncGenerator => (),
}
write!(f, "{}(", key)?;
join_nodes(f, node.parameters())?;
Expand Down Expand Up @@ -179,6 +182,31 @@ impl Executable for Object {
context,
)?;
}
&MethodDefinitionKind::AsyncGenerator => {
// TODO: Implement async generator method definition execution.
obj.__define_own_property__(
name,
PropertyDescriptor::builder()
.value(JsValue::undefined())
.writable(true)
.enumerable(true)
.configurable(true)
.build(),
context,
)?;
}
&MethodDefinitionKind::Async => {
obj.__define_own_property__(
name,
PropertyDescriptor::builder()
.value(JsValue::undefined())
.writable(true)
.enumerable(true)
.configurable(true)
.build(),
context,
)?;
}
}
}
// [spec]: https://tc39.es/ecma262/#sec-runtime-semantics-propertydefinitionevaluation
Expand Down
Loading