neon/sys/
object.rs

1use std::mem::MaybeUninit;
2
3use super::{
4    bindings as napi,
5    raw::{Env, Local},
6};
7
8/// Mutates the `out` argument to refer to a `napi_value` containing a newly created JavaScript Object.
9pub unsafe fn new(out: &mut Local, env: Env) {
10    napi::create_object(env, out as *mut _).unwrap();
11}
12
13#[cfg(feature = "napi-8")]
14pub unsafe fn freeze(env: Env, obj: Local) -> Result<(), napi::Status> {
15    let status = napi::object_freeze(env, obj);
16    debug_assert!(matches!(
17        status,
18        Ok(()) | Err(napi::Status::PendingException | napi::Status::GenericFailure)
19    ));
20    status
21}
22
23#[cfg(feature = "napi-8")]
24pub unsafe fn seal(env: Env, obj: Local) -> Result<(), napi::Status> {
25    napi::object_seal(env, obj)
26}
27
28#[cfg(feature = "napi-6")]
29/// Mutates the `out` argument to refer to a `napi_value` containing the own property names of the
30/// `object` as a JavaScript Array.
31pub unsafe fn get_own_property_names(out: &mut Local, env: Env, object: Local) -> bool {
32    let mut property_names = MaybeUninit::uninit();
33
34    match napi::get_all_property_names(
35        env,
36        object,
37        napi::KeyCollectionMode::OwnOnly,
38        napi::KeyFilter::ALL_PROPERTIES | napi::KeyFilter::SKIP_SYMBOLS,
39        napi::KeyConversion::NumbersToStrings,
40        property_names.as_mut_ptr(),
41    ) {
42        Err(napi::Status::PendingException) => return false,
43        status => status.unwrap(),
44    }
45
46    *out = property_names.assume_init();
47
48    true
49}
50
51/// Mutate the `out` argument to refer to the value at `index` in the given `object`. Returns `false` if the value couldn't be retrieved.
52pub unsafe fn get_index(out: &mut Local, env: Env, object: Local, index: u32) -> bool {
53    let status = napi::get_element(env, object, index, out as *mut _);
54
55    status.is_ok()
56}
57
58/// Sets the key value of a `napi_value` at the `index` provided. Returns `true` if the set
59/// succeeded.
60///
61/// The `out` parameter and the return value contain the same information for historical reasons,
62/// see [discussion].
63///
64/// [discussion]: https://github.com/neon-bindings/neon/pull/458#discussion_r344827965
65pub unsafe fn set_index(out: &mut bool, env: Env, object: Local, index: u32, val: Local) -> bool {
66    let status = napi::set_element(env, object, index, val);
67    *out = status.is_ok();
68
69    *out
70}
71
72/// 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.
73pub unsafe fn get_string(
74    env: Env,
75    out: &mut Local,
76    object: Local,
77    key: *const u8,
78    len: i32,
79) -> bool {
80    let mut key_val = MaybeUninit::uninit();
81
82    // Not using `crate::string::new()` because it requires a _reference_ to a Local,
83    // while we only have uninitialized memory.
84    match napi::create_string_utf8(env, key as *const _, len as usize, key_val.as_mut_ptr()) {
85        Err(napi::Status::PendingException) => return false,
86        status => status.unwrap(),
87    }
88
89    // Not using napi_get_named_property() because the `key` may not be null terminated.
90    match napi::get_property(env, object, key_val.assume_init(), out as *mut _) {
91        Err(napi::Status::PendingException) => return false,
92        status => status.unwrap(),
93    }
94
95    true
96}
97
98/// Sets the key value of a `napi_value` at a named key. Returns `true` if the set succeeded.
99///
100/// The `out` parameter and the return value contain the same information for historical reasons,
101/// see [discussion].
102///
103/// [discussion]: https://github.com/neon-bindings/neon/pull/458#discussion_r344827965
104pub unsafe fn set_string(
105    env: Env,
106    out: &mut bool,
107    object: Local,
108    key: *const u8,
109    len: i32,
110    val: Local,
111) -> bool {
112    let mut key_val = MaybeUninit::uninit();
113
114    *out = true;
115
116    match napi::create_string_utf8(env, key as *const _, len as usize, key_val.as_mut_ptr()) {
117        Err(napi::Status::PendingException) => {
118            *out = false;
119            return false;
120        }
121        status => status.unwrap(),
122    }
123
124    match napi::set_property(env, object, key_val.assume_init(), val) {
125        Err(napi::Status::PendingException) => {
126            *out = false;
127            return false;
128        }
129        status => status.unwrap(),
130    }
131
132    true
133}
134
135/// Mutates `out` to refer to the value of the property of `object` named by the `key` value.
136/// Returns false if the value couldn't be retrieved.
137pub unsafe fn get(out: &mut Local, env: Env, object: Local, key: Local) -> bool {
138    let status = napi::get_property(env, object, key, out as *mut _);
139
140    status.is_ok()
141}
142
143/// Sets the property value of an `napi_value` object, named by another `value` `key`. Returns `true` if the set succeeded.
144///
145/// The `out` parameter and the return value contain the same information for historical reasons,
146/// see [discussion].
147///
148/// [discussion]: https://github.com/neon-bindings/neon/pull/458#discussion_r344827965
149pub unsafe fn set(out: &mut bool, env: Env, object: Local, key: Local, val: Local) -> bool {
150    let status = napi::set_property(env, object, key, val);
151    *out = status.is_ok();
152
153    *out
154}