neon/sys/object.rs
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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
use std::mem::MaybeUninit;
use super::{
bindings as napi,
raw::{Env, Local},
};
/// Mutates the `out` argument to refer to a `napi_value` containing a newly created JavaScript Object.
pub unsafe fn new(out: &mut Local, env: Env) {
napi::create_object(env, out as *mut _).unwrap();
}
#[cfg(feature = "napi-8")]
pub unsafe fn freeze(env: Env, obj: Local) -> Result<(), napi::Status> {
let status = napi::object_freeze(env, obj);
debug_assert!(matches!(
status,
Ok(()) | Err(napi::Status::PendingException | napi::Status::GenericFailure)
));
status
}
#[cfg(feature = "napi-8")]
pub unsafe fn seal(env: Env, obj: Local) -> Result<(), napi::Status> {
napi::object_seal(env, obj)
}
#[cfg(feature = "napi-6")]
/// Mutates the `out` argument to refer to a `napi_value` containing the own property names of the
/// `object` as a JavaScript Array.
pub unsafe fn get_own_property_names(out: &mut Local, env: Env, object: Local) -> bool {
let mut property_names = MaybeUninit::uninit();
match napi::get_all_property_names(
env,
object,
napi::KeyCollectionMode::OwnOnly,
napi::KeyFilter::ALL_PROPERTIES | napi::KeyFilter::SKIP_SYMBOLS,
napi::KeyConversion::NumbersToStrings,
property_names.as_mut_ptr(),
) {
Err(napi::Status::PendingException) => return false,
status => status.unwrap(),
}
*out = property_names.assume_init();
true
}
/// Mutate the `out` argument to refer to the value at `index` in the given `object`. Returns `false` if the value couldn't be retrieved.
pub unsafe fn get_index(out: &mut Local, env: Env, object: Local, index: u32) -> bool {
let status = napi::get_element(env, object, index, out as *mut _);
status.is_ok()
}
/// Sets the key value of a `napi_value` at the `index` provided. Returns `true` if the set
/// succeeded.
///
/// The `out` parameter and the return value contain the same information for historical reasons,
/// see [discussion].
///
/// [discussion]: https://github.com/neon-bindings/neon/pull/458#discussion_r344827965
pub unsafe fn set_index(out: &mut bool, env: Env, object: Local, index: u32, val: Local) -> bool {
let status = napi::set_element(env, object, index, val);
*out = status.is_ok();
*out
}
/// Mutate the `out` argument to refer to the value at a named `key` in the given `object`. Returns `false` if the value couldn't be retrieved.
pub unsafe fn get_string(
env: Env,
out: &mut Local,
object: Local,
key: *const u8,
len: i32,
) -> bool {
let mut key_val = MaybeUninit::uninit();
// Not using `crate::string::new()` because it requires a _reference_ to a Local,
// while we only have uninitialized memory.
match napi::create_string_utf8(env, key as *const _, len as usize, key_val.as_mut_ptr()) {
Err(napi::Status::PendingException) => return false,
status => status.unwrap(),
}
// Not using napi_get_named_property() because the `key` may not be null terminated.
match napi::get_property(env, object, key_val.assume_init(), out as *mut _) {
Err(napi::Status::PendingException) => return false,
status => status.unwrap(),
}
true
}
/// Sets the key value of a `napi_value` at a named key. Returns `true` if the set succeeded.
///
/// The `out` parameter and the return value contain the same information for historical reasons,
/// see [discussion].
///
/// [discussion]: https://github.com/neon-bindings/neon/pull/458#discussion_r344827965
pub unsafe fn set_string(
env: Env,
out: &mut bool,
object: Local,
key: *const u8,
len: i32,
val: Local,
) -> bool {
let mut key_val = MaybeUninit::uninit();
*out = true;
match napi::create_string_utf8(env, key as *const _, len as usize, key_val.as_mut_ptr()) {
Err(napi::Status::PendingException) => {
*out = false;
return false;
}
status => status.unwrap(),
}
match napi::set_property(env, object, key_val.assume_init(), val) {
Err(napi::Status::PendingException) => {
*out = false;
return false;
}
status => status.unwrap(),
}
true
}
/// Mutates `out` to refer to the value of the property of `object` named by the `key` value.
/// Returns false if the value couldn't be retrieved.
pub unsafe fn get(out: &mut Local, env: Env, object: Local, key: Local) -> bool {
let status = napi::get_property(env, object, key, out as *mut _);
status.is_ok()
}
/// Sets the property value of an `napi_value` object, named by another `value` `key`. Returns `true` if the set succeeded.
///
/// The `out` parameter and the return value contain the same information for historical reasons,
/// see [discussion].
///
/// [discussion]: https://github.com/neon-bindings/neon/pull/458#discussion_r344827965
pub unsafe fn set(out: &mut bool, env: Env, object: Local, key: Local, val: Local) -> bool {
let status = napi::set_property(env, object, key, val);
*out = status.is_ok();
*out
}