Browse Source

move Property to its own module

pull/92/head
Jason Williams 5 years ago
parent
commit
f90f976732
  1. 2
      src/lib/environment/object_environment_record.rs
  2. 3
      src/lib/js/array.rs
  3. 3
      src/lib/js/function.rs
  4. 2
      src/lib/js/mod.rs
  5. 83
      src/lib/js/object.rs
  6. 81
      src/lib/js/property.rs
  7. 3
      src/lib/js/string.rs
  8. 3
      src/lib/js/value.rs

2
src/lib/environment/object_environment_record.rs

@ -12,7 +12,7 @@ use crate::{
lexical_environment::{Environment, EnvironmentType},
},
js::{
object::Property,
property::Property,
value::{Value, ValueData},
},
};

3
src/lib/js/array.rs

@ -2,7 +2,8 @@ use crate::{
exec::Interpreter,
js::{
function::NativeFunctionData,
object::{ObjectKind, Property, PROTOTYPE},
object::{ObjectKind, PROTOTYPE},
property::Property,
value::{from_value, to_value, ResultValue, Value, ValueData},
},
};

3
src/lib/js/function.rs

@ -1,7 +1,8 @@
use crate::{
exec::Interpreter,
js::{
object::{Object, Property},
object::Object,
property::Property,
value::{to_value, ResultValue, Value, ValueData},
},
syntax::ast::expr::Expr,

2
src/lib/js/mod.rs

@ -16,3 +16,5 @@ pub mod object;
pub mod string;
/// Javascript values, utility methods and conversion between Javascript values and Rust values
pub mod value;
// Property, used by `Object`
pub mod property;

83
src/lib/js/object.rs

@ -2,7 +2,8 @@ use crate::{
exec::Interpreter,
js::{
function::NativeFunctionData,
value::{from_value, to_value, FromValue, ResultValue, ToValue, Value, ValueData},
property::Property,
value::{from_value, to_value, ResultValue, Value, ValueData},
},
};
use gc::Gc;
@ -10,11 +11,9 @@ use gc_derive::{Finalize, Trace};
use std::{borrow::Borrow, collections::HashMap, ops::Deref};
/// Static `prototype`, usually set on constructors as a key to point to their respective prototype object.
/// As this string will be used a lot throughout the program, its best being a static global string which will be referenced
pub static PROTOTYPE: &str = "prototype";
/// Static `__proto__`, usually set on Object instances as a key to point to their respective prototype object.
/// As this string will be used a lot throughout the program, its best being a static global string which will be referenced
pub static INSTANCE_PROTOTYPE: &str = "__proto__";
/// `ObjectData` is the representation of an object in JavaScript
@ -105,70 +104,6 @@ pub enum ObjectKind {
Number,
}
/// A Javascript Property AKA The Property Descriptor
/// [[SPEC] - The Property Descriptor Specification Type](https://tc39.github.io/ecma262/#sec-property-descriptor-specification-type)
/// [[SPEC] - Default Attribute Values](https://tc39.github.io/ecma262/#table-4)
#[derive(Trace, Finalize, Clone, Debug)]
pub struct Property {
/// If the type of this can be changed and this can be deleted
pub configurable: bool,
/// If the property shows up in enumeration of the object
pub enumerable: bool,
/// If this property can be changed with an assignment
pub writable: bool,
/// The value associated with the property
pub value: Value,
/// The function serving as getter
pub get: Value,
/// The function serving as setter
pub set: Value,
}
impl Property {
/// Checks if the provided Value can be used as a property key.
pub fn is_property_key(value: &Value) -> bool {
value.is_string() // || value.is_symbol() // Uncomment this when we are handeling symbols.
}
/// Make a new property with the given value
pub fn new(value: Value) -> Self {
Self {
configurable: false,
enumerable: false,
writable: false,
value,
get: Gc::new(ValueData::Undefined),
set: Gc::new(ValueData::Undefined),
}
}
}
impl ToValue for Property {
fn to_value(&self) -> Value {
let prop = ValueData::new_obj(None);
prop.set_field_slice("configurable", to_value(self.configurable));
prop.set_field_slice("enumerable", to_value(self.enumerable));
prop.set_field_slice("writable", to_value(self.writable));
prop.set_field_slice("value", self.value.clone());
prop.set_field_slice("get", self.get.clone());
prop.set_field_slice("set", self.set.clone());
prop
}
}
impl FromValue for Property {
fn from_value(v: Value) -> Result<Self, &'static str> {
Ok(Self {
configurable: from_value(v.get_field_slice("configurable")).unwrap(),
enumerable: from_value(v.get_field_slice("enumerable")).unwrap(),
writable: from_value(v.get_field_slice("writable")).unwrap(),
value: v.get_field_slice("value"),
get: v.get_field_slice("get"),
set: v.get_field_slice("set"),
})
}
}
/// Create a new object
pub fn make_object(_: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
Ok(Gc::new(ValueData::Undefined))
@ -244,17 +179,3 @@ pub fn _create(global: &Value) -> Value {
pub fn init(global: &Value) {
global.set_field_slice("Object", _create(global));
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn is_property_key_test() {
let v = Value::new(ValueData::String(String::from("Boop")));
assert!(Property::is_property_key(&v));
let v = Value::new(ValueData::Boolean(true));
assert!(!Property::is_property_key(&v));
}
}

81
src/lib/js/property.rs

@ -0,0 +1,81 @@
use crate::js::value::{from_value, to_value, FromValue, ToValue, Value, ValueData};
use gc::Gc;
use gc_derive::{Finalize, Trace};
/// A Javascript Property AKA The Property Descriptor
/// [[SPEC] - The Property Descriptor Specification Type](https://tc39.github.io/ecma262/#sec-property-descriptor-specification-type)
/// [[SPEC] - Default Attribute Values](https://tc39.github.io/ecma262/#table-4)
#[derive(Trace, Finalize, Clone, Debug)]
pub struct Property {
/// If the type of this can be changed and this can be deleted
pub configurable: bool,
/// If the property shows up in enumeration of the object
pub enumerable: bool,
/// If this property can be changed with an assignment
pub writable: bool,
/// The value associated with the property
pub value: Value,
/// The function serving as getter
pub get: Value,
/// The function serving as setter
pub set: Value,
}
impl Property {
/// Checks if the provided Value can be used as a property key.
pub fn is_property_key(value: &Value) -> bool {
value.is_string() // || value.is_symbol() // Uncomment this when we are handeling symbols.
}
/// Make a new property with the given value
pub fn new(value: Value) -> Self {
Self {
configurable: false,
enumerable: false,
writable: false,
value,
get: Gc::new(ValueData::Undefined),
set: Gc::new(ValueData::Undefined),
}
}
}
impl ToValue for Property {
fn to_value(&self) -> Value {
let prop = ValueData::new_obj(None);
prop.set_field_slice("configurable", to_value(self.configurable));
prop.set_field_slice("enumerable", to_value(self.enumerable));
prop.set_field_slice("writable", to_value(self.writable));
prop.set_field_slice("value", self.value.clone());
prop.set_field_slice("get", self.get.clone());
prop.set_field_slice("set", self.set.clone());
prop
}
}
impl FromValue for Property {
fn from_value(v: Value) -> Result<Self, &'static str> {
Ok(Self {
configurable: from_value(v.get_field_slice("configurable")).unwrap(),
enumerable: from_value(v.get_field_slice("enumerable")).unwrap(),
writable: from_value(v.get_field_slice("writable")).unwrap(),
value: v.get_field_slice("value"),
get: v.get_field_slice("get"),
set: v.get_field_slice("set"),
})
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn is_property_key_test() {
let v = Value::new(ValueData::String(String::from("Boop")));
assert!(Property::is_property_key(&v));
let v = Value::new(ValueData::Boolean(true));
assert!(!Property::is_property_key(&v));
}
}

3
src/lib/js/string.rs

@ -2,7 +2,8 @@ use crate::{
exec::Interpreter,
js::{
function::NativeFunctionData,
object::{ObjectKind, Property, PROTOTYPE},
object::{ObjectKind, PROTOTYPE},
property::Property,
value::{from_value, to_value, ResultValue, Value, ValueData},
},
};

3
src/lib/js/value.rs

@ -1,6 +1,7 @@
use crate::js::{
function::{Function, NativeFunction, NativeFunctionData},
object::{Object, ObjectKind, Property, INSTANCE_PROTOTYPE, PROTOTYPE},
object::{Object, ObjectKind, INSTANCE_PROTOTYPE, PROTOTYPE},
property::Property
};
use gc::{Gc, GcCell};
use gc_derive::{Finalize, Trace};

Loading…
Cancel
Save