Skip to content

Commit

Permalink
Implement Classes (#1976)
Browse files Browse the repository at this point in the history
This Pull Request fixes/closes #337.

It changes the following:

- Implement class declaration parsing.
- Implement class expression parsing.
- Implement class execution.

There are still some features like `super` missing and there are some early errors that are not implemented yet. But I think it makes sense to merge this, as we can branch out the missing features from here.
  • Loading branch information
raskad committed Apr 7, 2022
1 parent e6d12f8 commit 2239669
Show file tree
Hide file tree
Showing 45 changed files with 3,752 additions and 373 deletions.
451 changes: 448 additions & 3 deletions boa_engine/src/bytecompiler.rs

Large diffs are not rendered by default.

29 changes: 23 additions & 6 deletions boa_engine/src/object/jsobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
Context, JsResult, JsValue,
};
use boa_gc::{self, Finalize, Gc, Trace};
use rustc_hash::FxHashMap;
use std::{
cell::RefCell,
collections::HashMap,
Expand Down Expand Up @@ -51,12 +52,28 @@ impl JsObject {
/// internal slots from the `data` provided.
#[inline]
pub fn from_proto_and_data<O: Into<Option<Self>>>(prototype: O, data: ObjectData) -> Self {
Self::from_object(Object {
data,
prototype: prototype.into(),
extensible: true,
properties: PropertyMap::default(),
})
let prototype: Option<Self> = prototype.into();
if let Some(prototype) = prototype {
let private = {
let prototype_b = prototype.borrow();
prototype_b.private_elements.clone()
};
Self::from_object(Object {
data,
prototype: Some(prototype),
extensible: true,
properties: PropertyMap::default(),
private_elements: private,
})
} else {
Self::from_object(Object {
data,
prototype: None,
extensible: true,
properties: PropertyMap::default(),
private_elements: FxHashMap::default(),
})
}
}

/// Immutably borrows the `Object`.
Expand Down
71 changes: 71 additions & 0 deletions boa_engine/src/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ use crate::{
Context, JsBigInt, JsResult, JsString, JsSymbol, JsValue,
};
use boa_gc::{Finalize, Trace};
use boa_interner::Sym;
use rustc_hash::FxHashMap;
use std::{
any::Any,
fmt::{self, Debug, Display},
Expand Down Expand Up @@ -106,6 +108,18 @@ pub struct Object {
prototype: JsPrototype,
/// Whether it can have new properties added to it.
extensible: bool,
/// The `[[PrivateElements]]` internal slot.
private_elements: FxHashMap<Sym, PrivateElement>,
}

/// The representation of private object elements.
#[derive(Clone, Debug, Trace, Finalize)]
pub(crate) enum PrivateElement {
Value(JsValue),
Accessor {
getter: Option<JsObject>,
setter: Option<JsObject>,
},
}

/// Defines the kind of an object and its internal methods
Expand Down Expand Up @@ -459,6 +473,7 @@ impl Default for Object {
properties: PropertyMap::default(),
prototype: None,
extensible: true,
private_elements: FxHashMap::default(),
}
}
}
Expand Down Expand Up @@ -1219,6 +1234,62 @@ impl Object {
pub(crate) fn remove(&mut self, key: &PropertyKey) -> Option<PropertyDescriptor> {
self.properties.remove(key)
}

/// Get a private element.
#[inline]
pub(crate) fn get_private_element(&self, name: Sym) -> Option<&PrivateElement> {
self.private_elements.get(&name)
}

/// Set a private element.
#[inline]
pub(crate) fn set_private_element(&mut self, name: Sym, value: PrivateElement) {
self.private_elements.insert(name, value);
}

/// Set a private setter.
#[inline]
pub(crate) fn set_private_element_setter(&mut self, name: Sym, setter: JsObject) {
match self.private_elements.get_mut(&name) {
Some(PrivateElement::Accessor {
getter: _,
setter: s,
}) => {
*s = Some(setter);
}
_ => {
self.private_elements.insert(
name,
PrivateElement::Accessor {
getter: None,
setter: Some(setter),
},
);
}
}
}

/// Set a private getter.
#[inline]
pub(crate) fn set_private_element_getter(&mut self, name: Sym, getter: JsObject) {
match self.private_elements.get_mut(&name) {
Some(PrivateElement::Accessor {
getter: g,
setter: _,
}) => {
*g = Some(getter);
}
_ => {
self.private_elements.insert(
name,
PrivateElement::Accessor {
getter: Some(getter),
setter: None,
},
);
}
}
}
}

/// The functions binding.
Expand Down
Loading

0 comments on commit 2239669

Please sign in to comment.