1use crate::*;
2use std::fmt;
3use std::marker::PhantomData;
4
5#[derive(Clone)]
6pub struct Object {
7 pub(crate) mv8: MiniV8,
8 pub(crate) handle: v8::Global<v8::Object>,
9}
10
11impl Object {
12 pub fn get<K: ToValue, V: FromValue>(&self, key: K) -> Result<V> {
18 let key = key.to_value(&self.mv8)?;
19 self.mv8.try_catch(|scope| {
20 let object = v8::Local::new(scope, self.handle.clone());
21 let key = key.to_v8_value(scope);
22 let result = object.get(scope, key);
23 self.mv8.exception(scope)?;
24 Ok(Value::from_v8_value(&self.mv8, scope, result.unwrap()))
25 }).and_then(|v| v.into(&self.mv8))
26 }
27
28 pub fn set<K: ToValue, V: ToValue>(&self, key: K, value: V) -> Result<()> {
33 let key = key.to_value(&self.mv8)?;
34 let value = value.to_value(&self.mv8)?;
35 self.mv8.try_catch(|scope| {
36 let object = v8::Local::new(scope, self.handle.clone());
37 let key = key.to_v8_value(scope);
38 let value = value.to_v8_value(scope);
39 object.set(scope, key, value);
40 self.mv8.exception(scope)
41 })
42 }
43
44 pub fn remove<K: ToValue>(&self, key: K) -> Result<()> {
50 let key = key.to_value(&self.mv8)?;
51 self.mv8.try_catch(|scope| {
52 let object = v8::Local::new(scope, self.handle.clone());
53 let key = key.to_v8_value(scope);
54 object.delete(scope, key);
55 self.mv8.exception(scope)
56 })
57 }
58
59 pub fn has<K: ToValue>(&self, key: K) -> Result<bool> {
64 let key = key.to_value(&self.mv8)?;
65 self.mv8.try_catch(|scope| {
66 let object = v8::Local::new(scope, self.handle.clone());
67 let key = key.to_v8_value(scope);
68 let has = object.has(scope, key);
69 self.mv8.exception(scope)?;
70 Ok(has.unwrap())
71 })
72 }
73
74 pub fn call_prop<K, A, R>(&self, key: K, args: A) -> Result<R>
77 where
78 K: ToValue,
79 A: ToValues,
80 R: FromValue,
81 {
82 let func: Function = self.get(key)?;
83 func.call_method(self.clone(), args)
84 }
85
86 pub fn keys(&self, include_inherited: bool) -> Result<Array> {
92 self.mv8.try_catch(|scope| {
93 let object = v8::Local::new(scope, self.handle.clone());
94 let keys = if include_inherited {
95 object.get_property_names(scope, Default::default())
96 } else {
97 object.get_own_property_names(scope, Default::default())
98 };
99 self.mv8.exception(scope)?;
100 Ok(Array {
101 mv8: self.mv8.clone(),
102 handle: v8::Global::new(scope, keys.unwrap()),
103 })
104 })
105 }
106
107 pub fn properties<K, V>(self, include_inherited: bool) -> Result<Properties<K, V>>
112 where
113 K: FromValue,
114 V: FromValue,
115 {
116 let keys = self.keys(include_inherited)?;
117 Ok(Properties { object: self, keys, index: 0, _phantom: PhantomData })
118 }
119}
120
121impl fmt::Debug for Object {
122 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
123 let keys = match self.keys(false) {
124 Ok(keys) => keys,
125 Err(_) => return write!(f, "<object with keys exception>"),
126 };
127
128 let len = keys.len();
129 if len == 0 {
130 return write!(f, "{{}}");
131 }
132
133 write!(f, "{{ ")?;
134 for i in 0..len {
135 if let Ok(k) = keys.get::<Value>(i).and_then(|k| k.coerce_string(&self.mv8)) {
136 write!(f, "{:?}: ", k)?;
137 match self.get::<_, Value>(k) {
138 Ok(v) => write!(f, "{:?}", v)?,
139 Err(_) => write!(f, "?")?,
140 };
141 } else {
142 write!(f, "?")?;
143 }
144 if i + 1 < len {
145 write!(f, ", ")?;
146 }
147 }
148 write!(f, " }}")
149 }
150}
151
152pub struct Properties<K, V> {
154 object: Object,
155 keys: Array,
156 index: u32,
157 _phantom: PhantomData<(K, V)>,
158}
159
160impl<K, V> Iterator for Properties<K, V>
161where
162 K: FromValue,
163 V: FromValue,
164{
165 type Item = Result<(K, V)>;
166
167 fn next(&mut self) -> Option<Self::Item> {
170 if self.index >= self.keys.len() {
171 return None;
172 }
173
174 let key = self.keys.get::<Value>(self.index);
175 self.index += 1;
176
177 let key = match key {
178 Ok(v) => v,
179 Err(e) => return Some(Err(e)),
180 };
181
182 let value = match self.object.get::<_, V>(key.clone()) {
183 Ok(v) => v,
184 Err(e) => return Some(Err(e)),
185 };
186
187 let key = match key.into(&self.object.mv8) {
188 Ok(v) => v,
189 Err(e) => return Some(Err(e)),
190 };
191
192 Some(Ok((key, value)))
193 }
194}