neon/context/
internal.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
use std::{cell::RefCell, ffi::c_void, mem::MaybeUninit};

use crate::{
    context::{Cx, ModuleContext},
    handle::Handle,
    result::NeonResult,
    sys::{self, raw},
    types::{private::ValueInternal, JsObject},
};

#[repr(C)]
#[derive(Clone, Copy)]
pub struct Env(raw::Env);

impl From<raw::Env> for Env {
    fn from(env: raw::Env) -> Self {
        Self(env)
    }
}

thread_local! {
    #[allow(unused)]
    pub(crate) static IS_RUNNING: RefCell<bool> = const { RefCell::new(false) };
}

impl Env {
    pub(crate) fn to_raw(self) -> raw::Env {
        let Self(ptr) = self;
        ptr
    }

    pub(super) unsafe fn try_catch<T, F>(self, f: F) -> Result<T, raw::Local>
    where
        F: FnOnce() -> Result<T, crate::result::Throw>,
    {
        let result = f();
        let mut local: MaybeUninit<raw::Local> = MaybeUninit::zeroed();

        if sys::error::catch_error(self.to_raw(), local.as_mut_ptr()) {
            Err(local.assume_init())
        } else if let Ok(result) = result {
            Ok(result)
        } else {
            panic!("try_catch: unexpected Err(Throw) when VM is not in a throwing state");
        }
    }
}

pub trait ContextInternal<'cx>: Sized {
    fn cx(&self) -> &Cx<'cx>;
    fn cx_mut(&mut self) -> &mut Cx<'cx>;
    fn env(&self) -> Env {
        self.cx().env
    }
}

fn default_main(mut cx: ModuleContext) -> NeonResult<()> {
    #[cfg(feature = "tokio-rt-multi-thread")]
    crate::executor::tokio::init(&mut cx)?;
    crate::registered().export(&mut cx)
}

fn init(cx: ModuleContext) -> NeonResult<()> {
    if crate::macro_internal::MAIN.len() > 1 {
        panic!("The `neon::main` macro must only be used once");
    }

    if let Some(main) = crate::macro_internal::MAIN.first() {
        main(cx)
    } else {
        default_main(cx)
    }
}

#[no_mangle]
unsafe extern "C" fn napi_register_module_v1(env: *mut c_void, m: *mut c_void) -> *mut c_void {
    let env = env.cast();

    sys::setup(env);

    IS_RUNNING.with(|v| {
        *v.borrow_mut() = true;
    });

    let env = Env(env);
    let exports = Handle::new_internal(JsObject::from_local(env, m.cast()));
    let _ = ModuleContext::with(env, exports, init);

    m
}