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

[Merged by Bors] - Implement member accessors in initializer of for loops #2381

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
349 changes: 181 additions & 168 deletions boa_engine/src/bytecompiler/mod.rs

Large diffs are not rendered by default.

79 changes: 67 additions & 12 deletions boa_engine/src/syntax/ast/expression/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
//! - *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]`.
//!
//! A property access expression can be represented by a [`SimplePropertyAccess`] (`x.y`), a
//! [`PrivatePropertyAccess`] (`x.#y`) or a [`SuperPropertyAccess`] (`super["y"]`), each of them with
//! slightly different semantics overall.
//!
//! [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

Expand Down Expand Up @@ -60,12 +64,62 @@ impl From<Expression> for PropertyAccessField {
/// 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 {
pub enum PropertyAccess {
/// A simple property access (`x.prop`).
Simple(SimplePropertyAccess),
/// A property access of a private property (`x.#priv`).
Private(PrivatePropertyAccess),
/// A property access of a `super` reference. (`super["prop"]`).
Super(SuperPropertyAccess),
}

impl PropertyAccess {
#[inline]
pub(crate) fn contains_arguments(&self) -> bool {
match self {
PropertyAccess::Simple(s) => s.contains_arguments(),
PropertyAccess::Private(p) => p.contains_arguments(),
PropertyAccess::Super(s) => s.contains_arguments(),
}
}

#[inline]
pub(crate) fn contains(&self, symbol: ContainsSymbol) -> bool {
match self {
PropertyAccess::Simple(s) => s.contains(symbol),
PropertyAccess::Private(p) => p.contains(symbol),
PropertyAccess::Super(s) => s.contains(symbol),
}
}
}

impl ToInternedString for PropertyAccess {
#[inline]
fn to_interned_string(&self, interner: &Interner) -> String {
match self {
PropertyAccess::Simple(s) => s.to_interned_string(interner),
PropertyAccess::Private(p) => p.to_interned_string(interner),
PropertyAccess::Super(s) => s.to_interned_string(interner),
}
}
}

impl From<PropertyAccess> for Expression {
#[inline]
fn from(access: PropertyAccess) -> Self {
Self::PropertyAccess(access)
}
}

/// A simple property access, where the target object is an [`Expression`].
#[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq)]
pub struct SimplePropertyAccess {
target: Box<Expression>,
field: PropertyAccessField,
}

impl PropertyAccess {
impl SimplePropertyAccess {
/// Gets the target object of the property access.
#[inline]
pub fn target(&self) -> &Expression {
Expand Down Expand Up @@ -101,7 +155,7 @@ impl PropertyAccess {
}
}

impl ToInternedString for PropertyAccess {
impl ToInternedString for SimplePropertyAccess {
#[inline]
fn to_interned_string(&self, interner: &Interner) -> String {
let target = self.target.to_interned_string(interner);
Expand All @@ -114,17 +168,18 @@ impl ToInternedString for PropertyAccess {
}
}

impl From<PropertyAccess> for Expression {
impl From<SimplePropertyAccess> for PropertyAccess {
#[inline]
fn from(access: PropertyAccess) -> Self {
Self::PropertyAccess(access)
fn from(access: SimplePropertyAccess) -> Self {
Self::Simple(access)
}
}

/// An access expression to a class object's [private fields][mdn].
///
/// 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`.
/// property must be prefixed by `#`, and the bracket notation is not allowed. For example,
/// `this.#a` is a valid private property access.
///
/// This expression corresponds to the [`MemberExpression.PrivateIdentifier`][spec] production.
///
Expand Down Expand Up @@ -181,10 +236,10 @@ impl ToInternedString for PrivatePropertyAccess {
}
}

impl From<PrivatePropertyAccess> for Expression {
impl From<PrivatePropertyAccess> for PropertyAccess {
#[inline]
fn from(access: PrivatePropertyAccess) -> Self {
Self::PrivatePropertyAccess(access)
Self::Private(access)
}
}

Expand Down Expand Up @@ -219,7 +274,7 @@ impl SuperPropertyAccess {

#[inline]
pub(crate) fn contains(&self, symbol: ContainsSymbol) -> bool {
self.field.contains(symbol)
symbol == ContainsSymbol::SuperProperty || self.field.contains(symbol)
}
}

Expand All @@ -237,9 +292,9 @@ impl ToInternedString for SuperPropertyAccess {
}
}

impl From<SuperPropertyAccess> for Expression {
impl From<SuperPropertyAccess> for PropertyAccess {
#[inline]
fn from(access: SuperPropertyAccess) -> Self {
Self::SuperPropertyAccess(access)
Self::Super(access)
}
}
19 changes: 2 additions & 17 deletions boa_engine/src/syntax/ast/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
use boa_interner::{Interner, Sym, ToIndentedString, ToInternedString};

use self::{
access::{PrivatePropertyAccess, PropertyAccess, SuperPropertyAccess},
access::PropertyAccess,
literal::{ArrayLiteral, Literal, ObjectLiteral, TemplateLiteral},
operator::{Assign, Binary, Conditional, Unary},
};
Expand Down Expand Up @@ -104,12 +104,6 @@ pub enum Expression {
/// See [`PropertyAccess`].
PropertyAccess(PropertyAccess),

/// See [`SuperPropertyAccess`]
SuperPropertyAccess(SuperPropertyAccess),

/// See [`PrivatePropertyAccess].
PrivatePropertyAccess(PrivatePropertyAccess),

/// See [`New`].
New(New),

Expand Down Expand Up @@ -176,8 +170,6 @@ impl Expression {
Self::AsyncGenerator(asgen) => asgen.to_indented_string(interner, indentation),
Self::TemplateLiteral(tem) => tem.to_interned_string(interner),
Self::PropertyAccess(prop) => prop.to_interned_string(interner),
Self::SuperPropertyAccess(supp) => supp.to_interned_string(interner),
Self::PrivatePropertyAccess(private) => private.to_interned_string(interner),
Self::New(new) => new.to_interned_string(interner),
Self::Call(call) => call.to_interned_string(interner),
Self::SuperCall(supc) => supc.to_interned_string(interner),
Expand Down Expand Up @@ -218,8 +210,6 @@ impl Expression {
Expression::Class(class) => class.contains_arguments(),
Expression::TemplateLiteral(template) => template.contains_arguments(),
Expression::PropertyAccess(access) => access.contains_arguments(),
Expression::SuperPropertyAccess(access) => access.contains_arguments(),
Expression::PrivatePropertyAccess(access) => access.contains_arguments(),
Expression::New(new) => new.contains_arguments(),
Expression::Call(call) => call.contains_arguments(),
Expression::SuperCall(call) => call.contains_arguments(),
Expand Down Expand Up @@ -257,12 +247,7 @@ impl Expression {
Expression::ArrowFunction(arrow) => arrow.contains(symbol),
Expression::Class(class) => class.contains(symbol),
Expression::TemplateLiteral(temp) => temp.contains(symbol),
Expression::PropertyAccess(access) => access.contains(symbol),
Expression::SuperPropertyAccess(_access) if symbol == ContainsSymbol::SuperProperty => {
true
}
Expression::SuperPropertyAccess(access) => access.contains(symbol),
Expression::PrivatePropertyAccess(access) => access.contains(symbol),
Expression::PropertyAccess(prop) => prop.contains(symbol),
Expression::New(new) => new.contains(symbol),
Expression::Call(call) => call.contains(symbol),
Expression::SuperCall(_) if symbol == ContainsSymbol::SuperCall => true,
Expand Down
46 changes: 13 additions & 33 deletions boa_engine/src/syntax/ast/expression/operator/assign/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use boa_interner::{Interner, Sym, ToInternedString};
use crate::syntax::{
ast::{
expression::{
access::{PrivatePropertyAccess, PropertyAccess, SuperPropertyAccess},
access::PropertyAccess,
identifier::Identifier,
literal::{ArrayLiteral, ObjectLiteral},
Expression,
Expand Down Expand Up @@ -75,9 +75,7 @@ impl Assign {
pub(crate) fn contains_arguments(&self) -> bool {
(match &*self.lhs {
AssignTarget::Identifier(ident) => *ident == Sym::ARGUMENTS,
AssignTarget::Property(access) => access.contains_arguments(),
AssignTarget::PrivateProperty(access) => access.contains_arguments(),
AssignTarget::SuperProperty(access) => access.contains_arguments(),
AssignTarget::Access(access) => access.contains_arguments(),
AssignTarget::Pattern(pattern) => pattern.contains_arguments(),
} || self.rhs.contains_arguments())
}
Expand All @@ -86,9 +84,7 @@ impl Assign {
pub(crate) fn contains(&self, symbol: ContainsSymbol) -> bool {
(match &*self.lhs {
AssignTarget::Identifier(_) => false,
AssignTarget::Property(access) => access.contains(symbol),
AssignTarget::PrivateProperty(access) => access.contains(symbol),
AssignTarget::SuperProperty(access) => access.contains(symbol),
AssignTarget::Access(access) => access.contains(symbol),
AssignTarget::Pattern(pattern) => pattern.contains(symbol),
} || self.rhs.contains(symbol))
}
Expand Down Expand Up @@ -123,12 +119,8 @@ 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}`.
Access(PropertyAccess),
/// A pattern assignment, such as `{a, b, ...c}`.
Pattern(Pattern),
}

Expand All @@ -142,11 +134,7 @@ impl AssignTarget {
) -> Option<Self> {
match expression {
Expression::Identifier(id) => Some(Self::Identifier(*id)),
Expression::PropertyAccess(access) => Some(Self::Property(access.clone())),
Expression::PrivatePropertyAccess(access) => {
Some(Self::PrivateProperty(access.clone()))
}
Expression::SuperPropertyAccess(access) => Some(Self::SuperProperty(access.clone())),
Expression::PropertyAccess(access) => Some(Self::Access(access.clone())),
Expression::ObjectLiteral(object) if destructure => {
let pattern = object_decl_to_declaration_pattern(object, strict)?;
Some(Self::Pattern(pattern.into()))
Expand All @@ -165,9 +153,7 @@ impl ToInternedString for AssignTarget {
fn to_interned_string(&self, interner: &Interner) -> String {
match self {
AssignTarget::Identifier(id) => id.to_interned_string(interner),
AssignTarget::Property(access) => access.to_interned_string(interner),
AssignTarget::PrivateProperty(access) => access.to_interned_string(interner),
AssignTarget::SuperProperty(access) => access.to_interned_string(interner),
AssignTarget::Access(access) => access.to_interned_string(interner),
AssignTarget::Pattern(pattern) => pattern.to_interned_string(interner),
}
}
Expand All @@ -189,9 +175,7 @@ pub(crate) fn object_decl_to_declaration_pattern(
let mut excluded_keys = Vec::new();
for (i, property) in object.properties().iter().enumerate() {
match property {
PropertyDefinition::IdentifierReference(ident)
if strict && ident.sym() == Sym::EVAL =>
{
PropertyDefinition::IdentifierReference(ident) if strict && *ident == Sym::EVAL => {
return None
}
PropertyDefinition::IdentifierReference(ident) => {
Expand Down Expand Up @@ -279,21 +263,18 @@ pub(crate) fn object_decl_to_declaration_pattern(
default_init: Some(assign.rhs().clone()),
});
}
AssignTarget::Property(field) => {
AssignTarget::Access(access) => {
bindings.push(ObjectPatternElement::AssignmentPropertyAccess {
name: name.clone(),
access: field.clone(),
access: access.clone(),
default_init: Some(assign.rhs().clone()),
});
}
AssignTarget::SuperProperty(_) | AssignTarget::PrivateProperty(_) => {
return None
}
},
(_, Expression::PropertyAccess(field)) => {
(_, Expression::PropertyAccess(access)) => {
bindings.push(ObjectPatternElement::AssignmentPropertyAccess {
name: name.clone(),
access: field.clone(),
access: access.clone(),
default_init: None,
});
}
Expand Down Expand Up @@ -402,7 +383,7 @@ pub(crate) fn array_decl_to_declaration_pattern(
default_init: Some(assign.rhs().clone()),
});
}
AssignTarget::Property(access) => {
AssignTarget::Access(access) => {
bindings.push(ArrayPatternElement::PropertyAccess {
access: access.clone(),
});
Expand All @@ -421,7 +402,6 @@ pub(crate) fn array_decl_to_declaration_pattern(
});
}
},
AssignTarget::PrivateProperty(_) | AssignTarget::SuperProperty(_) => return None,
},
Expression::ArrayLiteral(array) => {
let pattern = array_decl_to_declaration_pattern(array, strict)?.into();
Expand Down
Loading