use crate::builtins::value::Value;
use gc::{Finalize, Trace};
#[derive(Trace, Finalize, Clone, Debug)]
pub struct Property {
pub configurable: Option<bool>,
pub enumerable: Option<bool>,
pub writable: Option<bool>,
pub value: Option<Value>,
pub get: Option<Value>,
pub set: Option<Value>,
}
impl Property {
pub fn is_property_key(value: &Value) -> bool {
value.is_string() || value.is_symbol() }
pub fn new() -> Self {
Self {
configurable: None,
enumerable: None,
writable: None,
value: None,
get: None,
set: None,
}
}
pub fn configurable(mut self, configurable: bool) -> Self {
self.configurable = Some(configurable);
self
}
pub fn enumerable(mut self, enumerable: bool) -> Self {
self.enumerable = Some(enumerable);
self
}
pub fn writable(mut self, writable: bool) -> Self {
self.writable = Some(writable);
self
}
pub fn value(mut self, value: Value) -> Self {
self.value = Some(value);
self
}
pub fn get(mut self, get: Value) -> Self {
self.get = Some(get);
self
}
pub fn set(mut self, set: Value) -> Self {
self.set = Some(set);
self
}
pub fn is_none(&self) -> bool {
self.get.is_none()
&& self.set.is_none()
&& self.writable.is_none()
&& self.configurable.is_none()
&& self.enumerable.is_none()
}
pub fn is_accessor_descriptor(&self) -> bool {
self.get.is_some() || self.set.is_some()
}
pub fn is_data_descriptor(&self) -> bool {
self.value.is_some() || self.writable.is_some()
}
pub fn is_generic_descriptor(&self) -> bool {
!self.is_accessor_descriptor() && !self.is_data_descriptor()
}
}
impl Default for Property {
fn default() -> Self {
Self {
configurable: None,
enumerable: None,
writable: None,
value: None,
get: None,
set: None,
}
}
}
impl From<&Property> for Value {
fn from(value: &Property) -> Value {
let property = Value::new_object(None);
property.set_field("configurable", Value::from(value.configurable));
property.set_field("enumerable", Value::from(value.enumerable));
property.set_field("writable", Value::from(value.writable));
property.set_field("value", value.value.clone().unwrap_or_else(Value::null));
property.set_field("get", value.get.clone().unwrap_or_else(Value::null));
property.set_field("set", value.set.clone().unwrap_or_else(Value::null));
property
}
}
impl<'a> From<&'a Value> for Property {
fn from(value: &Value) -> Self {
Self {
configurable: { Some(bool::from(&value.get_field("configurable"))) },
enumerable: { Some(bool::from(&value.get_field("enumerable"))) },
writable: { Some(bool::from(&value.get_field("writable"))) },
value: Some(value.get_field("value")),
get: Some(value.get_field("get")),
set: Some(value.get_field("set")),
}
}
}
#[cfg(test)]
mod tests;