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
use crate::{api, prelude::*};
use std::mem::MaybeUninit;
/// Node-API provides the ability to establish a new 'scope' to which newly created handles
/// will be associated. Once those handles are no longer required, the scope can be 'closed'
/// and any handles associated with the scope are invalidated. The methods available to
/// open/close scopes are napi_open_handle_scope and napi_close_handle_scope.
///
/// Node-API only supports a single nested hierarchy of scopes. There is only one active scope
/// at any time, and all new handles will be associated with that scope while it is active.
/// Scopes must be closed in the reverse order from which they are opened. In addition,
/// all scopes created within a native method must be closed before returning from that method.
#[derive(Clone, Debug)]
pub struct NapiHandleScope(NapiEnv, napi_handle_scope);
impl NapiHandleScope {
pub(crate) fn from_raw(env: NapiEnv, handle: napi_handle_scope) -> NapiHandleScope {
NapiHandleScope(env, handle)
}
pub fn env(&self) -> NapiEnv {
self.0
}
pub fn raw(&self) -> napi_handle_scope {
self.1
}
/// This API opens a new scope.
pub fn open(env: NapiEnv) -> NapiResult<NapiHandleScope> {
let handle = napi_call!(=napi_open_handle_scope, env);
Ok(NapiHandleScope(env, handle))
}
/// This API closes the scope passed in. Scopes must be closed in the reverse
/// order from which they were created.
/// This API can be called even if there is a pending JavaScript exception.
pub fn close(&mut self) -> NapiResult<()> {
napi_call!(napi_close_handle_scope, self.env(), self.raw())
}
}
impl Drop for NapiHandleScope {
fn drop(&mut self) {
if let Err(e) = self.close() {
log::warn!("[{}] napi_close_handle_scope failed.", e);
}
}
}
/// When nesting scopes, there are cases where a handle from an inner scope needs to live
/// beyond the lifespan of that scope. Node-API supports an 'escapable scope' in order to
/// support this case. An escapable scope allows one handle to be 'promoted' so that it
/// 'escapes' the current scope and the lifespan of the handle changes from the current scope
/// to that of the outer scope.
///
/// The methods available to open/close escapable scopes are napi_open_escapable_handle_scope
/// and napi_close_escapable_handle_scope.
///
/// The request to promote a handle is made through napi_escape_handle which can only be
/// called once.
#[derive(Clone, Debug)]
pub struct NapiEscapableHandleScope(NapiEnv, napi_escapable_handle_scope);
impl NapiEscapableHandleScope {
pub(crate) fn from_value(
env: NapiEnv,
handle: napi_escapable_handle_scope,
) -> NapiEscapableHandleScope {
NapiEscapableHandleScope(env, handle)
}
pub fn env(&self) -> NapiEnv {
self.0
}
pub fn raw(&self) -> napi_escapable_handle_scope {
self.1
}
/// This API opens a new scope from which one object can be promoted to the outer scope.
pub fn open(env: NapiEnv) -> NapiResult<NapiEscapableHandleScope> {
let handle = napi_call!(=napi_open_escapable_handle_scope, env);
Ok(NapiEscapableHandleScope(env, handle))
}
/// This API closes the scope passed in. Scopes must be closed in the reverse
/// order from which they were created.
/// This API can be called even if there is a pending JavaScript exception.
pub fn close(&mut self) -> NapiResult<()> {
napi_call!(napi_close_escapable_handle_scope, self.env(), self.raw())
}
/// This API promotes the handle to the JavaScript object so that it is valid for
/// the lifetime of the outer scope. It can only be called once per scope. If it is
/// called more than once an error will be returned.
///
/// This API can be called even if there is a pending JavaScript exception.
pub fn escape<T: NapiValueT>(&mut self, escapee: T) -> NapiResult<T> {
let escapee = napi_call!(=napi_escape_handle, self.env(), self.1, escapee.raw());
Ok(T::from_raw(self.env(), escapee))
}
}
impl Drop for NapiEscapableHandleScope {
fn drop(&mut self) {
if let Err(e) = self.close() {
log::warn!("[{}] napi_close_escapable_handle_scope failed.", e);
}
}
}