|
|
|
@ -44,8 +44,8 @@ mod tests;
|
|
|
|
|
/// Static `prototype`, usually set on constructors as a key to point to their respective prototype object.
|
|
|
|
|
pub static PROTOTYPE: &str = "prototype"; |
|
|
|
|
|
|
|
|
|
/// Static `__proto__`, usually set on Object instances as a key to point to their respective prototype object.
|
|
|
|
|
pub static INSTANCE_PROTOTYPE: &str = "__proto__"; |
|
|
|
|
// /// Static `__proto__`, usually set on Object instances as a key to point to their respective prototype object.
|
|
|
|
|
// pub static INSTANCE_PROTOTYPE: &str = "__proto__";
|
|
|
|
|
|
|
|
|
|
/// The internal representation of an JavaScript object.
|
|
|
|
|
#[derive(Debug, Trace, Finalize, Clone)] |
|
|
|
@ -58,6 +58,8 @@ pub struct Object {
|
|
|
|
|
properties: FxHashMap<RcString, Property>, |
|
|
|
|
/// Symbol Properties
|
|
|
|
|
symbol_properties: FxHashMap<u32, Property>, |
|
|
|
|
/// Instance prototype `__proto__`.
|
|
|
|
|
prototype: Value, |
|
|
|
|
/// Some rust object that stores internal state
|
|
|
|
|
state: Option<InternalStateCell>, |
|
|
|
|
/// Whether it can have new properties added to it.
|
|
|
|
@ -109,6 +111,7 @@ impl Default for Object {
|
|
|
|
|
internal_slots: FxHashMap::default(), |
|
|
|
|
properties: FxHashMap::default(), |
|
|
|
|
symbol_properties: FxHashMap::default(), |
|
|
|
|
prototype: Value::null(), |
|
|
|
|
state: None, |
|
|
|
|
extensible: true, |
|
|
|
|
} |
|
|
|
@ -122,7 +125,7 @@ impl Object {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Return a new ObjectData struct, with `kind` set to Ordinary
|
|
|
|
|
pub fn function(function: Function) -> Self { |
|
|
|
|
pub fn function(function: Function, prototype: Value) -> Self { |
|
|
|
|
let _timer = BoaProfiler::global().start_event("Object::Function", "object"); |
|
|
|
|
|
|
|
|
|
Self { |
|
|
|
@ -130,6 +133,7 @@ impl Object {
|
|
|
|
|
internal_slots: FxHashMap::default(), |
|
|
|
|
properties: FxHashMap::default(), |
|
|
|
|
symbol_properties: FxHashMap::default(), |
|
|
|
|
prototype, |
|
|
|
|
state: None, |
|
|
|
|
extensible: true, |
|
|
|
|
} |
|
|
|
@ -144,8 +148,7 @@ impl Object {
|
|
|
|
|
// TODO: proto should be a &Value here
|
|
|
|
|
pub fn create(proto: Value) -> Self { |
|
|
|
|
let mut obj = Self::default(); |
|
|
|
|
obj.internal_slots |
|
|
|
|
.insert(INSTANCE_PROTOTYPE.to_string(), proto); |
|
|
|
|
obj.prototype = proto; |
|
|
|
|
obj |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -156,6 +159,7 @@ impl Object {
|
|
|
|
|
internal_slots: FxHashMap::default(), |
|
|
|
|
properties: FxHashMap::default(), |
|
|
|
|
symbol_properties: FxHashMap::default(), |
|
|
|
|
prototype: Value::null(), |
|
|
|
|
state: None, |
|
|
|
|
extensible: true, |
|
|
|
|
} |
|
|
|
@ -168,6 +172,7 @@ impl Object {
|
|
|
|
|
internal_slots: FxHashMap::default(), |
|
|
|
|
properties: FxHashMap::default(), |
|
|
|
|
symbol_properties: FxHashMap::default(), |
|
|
|
|
prototype: Value::null(), |
|
|
|
|
state: None, |
|
|
|
|
extensible: true, |
|
|
|
|
} |
|
|
|
@ -183,6 +188,7 @@ impl Object {
|
|
|
|
|
internal_slots: FxHashMap::default(), |
|
|
|
|
properties: FxHashMap::default(), |
|
|
|
|
symbol_properties: FxHashMap::default(), |
|
|
|
|
prototype: Value::null(), |
|
|
|
|
state: None, |
|
|
|
|
extensible: true, |
|
|
|
|
} |
|
|
|
@ -195,6 +201,7 @@ impl Object {
|
|
|
|
|
internal_slots: FxHashMap::default(), |
|
|
|
|
properties: FxHashMap::default(), |
|
|
|
|
symbol_properties: FxHashMap::default(), |
|
|
|
|
prototype: Value::null(), |
|
|
|
|
state: None, |
|
|
|
|
extensible: true, |
|
|
|
|
} |
|
|
|
@ -419,6 +426,15 @@ impl Object {
|
|
|
|
|
pub fn state_mut(&mut self) -> &mut Option<InternalStateCell> { |
|
|
|
|
&mut self.state |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn prototype(&self) -> &Value { |
|
|
|
|
&self.prototype |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn set_prototype(&mut self, prototype: Value) { |
|
|
|
|
assert!(prototype.is_null() || prototype.is_object()); |
|
|
|
|
self.prototype = prototype |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Create a new object.
|
|
|
|
@ -476,14 +492,16 @@ pub fn is(_: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
|
|
|
|
|
/// Get the `prototype` of an object.
|
|
|
|
|
pub fn get_prototype_of(_: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
let obj = args.get(0).expect("Cannot get object"); |
|
|
|
|
Ok(obj.get_field(INSTANCE_PROTOTYPE)) |
|
|
|
|
Ok(obj |
|
|
|
|
.as_object() |
|
|
|
|
.map_or_else(Value::undefined, |object| object.prototype.clone())) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Set the `prototype` of an object.
|
|
|
|
|
pub fn set_prototype_of(_: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
let obj = args.get(0).expect("Cannot get object").clone(); |
|
|
|
|
let proto = args.get(1).expect("Cannot get object").clone(); |
|
|
|
|
obj.set_internal_slot(INSTANCE_PROTOTYPE, proto); |
|
|
|
|
obj.as_object_mut().unwrap().prototype = proto; |
|
|
|
|
Ok(obj) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|