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
use std::cell::RefCell;
use std::ptr;

use crate::{check_status, sys, JsGlobal, JsNull, JsUndefined, NapiValue, Result};

use super::Array;

pub use crate::Env;

thread_local! {
  static JS_UNDEFINED: RefCell<Option<JsUndefined>> = RefCell::default();
  static JS_NULL: RefCell<Option<JsNull>> = RefCell::default();
}

impl Env {
  pub fn create_array(&self, len: u32) -> Result<Array> {
    Array::new(self.0, len)
  }

  /// Get [JsUndefined](./struct.JsUndefined.html) value
  pub fn get_undefined(&self) -> Result<JsUndefined> {
    if let Some(js_undefined) = JS_UNDEFINED.with(|x| *x.borrow()) {
      return Ok(js_undefined);
    }
    let mut raw_value = ptr::null_mut();
    check_status!(unsafe { sys::napi_get_undefined(self.0, &mut raw_value) })?;
    let js_undefined = unsafe { JsUndefined::from_raw_unchecked(self.0, raw_value) };
    JS_UNDEFINED.with(|x| x.borrow_mut().replace(js_undefined));
    Ok(js_undefined)
  }

  pub fn get_null(&self) -> Result<JsNull> {
    if let Some(js_null) = JS_NULL.with(|cell| *cell.borrow()) {
      return Ok(js_null);
    }
    let mut raw_value = ptr::null_mut();
    check_status!(unsafe { sys::napi_get_null(self.0, &mut raw_value) })?;
    let js_null = unsafe { JsNull::from_raw_unchecked(self.0, raw_value) };
    JS_NULL.with(|js_null_cell| {
      js_null_cell.borrow_mut().replace(js_null);
    });
    Ok(js_null)
  }

  pub fn get_global(&self) -> Result<JsGlobal> {
    let mut global = std::ptr::null_mut();
    crate::check_status!(
      unsafe { sys::napi_get_global(self.0, &mut global) },
      "Get global object from Env failed"
    )?;
    Ok(JsGlobal(crate::Value {
      value: global,
      env: self.0,
      value_type: crate::ValueType::Object,
    }))
  }
}