Browse Source

Added some documentation to object

pull/293/head
HalidOdat 5 years ago
parent
commit
afb09173d5
  1. 1
      boa/src/builtins/mod.rs
  2. 37
      boa/src/builtins/object/internal_methods_trait.rs
  3. 114
      boa/src/builtins/object/mod.rs

1
boa/src/builtins/mod.rs

@ -21,7 +21,6 @@ pub mod function;
pub mod json; pub mod json;
pub mod math; pub mod math;
pub mod number; pub mod number;
/// The global `Object` object
pub mod object; pub mod object;
pub mod property; pub mod property;
pub mod regexp; pub mod regexp;

37
boa/src/builtins/object/internal_methods_trait.rs

@ -1,3 +1,10 @@
//! This module defines the `ObjectInternalMethods` trait.
//!
//! More information:
//! - [ECMAScript reference][spec]
//!
//! [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots
use crate::builtins::{ use crate::builtins::{
object::{Object, PROTOTYPE}, object::{Object, PROTOTYPE},
property::Property, property::Property,
@ -8,11 +15,21 @@ use std::borrow::Borrow;
use std::ops::Deref; use std::ops::Deref;
/// Here lies the internal methods for ordinary objects. /// Here lies the internal methods for ordinary objects.
///
/// Most objects make use of these methods, including exotic objects like functions. /// Most objects make use of these methods, including exotic objects like functions.
/// So thats why this is a trait /// So thats why this is a trait
/// <https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots> ///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots
pub trait ObjectInternalMethods { pub trait ObjectInternalMethods {
/// https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-hasproperty-p /// Check if has property.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-hasproperty-p
fn has_property(&self, val: &Value) -> bool { fn has_property(&self, val: &Value) -> bool {
debug_assert!(Property::is_property_key(val)); debug_assert!(Property::is_property_key(val));
let prop = self.get_own_property(val); let prop = self.get_own_property(val);
@ -32,7 +49,12 @@ pub trait ObjectInternalMethods {
true true
} }
/// https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-isextensible /// Check if it is extensible.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-isextensible
fn is_extensible(&self) -> bool { fn is_extensible(&self) -> bool {
let val = self.get_internal_slot("extensible"); let val = self.get_internal_slot("extensible");
match *val.deref().borrow() { match *val.deref().borrow() {
@ -41,13 +63,18 @@ pub trait ObjectInternalMethods {
} }
} }
/// https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-preventextensions /// Disable extensibility.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-preventextensions
fn prevent_extensions(&mut self) -> bool { fn prevent_extensions(&mut self) -> bool {
self.set_internal_slot("extensible", to_value(false)); self.set_internal_slot("extensible", to_value(false));
true true
} }
// [[Delete]] /// Delete property.
fn delete(&mut self, prop_key: &Value) -> bool { fn delete(&mut self, prop_key: &Value) -> bool {
debug_assert!(Property::is_property_key(prop_key)); debug_assert!(Property::is_property_key(prop_key));
let desc = self.get_own_property(prop_key); let desc = self.get_own_property(prop_key);

114
boa/src/builtins/object/mod.rs

@ -1,3 +1,18 @@
//! This module implements the global `Object` object.
//!
//! The `Object` class represents one of JavaScript's data types.
//!
//! It is used to store various keyed collections and more complex entities.
//! Objects can be created using the `Object()` constructor or the
//! object initializer / literal syntax.
//!
//! More information:
//! - [ECMAScript reference][spec]
//! - [MDN documentation][mdn]
//!
//! [spec]: https://tc39.es/ecma262/#sec-objects
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
use crate::{ use crate::{
builtins::{ builtins::{
function::NativeFunctionData, function::NativeFunctionData,
@ -22,12 +37,12 @@ pub static PROTOTYPE: &str = "prototype";
/// Static `__proto__`, usually set on Object instances as a key to point to their respective prototype object. /// Static `__proto__`, usually set on Object instances as a key to point to their respective prototype object.
pub static INSTANCE_PROTOTYPE: &str = "__proto__"; pub static INSTANCE_PROTOTYPE: &str = "__proto__";
/// `ObjectData` is the representation of an object in JavaScript /// The internal representation of an JavaScript object.
#[derive(Trace, Finalize, Debug, Clone)] #[derive(Trace, Finalize, Debug, Clone)]
pub struct Object { pub struct Object {
/// Kind /// The type of the object.
pub kind: ObjectKind, pub kind: ObjectKind,
/// Internal Slots /// Intfiernal Slots
pub internal_slots: Box<HashMap<String, Value>>, pub internal_slots: Box<HashMap<String, Value>>,
/// Properties /// Properties
pub properties: Box<HashMap<String, Property>>, pub properties: Box<HashMap<String, Property>>,
@ -38,7 +53,17 @@ pub struct Object {
} }
impl ObjectInternalMethods for Object { impl ObjectInternalMethods for Object {
/// https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-setprototypeof-v /// `Object.setPropertyOf(obj, prototype)`
///
/// This method sets the prototype (i.e., the internal `[[Prototype]]` property)
/// of a specified object to another object or `null`.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-setprototypeof-v
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf
fn set_prototype_of(&mut self, val: Value) -> bool { fn set_prototype_of(&mut self, val: Value) -> bool {
debug_assert!(val.is_object() || val.is_null()); debug_assert!(val.is_object() || val.is_null());
let current = self.get_internal_slot(PROTOTYPE); let current = self.get_internal_slot(PROTOTYPE);
@ -64,20 +89,22 @@ impl ObjectInternalMethods for Object {
true true
} }
/// Helper function for property insertion.
fn insert_property(&mut self, name: String, p: Property) { fn insert_property(&mut self, name: String, p: Property) {
self.properties.insert(name, p); self.properties.insert(name, p);
} }
/// Helper function for property removal.
fn remove_property(&mut self, name: &str) { fn remove_property(&mut self, name: &str) {
self.properties.remove(name); self.properties.remove(name);
} }
/// Utility function to set an internal slot /// Helper function to set an internal slot
fn set_internal_slot(&mut self, name: &str, val: Value) { fn set_internal_slot(&mut self, name: &str, val: Value) {
self.internal_slots.insert(name.to_string(), val); self.internal_slots.insert(name.to_string(), val);
} }
/// Utility function to get an immutable internal slot or Null /// Helper function to get an immutable internal slot or Null
fn get_internal_slot(&self, name: &str) -> Value { fn get_internal_slot(&self, name: &str) -> Value {
match self.internal_slots.get(name) { match self.internal_slots.get(name) {
Some(v) => v.clone(), Some(v) => v.clone(),
@ -85,8 +112,14 @@ impl ObjectInternalMethods for Object {
} }
} }
/// https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-getownproperty-p /// The specification returns a Property Descriptor or Undefined.
/// The specification returns a Property Descriptor or Undefined. These are 2 separate types and we can't do that here. ///
/// These are 2 separate types and we can't do that here.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-getownproperty-p
fn get_own_property(&self, prop: &Value) -> Property { fn get_own_property(&self, prop: &Value) -> Property {
debug_assert!(Property::is_property_key(prop)); debug_assert!(Property::is_property_key(prop));
// Prop could either be a String or Symbol // Prop could either be a String or Symbol
@ -143,6 +176,12 @@ impl ObjectInternalMethods for Object {
} }
} }
/// Define an own property.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-defineownproperty-p-desc
#[allow(clippy::option_unwrap_used)] #[allow(clippy::option_unwrap_used)]
fn define_own_property(&mut self, property_key: String, desc: Property) -> bool { fn define_own_property(&mut self, property_key: String, desc: Property) -> bool {
let mut current = self.get_own_property(&to_value(property_key.to_string())); let mut current = self.get_own_property(&to_value(property_key.to_string()));
@ -285,9 +324,12 @@ impl Object {
object object
} }
/// ObjectCreate is used to specify the runtime creation of new ordinary objects /// ObjectCreate is used to specify the runtime creation of new ordinary objects.
///
/// More information:
/// - [ECMAScript reference][spec]
/// ///
/// https://tc39.es/ecma262/#sec-objectcreate /// [spec]: https://tc39.es/ecma262/#sec-objectcreate
// TODO: proto should be a &Value here // TODO: proto should be a &Value here
pub fn create(proto: Value) -> Object { pub fn create(proto: Value) -> Object {
let mut obj = Object::default(); let mut obj = Object::default();
@ -298,19 +340,20 @@ impl Object {
obj obj
} }
/// Utility function to set an internal slot which is a function /// Utility function to set an internal slot which is a function.
pub fn set_internal_method(&mut self, name: &str, val: NativeFunctionData) { pub fn set_internal_method(&mut self, name: &str, val: NativeFunctionData) {
self.internal_slots.insert(name.to_string(), to_value(val)); self.internal_slots.insert(name.to_string(), to_value(val));
} }
/// Utility function to set a method on this object /// Utility function to set a method on this object.
/// The native function will live in the `properties` field of the Object ///
/// The native function will live in the `properties` field of the Object.
pub fn set_method(&mut self, name: &str, val: NativeFunctionData) { pub fn set_method(&mut self, name: &str, val: NativeFunctionData) {
self.properties self.properties
.insert(name.to_string(), Property::default().value(to_value(val))); .insert(name.to_string(), Property::default().value(to_value(val)));
} }
/// Return a new Boolean object whose [[BooleanData]] internal slot is set to argument. /// Return a new Boolean object whose `[[BooleanData]]` internal slot is set to argument.
fn from_boolean(argument: &Value) -> Self { fn from_boolean(argument: &Value) -> Self {
let mut obj = Object { let mut obj = Object {
kind: ObjectKind::Boolean, kind: ObjectKind::Boolean,
@ -325,7 +368,7 @@ impl Object {
obj obj
} }
/// Return a new Number object whose [[NumberData]] internal slot is set to argument. /// Return a new `Number` object whose `[[NumberData]]` internal slot is set to argument.
fn from_number(argument: &Value) -> Self { fn from_number(argument: &Value) -> Self {
let mut obj = Object { let mut obj = Object {
kind: ObjectKind::Number, kind: ObjectKind::Number,
@ -340,7 +383,7 @@ impl Object {
obj obj
} }
/// Return a new String object whose [[StringData]] internal slot is set to argument. /// Return a new `String` object whose `[[StringData]]` internal slot is set to argument.
fn from_string(argument: &Value) -> Self { fn from_string(argument: &Value) -> Self {
let mut obj = Object { let mut obj = Object {
kind: ObjectKind::String, kind: ObjectKind::String,
@ -355,7 +398,12 @@ impl Object {
obj obj
} }
// https://tc39.es/ecma262/#sec-toobject /// Converts the `Value` to an `Object` type.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-toobject
pub fn from(value: &Value) -> Result<Self, ()> { pub fn from(value: &Value) -> Result<Self, ()> {
match *value.deref().borrow() { match *value.deref().borrow() {
ValueData::Boolean(_) => Ok(Self::from_boolean(value)), ValueData::Boolean(_) => Ok(Self::from_boolean(value)),
@ -367,6 +415,7 @@ impl Object {
} }
} }
/// Defines the different types of objects.
#[derive(Trace, Finalize, Clone, Debug, Eq, PartialEq)] #[derive(Trace, Finalize, Clone, Debug, Eq, PartialEq)]
pub enum ObjectKind { pub enum ObjectKind {
Function, Function,
@ -379,18 +428,18 @@ pub enum ObjectKind {
Number, Number,
} }
/// Create a new object /// Create a new object.
pub fn make_object(_: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue { pub fn make_object(_: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
Ok(Gc::new(ValueData::Undefined)) Ok(Gc::new(ValueData::Undefined))
} }
/// Get the prototype of an object /// Get the `prototype` of an object.
pub fn get_proto_of(_: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { pub fn get_proto_of(_: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
let obj = args.get(0).expect("Cannot get object"); let obj = args.get(0).expect("Cannot get object");
Ok(obj.get_field_slice(INSTANCE_PROTOTYPE)) Ok(obj.get_field_slice(INSTANCE_PROTOTYPE))
} }
/// Set the prototype of an object /// Set the `prototype` of an object.
pub fn set_proto_of(_: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { pub fn set_proto_of(_: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
let obj = args.get(0).expect("Cannot get object").clone(); let obj = args.get(0).expect("Cannot get object").clone();
let proto = args.get(1).expect("Cannot get object").clone(); let proto = args.get(1).expect("Cannot get object").clone();
@ -409,12 +458,31 @@ pub fn define_prop(_: &Value, args: &[Value], _: &mut Interpreter) -> ResultValu
Ok(Gc::new(ValueData::Undefined)) Ok(Gc::new(ValueData::Undefined))
} }
/// To string /// `Object.prototype.toString()`
///
/// This method returns a string representing the object.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-object.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
pub fn to_string(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue { pub fn to_string(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
Ok(to_value(this.to_string())) Ok(to_value(this.to_string()))
} }
/// Check if it has a property /// `Object.prototype.hasOwnPrototype( property )`
///
/// The method returns a boolean indicating whether the object has the specified property
/// as its own property (as opposed to inheriting it).
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-object.prototype.hasownproperty
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
pub fn has_own_prop(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { pub fn has_own_prop(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
let prop = if args.is_empty() { let prop = if args.is_empty() {
None None
@ -426,7 +494,7 @@ pub fn has_own_prop(this: &Value, args: &[Value], _: &mut Interpreter) -> Result
)) ))
} }
/// Create a new `Object` object /// Create a new `Object` object.
pub fn create_constructor(_: &Value) -> Value { pub fn create_constructor(_: &Value) -> Value {
let object = to_value(make_object as NativeFunctionData); let object = to_value(make_object as NativeFunctionData);
// Prototype chain ends here VV // Prototype chain ends here VV

Loading…
Cancel
Save