summaryrefslogtreecommitdiff
path: root/test_napi/src/lib.rs
blob: 3ab1f3c84671e78d5d53bfbd5dcf713ca607cc79 (plain)
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
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
#![allow(clippy::all)]
#![allow(clippy::undocumented_unsafe_blocks)]

use napi_sys::Status::napi_ok;
use std::ffi::c_void;

use napi_sys::*;

pub mod array;
pub mod arraybuffer;
pub mod r#async;
pub mod callback;
pub mod coerce;
pub mod numbers;
pub mod object_wrap;
pub mod primitives;
pub mod promise;
pub mod properties;
pub mod strings;
pub mod typedarray;

#[macro_export]
macro_rules! get_callback_info {
  ($env: expr, $callback_info: expr, $size: literal) => {{
    let mut args = [std::ptr::null_mut(); $size];
    let mut argc = $size;
    let mut this = std::ptr::null_mut();
    unsafe {
      assert!(
        napi_get_cb_info(
          $env,
          $callback_info,
          &mut argc,
          args.as_mut_ptr(),
          &mut this,
          std::ptr::null_mut(),
        ) == napi_ok,
      )
    };
    (args, argc, this)
  }};
}

#[macro_export]
macro_rules! new_property {
  ($env: expr, $name: expr, $value: expr) => {
    napi_property_descriptor {
      utf8name: $name.as_ptr() as *const std::os::raw::c_char,
      name: std::ptr::null_mut(),
      method: Some($value),
      getter: None,
      setter: None,
      data: std::ptr::null_mut(),
      attributes: 0,
      value: std::ptr::null_mut(),
    }
  };
}

extern "C" fn cleanup(arg: *mut c_void) {
  println!("cleanup({})", arg as i64);
}

static SECRET: i64 = 42;
static WRONG_SECRET: i64 = 17;
static THIRD_SECRET: i64 = 18;

extern "C" fn install_cleanup_hook(
  env: napi_env,
  info: napi_callback_info,
) -> napi_value {
  let (_args, argc, _) = get_callback_info!(env, info, 1);
  assert_eq!(argc, 0);

  unsafe {
    napi_add_env_cleanup_hook(env, Some(cleanup), WRONG_SECRET as *mut c_void);
    napi_add_env_cleanup_hook(env, Some(cleanup), SECRET as *mut c_void);
    napi_add_env_cleanup_hook(env, Some(cleanup), THIRD_SECRET as *mut c_void);
    napi_remove_env_cleanup_hook(
      env,
      Some(cleanup),
      WRONG_SECRET as *mut c_void,
    );
  }

  std::ptr::null_mut()
}

pub fn init_cleanup_hook(env: napi_env, exports: napi_value) {
  let properties = &[new_property!(
    env,
    "installCleanupHook\0",
    install_cleanup_hook
  )];

  unsafe {
    napi_define_properties(env, exports, properties.len(), properties.as_ptr())
  };
}

#[no_mangle]
unsafe extern "C" fn napi_register_module_v1(
  env: napi_env,
  exports: napi_value,
) -> napi_value {
  #[cfg(windows)]
  {
    napi_sys::setup();
  }

  strings::init(env, exports);
  numbers::init(env, exports);
  typedarray::init(env, exports);
  arraybuffer::init(env, exports);
  array::init(env, exports);
  primitives::init(env, exports);
  properties::init(env, exports);
  promise::init(env, exports);
  coerce::init(env, exports);
  object_wrap::init(env, exports);
  callback::init(env, exports);
  r#async::init(env, exports);
  init_cleanup_hook(env, exports);

  exports
}