1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use libquickjspp_sys as q;
use crate::{ExecutionError, ValueError};
use super::OwnedJsValue;
pub struct OwnedJsArray {
value: OwnedJsValue,
}
impl OwnedJsArray {
pub fn try_from_value(value: OwnedJsValue) -> Result<Self, ValueError> {
if !value.is_array() {
Err(ValueError::Internal("Expected an array".into()))
} else {
Ok(Self { value })
}
}
pub fn length(&self) -> u64 {
let mut next_index: i64 = 0;
unsafe {
q::JS_GetPropertyLength(
self.value.context(),
&mut next_index as *mut _,
self.value.value,
);
}
next_index as u64
}
pub fn get_index(&self, index: u32) -> Result<Option<OwnedJsValue>, ExecutionError> {
let value_raw =
unsafe { q::JS_GetPropertyUint32(self.value.context(), self.value.value, index) };
let tag = unsafe { q::JS_ValueGetTag(value_raw) };
if tag == q::JS_TAG_EXCEPTION {
return Err(ExecutionError::Internal("Could not build array".into()));
} else if tag == q::JS_TAG_UNDEFINED {
return Ok(None);
}
Ok(Some(OwnedJsValue::new(self.value.context(), value_raw)))
}
pub fn set_index(&self, index: u32, value: OwnedJsValue) -> Result<(), ExecutionError> {
unsafe {
// NOTE: SetPropertyStr takes ownership of the value.
// We do not, however, call OwnedJsValue::extract immediately, so
// the inner JSValue is still managed.
// `mem::forget` is called below only if SetProperty succeeds.
// This prevents leaks when an error occurs.
let ret =
q::JS_SetPropertyUint32(self.value.context(), self.value.value, index, value.value);
if ret < 0 {
Err(ExecutionError::Internal("Could not set property".into()))
} else {
// Now we can call forget to prevent calling the destructor.
std::mem::forget(value);
Ok(())
}
}
}
pub fn push(&self, value: OwnedJsValue) -> Result<(), ExecutionError> {
unsafe {
let mut next_index: i64 = 0;
q::JS_GetPropertyLength(
self.value.context(),
&mut next_index as *mut _,
self.value.value,
);
// NOTE: SetPropertyStr takes ownership of the value.
// We do not, however, call OwnedJsValue::extract immediately, so
// the inner JSValue is still managed.
// `mem::forget` is called below only if SetProperty succeeds.
// This prevents leaks when an error occurs.
let ret = q::JS_SetPropertyInt64(
self.value.context(),
self.value.value,
next_index,
value.value,
);
if ret < 0 {
Err(ExecutionError::Internal(
"Could not set property".to_string(),
))
} else {
// Now we can call forget to prevent calling the destructor.
std::mem::forget(value);
Ok(())
}
}
}
pub fn raw_elements(&self) -> Vec<q::JSValue> {
let mut ret = vec![];
let length = self.length() as u32;
for i in 0..length {
let value_raw =
unsafe { q::JS_GetPropertyUint32(self.value.context(), self.value.value, i) };
ret.push(value_raw);
}
ret
}
}