/// Low-level, environment-bound wrappers around the general N-API value API.
///
/// The wrappers deliberately keep `NapiValue` opaque. A value is only valid
/// while its creating environment is active; references and handle scopes are
/// provided for values that need to outlive one callback.
///|
pub struct NapiObject {
priv value : NapiValue
}
///|
pub struct NapiFunction {
priv value : NapiValue
}
///|
pub struct NapiArray {
priv value : NapiValue
}
///|
pub enum NapiValueType {
Undefined
Null
Boolean
Number
String
Symbol
Object
Function
External
BigInt
}
///|
fn napi_value_type_of_int(kind : Int32) -> NapiValueType {
match kind {
0 => Undefined
1 => Null
2 => Boolean
3 => Number
4 => String
5 => Symbol
6 => Object
7 => Function
8 => External
9 => BigInt
_ => Undefined
}
}
///|
#borrow(result)
extern "c" fn napi_get_global_raw(
env : NapiEnv,
result : Ref[NapiValue],
) -> Int32 = "napi_get_global"
///|
#borrow(result)
extern "c" fn napi_get_undefined_raw(
env : NapiEnv,
result : Ref[NapiValue],
) -> Int32 = "napi_get_undefined"
///|
#borrow(result)
extern "c" fn napi_typeof_raw(
env : NapiEnv,
value : NapiValue,
result : Ref[Int32],
) -> Int32 = "moonbit_napi_value_kind"
///|
#borrow(result)
extern "c" fn napi_strict_equal_raw(
env : NapiEnv,
a : NapiValue,
b : NapiValue,
result : Ref[Bool],
) -> Int32 = "moonbit_napi_value_same"
///|
#borrow(key, result)
extern "c" fn napi_object_get_raw(
env : NapiEnv,
object : NapiValue,
key : Bytes,
result : Ref[NapiValue],
) -> Int32 = "napi_mbt_get_named_property"
///|
#borrow(key)
extern "c" fn napi_object_set_raw(
env : NapiEnv,
object : NapiValue,
key : Bytes,
value : NapiValue,
) -> Int32 = "napi_mbt_set_named_property"
///|
#borrow(key, result)
extern "c" fn napi_object_has_raw(
env : NapiEnv,
object : NapiValue,
key : Bytes,
result : Ref[Bool],
) -> Int32 = "napi_mbt_has_named_property"
///|
#borrow(result)
extern "c" fn napi_call_array_raw(
env : NapiEnv,
function : NapiValue,
receiver : NapiValue,
args : NapiValue,
result : Ref[NapiValue],
) -> Int32 = "napi_mbt_call_function_array"
///|
#borrow(result)
extern "c" fn napi_new_instance_array_raw(
env : NapiEnv,
function : NapiValue,
args : NapiValue,
result : Ref[NapiValue],
) -> Int32 = "napi_mbt_new_instance_array"
///|
#borrow(result)
extern "c" fn napi_object_keys_raw(
env : NapiEnv,
object : NapiValue,
result : Ref[NapiValue],
) -> Int32 = "napi_get_property_names"
///|
#borrow(result)
extern "c" fn napi_get_prototype_raw(
env : NapiEnv,
object : NapiValue,
result : Ref[NapiValue],
) -> Int32 = "napi_mbt_get_prototype"
///|
#borrow(result)
extern "c" fn napi_instanceof_raw(
env : NapiEnv,
object : NapiValue,
ctor : NapiValue,
result : Ref[Bool],
) -> Int32 = "napi_mbt_instanceof"
///|
#borrow(result)
extern "c" fn napi_coerce_string_raw(
env : NapiEnv,
value : NapiValue,
result : Ref[NapiValue],
) -> Int32 = "napi_coerce_to_string"
///|
#borrow(key)
extern "c" fn napi_define_data_property_raw(
env : NapiEnv,
object : NapiValue,
key : Bytes,
value : NapiValue,
attributes : Int32,
) -> Int32 = "napi_mbt_define_data_property"
///|
#borrow(scope)
extern "c" fn napi_open_handle_scope_raw(
env : NapiEnv,
scope : Ref[NapiHandleScope],
) -> Int32 = "napi_open_handle_scope"
///|
extern "c" fn napi_close_handle_scope_raw(
env : NapiEnv,
scope : NapiHandleScope,
) -> Int32 = "napi_close_handle_scope"
///|
#borrow(scope)
extern "c" fn napi_open_escapable_scope_raw(
env : NapiEnv,
scope : Ref[NapiEscapableHandleScope],
) -> Int32 = "napi_open_escapable_handle_scope"
///|
extern "c" fn napi_close_escapable_scope_raw(
env : NapiEnv,
scope : NapiEscapableHandleScope,
) -> Int32 = "napi_close_escapable_handle_scope"
///|
#borrow(result)
extern "c" fn napi_escape_handle_raw(
env : NapiEnv,
scope : NapiEscapableHandleScope,
value : NapiValue,
result : Ref[NapiValue],
) -> Int32 = "napi_escape_handle"
///|
pub fn napi_global(env : NapiEnv) -> NapiValue raise NapiError {
let result = Ref(moonbit_dummy_napi_value())
result_from_status(
env,
napi_get_global_raw(env, result),
b"Reading global object",
)
result.val
}
///|
pub fn napi_undefined(env : NapiEnv) -> NapiValue raise NapiError {
let result = Ref(moonbit_dummy_napi_value())
result_from_status(
env,
napi_get_undefined_raw(env, result),
b"Reading undefined",
)
result.val
}
///|
pub fn napi_value_type(
env : NapiEnv,
value : NapiValue,
) -> NapiValueType raise NapiError {
let result = Ref(0)
result_from_status(
env,
napi_typeof_raw(env, value, result),
b"Inspecting JavaScript value",
)
napi_value_type_of_int(result.val)
}
///|
pub fn napi_strict_equal(
env : NapiEnv,
a : NapiValue,
b : NapiValue,
) -> Bool raise NapiError {
let result = Ref(false)
result_from_status(
env,
napi_strict_equal_raw(env, a, b, result),
b"Comparing JavaScript values",
)
result.val
}
///|
pub fn NapiObject::from_value(
env : NapiEnv,
value : NapiValue,
) -> NapiObject raise NapiError {
match napi_value_type(env, value) {
Object | Function => { value, }
_ =>
raise napi_failure(1, TypeError, "ERR_NAPI_OBJECT", "Expected an object")
}
}
///|
pub fn NapiObject::value(self : NapiObject) -> NapiValue {
self.value
}
///|
pub fn NapiObject::get(
self : NapiObject,
env : NapiEnv,
key : String,
) -> NapiValue raise NapiError {
let result = Ref(moonbit_dummy_napi_value())
result_from_status(
env,
napi_object_get_raw(env, self.value, @utf8.encode(key), result),
b"Reading property",
)
result.val
}
///|
pub fn NapiObject::set(
self : NapiObject,
env : NapiEnv,
key : String,
value : NapiValue,
) -> Unit raise NapiError {
result_from_status(
env,
napi_object_set_raw(env, self.value, @utf8.encode(key), value),
b"Writing property",
)
}
///|
pub fn NapiObject::has(
self : NapiObject,
env : NapiEnv,
key : String,
) -> Bool raise NapiError {
let result = Ref(false)
result_from_status(
env,
napi_object_has_raw(env, self.value, @utf8.encode(key), result),
b"Checking property",
)
result.val
}
///|
pub fn NapiObject::define_property(
self : NapiObject,
env : NapiEnv,
key : String,
value : NapiValue,
attributes : Int32,
) -> Unit raise NapiError {
result_from_status(
env,
napi_define_data_property_raw(
env,
self.value,
@utf8.encode(key),
value,
attributes,
),
b"Defining property",
)
}
///|
pub fn NapiObject::keys(
self : NapiObject,
env : NapiEnv,
) -> Array[String] raise NapiError {
let result = Ref(moonbit_dummy_napi_value())
result_from_status(
env,
napi_object_keys_raw(env, self.value, result),
b"Reading property names",
)
Array::makei(napi_array_length(env, result.val), i => {
get_String(env, napi_array_get(env, result.val, i))
})
}
///|
pub fn NapiObject::prototype(
self : NapiObject,
env : NapiEnv,
) -> NapiObject raise NapiError {
let result = Ref(moonbit_dummy_napi_value())
result_from_status(
env,
napi_get_prototype_raw(env, self.value, result),
b"Reading prototype",
)
NapiObject::from_value(env, result.val)
}
///|
pub fn NapiObject::is_instance_of(
self : NapiObject,
env : NapiEnv,
ctor : NapiFunction,
) -> Bool raise NapiError {
let result = Ref(false)
result_from_status(
env,
napi_instanceof_raw(env, self.value, ctor.value, result),
b"Checking instance",
)
result.val
}
///|
pub fn NapiFunction::from_value(
env : NapiEnv,
value : NapiValue,
) -> NapiFunction raise NapiError {
if napi_value_type(env, value) is Function {
{ value, }
} else {
raise napi_failure(1, TypeError, "ERR_NAPI_FUNCTION", "Expected a function")
}
}
///|
pub fn NapiFunction::value(self : NapiFunction) -> NapiValue {
self.value
}
///|
pub fn NapiFunction::call(
self : NapiFunction,
env : NapiEnv,
receiver : NapiValue,
args : Array[NapiValue],
) -> NapiValue raise NapiError {
let js_args = napi_array_new(env, args.length())
for i, arg in args {
napi_array_set(env, js_args, i, arg)
}
let result = Ref(moonbit_dummy_napi_value())
result_from_status(
env,
napi_call_array_raw(env, self.value, receiver, js_args, result),
b"Calling JavaScript function",
)
result.val
}
///|
pub fn NapiFunction::new_instance(
self : NapiFunction,
env : NapiEnv,
args : Array[NapiValue],
) -> NapiObject raise NapiError {
let js_args = napi_array_new(env, args.length())
for i, arg in args {
napi_array_set(env, js_args, i, arg)
}
let result = Ref(moonbit_dummy_napi_value())
result_from_status(
env,
napi_new_instance_array_raw(env, self.value, js_args, result),
b"Constructing JavaScript object",
)
NapiObject::from_value(env, result.val)
}
///|
pub fn NapiArray::new(
env : NapiEnv,
length : Int32,
) -> NapiArray raise NapiError {
{ value: napi_array_new(env, length), }
}
///|
pub fn NapiArray::from_value(
env : NapiEnv,
value : NapiValue,
) -> NapiArray raise NapiError {
let is_array = Ref(false)
result_from_status(
env,
napi_is_array_raw(env, value, is_array),
b"Inspecting Array",
)
if is_array.val {
{ value, }
} else {
raise napi_failure(1, TypeError, "ERR_NAPI_ARRAY", "Expected an Array")
}
}
///|
pub fn NapiArray::value(self : NapiArray) -> NapiValue {
self.value
}
///|
pub fn NapiArray::length(
self : NapiArray,
env : NapiEnv,
) -> Int32 raise NapiError {
napi_array_length(env, self.value)
}
///|
pub fn NapiArray::get(
self : NapiArray,
env : NapiEnv,
index : Int32,
) -> NapiValue raise NapiError {
napi_array_get(env, self.value, index)
}
///|
pub fn NapiArray::set(
self : NapiArray,
env : NapiEnv,
index : Int32,
value : NapiValue,
) -> Unit raise NapiError {
napi_array_set(env, self.value, index, value)
}
///|
pub struct NapiHandleScopeGuard {
env : NapiEnv
scope : NapiHandleScope
mut closed : Bool
}
///|
pub fn NapiHandleScopeGuard::open(
env : NapiEnv,
) -> NapiHandleScopeGuard raise NapiError {
let scope = Ref(napi_dummy_handle_scope())
result_from_status(
env,
napi_open_handle_scope_raw(env, scope),
b"Opening handle scope",
)
{ env, scope: scope.val, closed: false, }
}
///|
pub fn NapiHandleScopeGuard::close(
self : NapiHandleScopeGuard,
) -> Unit raise NapiError {
if !self.closed {
self.closed = true
result_from_status(
self.env,
napi_close_handle_scope_raw(self.env, self.scope),
b"Closing handle scope",
)
}
}
///|
pub struct NapiEscapableHandleScopeGuard {
env : NapiEnv
scope : NapiEscapableHandleScope
mut closed : Bool
}
///|
pub fn NapiEscapableHandleScopeGuard::open(
env : NapiEnv,
) -> NapiEscapableHandleScopeGuard raise NapiError {
let scope = Ref(napi_dummy_escapable_scope())
result_from_status(
env,
napi_open_escapable_scope_raw(env, scope),
b"Opening escapable handle scope",
)
{ env, scope: scope.val, closed: false, }
}
///|
pub fn NapiEscapableHandleScopeGuard::escape(
self : NapiEscapableHandleScopeGuard,
value : NapiValue,
) -> NapiValue raise NapiError {
let result = Ref(moonbit_dummy_napi_value())
result_from_status(
self.env,
napi_escape_handle_raw(self.env, self.scope, value, result),
b"Escaping handle",
)
result.val
}
///|
pub fn NapiEscapableHandleScopeGuard::close(
self : NapiEscapableHandleScopeGuard,
) -> Unit raise NapiError {
if !self.closed {
self.closed = true
result_from_status(
self.env,
napi_close_escapable_scope_raw(self.env, self.scope),
b"Closing escapable handle scope",
)
}
}
///|
extern "c" fn napi_dummy_handle_scope() -> NapiHandleScope = "moonbit_dummy_handle_scope"
///|
extern "c" fn napi_dummy_escapable_scope() -> NapiEscapableHandleScope = "moonbit_dummy_escapable_scope"
///|
pub fn napi_coerce_to_string(
env : NapiEnv,
value : NapiValue,
) -> String raise NapiError {
let result = Ref(moonbit_dummy_napi_value())
result_from_status(
env,
napi_coerce_string_raw(env, value, result),
b"Converting value to string",
)
get_String(env, result.val)
}