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
}