use crate::quickjsrealmadapter::QuickJsRealmAdapter;
use crate::valueref::JSValueRef;
use hirofa_utils::js_utils::JsError;
use libquickjs_sys as q;
pub fn is_array_q(q_ctx: &QuickJsRealmAdapter, obj_ref: &JSValueRef) -> bool {
unsafe { is_array(q_ctx.context, obj_ref) }
}
pub unsafe fn is_array(context: *mut q::JSContext, obj_ref: &JSValueRef) -> bool {
let r = obj_ref.borrow_value();
let val = q::JS_IsArray(context, *r);
val > 0
}
pub fn get_length_q(q_ctx: &QuickJsRealmAdapter, arr_ref: &JSValueRef) -> Result<u32, JsError> {
unsafe { get_length(q_ctx.context, arr_ref) }
}
pub unsafe fn get_length(context: *mut q::JSContext, arr_ref: &JSValueRef) -> Result<u32, JsError> {
let len_ref = crate::quickjs_utils::objects::get_property(context, arr_ref, "length")?;
let len = crate::quickjs_utils::primitives::to_i32(&len_ref)?;
Ok(len as u32)
}
pub fn create_array_q(q_ctx: &QuickJsRealmAdapter) -> Result<JSValueRef, JsError> {
unsafe { create_array(q_ctx.context) }
}
pub unsafe fn create_array(context: *mut q::JSContext) -> Result<JSValueRef, JsError> {
let arr = q::JS_NewArray(context);
let arr_ref = JSValueRef::new(context, arr, false, true, "create_array");
if arr_ref.is_exception() {
return Err(JsError::new_str("Could not create array in runtime"));
}
Ok(arr_ref)
}
pub fn set_element_q(
q_ctx: &QuickJsRealmAdapter,
array_ref: &JSValueRef,
index: u32,
entry_value_ref: &JSValueRef,
) -> Result<(), JsError> {
unsafe { set_element(q_ctx.context, array_ref, index, entry_value_ref) }
}
pub unsafe fn set_element(
context: *mut q::JSContext,
array_ref: &JSValueRef,
index: u32,
entry_value_ref: &JSValueRef,
) -> Result<(), JsError> {
let entry_value_ref = entry_value_ref;
let ret = q::JS_DefinePropertyValueUint32(
context,
*array_ref.borrow_value(),
index,
entry_value_ref.clone_value_incr_rc(),
q::JS_PROP_C_W_E as i32,
);
if ret < 0 {
return Err(JsError::new_str("Could not append element to array"));
}
Ok(())
}
pub fn get_element_q(
q_ctx: &QuickJsRealmAdapter,
array_ref: &JSValueRef,
index: u32,
) -> Result<JSValueRef, JsError> {
unsafe { get_element(q_ctx.context, array_ref, index) }
}
pub unsafe fn get_element(
context: *mut q::JSContext,
array_ref: &JSValueRef,
index: u32,
) -> Result<JSValueRef, JsError> {
let value_raw = q::JS_GetPropertyUint32(context, *array_ref.borrow_value(), index);
let ret = JSValueRef::new(
context,
value_raw,
false,
true,
format!("get_element[{}]", index).as_str(),
);
if ret.is_exception() {
return Err(JsError::new_str("Could not build array"));
}
Ok(ret)
}
#[cfg(test)]
pub mod tests {
use crate::facades::tests::init_test_rt;
use crate::quickjs_utils::arrays::{create_array_q, get_element_q, set_element_q};
use crate::quickjs_utils::objects;
#[test]
fn test_array() {
let rt = init_test_rt();
rt.exe_rt_task_in_event_loop(|q_js_rt| {
let q_ctx = q_js_rt.get_main_context();
let arr = create_array_q(q_ctx).ok().unwrap();
assert_eq!(arr.get_ref_count(), 1);
let a = objects::create_object_q(q_ctx).ok().unwrap();
assert_eq!(1, a.get_ref_count());
set_element_q(q_ctx, &arr, 0, &a).ok().unwrap();
assert_eq!(2, a.get_ref_count());
let a2 = get_element_q(q_ctx, &arr, 0).ok().unwrap();
assert_eq!(3, a.get_ref_count());
assert_eq!(3, a2.get_ref_count());
});
}
}