Merge pull request #158 from napi-rs/object-functions

Object functions
This commit is contained in:
LongYinan 2020-09-03 15:50:54 +08:00 committed by GitHub
commit dfb7518cac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 1238 additions and 321 deletions

View file

@ -169,7 +169,7 @@ yarn test
| [napi_get_array_length](https://nodejs.org/api/n-api.html#n_api_napi_get_array_length) | 1 | v8.0.0 | ✅ |
| [napi_get_arraybuffer_info](https://nodejs.org/api/n-api.html#n_api_napi_get_arraybuffer_info) | 1 | v8.0.0 | ✅ |
| [napi_get_buffer_info](https://nodejs.org/api/n-api.html#n_api_napi_get_buffer_info) | 1 | v8.0.0 | ✅ |
| [napi_get_prototype](https://nodejs.org/api/n-api.html#n_api_napi_get_prototype) | 1 | v8.0.0 | ⛔️ |
| [napi_get_prototype](https://nodejs.org/api/n-api.html#n_api_napi_get_prototype) | 1 | v8.0.0 | |
| [napi_get_typedarray_info](https://nodejs.org/api/n-api.html#n_api_napi_get_typedarray_info) | 1 | v8.0.0 | ⛔️ |
| [napi_get_dataview_info](https://nodejs.org/api/n-api.html#n_api_napi_get_dataview_info) | 1 | v8.3.0 | ⛔️ |
| [napi_get_date_value](https://nodejs.org/api/n-api.html#n_api_napi_get_date_value) | 5 | v11.11.0 | ⛔️ |

View file

@ -112,7 +112,7 @@ pub fn js_function(attr: TokenStream, input: TokenStream) -> TokenStream {
}
let mut env = Env::from_raw(raw_env);
let call_ctx = CallContext::new(&mut env, raw_this, &raw_args, #arg_len_span, argc as usize);
let call_ctx = CallContext::new(&mut env, cb_info, raw_this, &raw_args, #arg_len_span, argc as usize);
let result = call_ctx.and_then(|ctx| {
match panic::catch_unwind(AssertUnwindSafe(move || #new_fn_name(ctx))) {
Ok(result) => result,

View file

@ -16,8 +16,7 @@ impl<T: Task> AsyncWork<T> {
#[inline]
pub fn run(env: sys::napi_env, task: T, deferred: sys::napi_deferred) -> Result<()> {
let mut raw_resource = ptr::null_mut();
let status = unsafe { sys::napi_create_object(env, &mut raw_resource) };
check_status(status)?;
check_status(unsafe { sys::napi_create_object(env, &mut raw_resource) })?;
let mut raw_name = ptr::null_mut();
let s = "napi_rs_async";
check_status(unsafe {

View file

@ -1,8 +1,12 @@
use std::ptr;
use crate::error::check_status;
use crate::{sys, Either, Env, Error, JsUndefined, JsUnknown, NapiValue, Result, Status};
pub struct CallContext<'env, T: NapiValue = JsUnknown> {
pub env: &'env Env,
pub this: T,
callback_info: sys::napi_callback_info,
args: &'env [sys::napi_value],
arg_len: usize,
actual_arg_length: usize,
@ -12,6 +16,7 @@ impl<'env, T: NapiValue> CallContext<'env, T> {
#[inline]
pub fn new(
env: &'env Env,
callback_info: sys::napi_callback_info,
this: sys::napi_value,
args: &'env [sys::napi_value],
arg_len: usize,
@ -19,6 +24,7 @@ impl<'env, T: NapiValue> CallContext<'env, T> {
) -> Result<Self> {
Ok(Self {
env,
callback_info,
this: T::from_raw(env.0, this)?,
args,
arg_len,
@ -53,4 +59,13 @@ impl<'env, T: NapiValue> CallContext<'env, T> {
}
}
}
pub fn get_new_target<V>(&self) -> Result<V>
where
V: NapiValue,
{
let mut value = ptr::null_mut();
check_status(unsafe { sys::napi_get_new_target(self.env.0, self.callback_info, &mut value) })?;
V::from_raw(self.env.0, value)
}
}

View file

@ -379,13 +379,13 @@ impl Env {
&self,
name: &str,
constructor_cb: Callback,
properties: Vec<Property>,
properties: &[Property],
) -> Result<JsFunction> {
let mut raw_result = ptr::null_mut();
let raw_properties = properties
.into_iter()
.map(|prop| prop.into_raw(self))
.collect::<Result<Vec<sys::napi_property_descriptor>>>()?;
.iter()
.map(|prop| prop.raw())
.collect::<Vec<sys::napi_property_descriptor>>();
check_status(unsafe {
sys::napi_define_class(
@ -541,9 +541,9 @@ impl Env {
#[inline]
pub fn get_napi_version(&self) -> Result<u32> {
let global = self.get_global()?;
let process = global.get_named_property::<JsObject>("process")?;
let versions = process.get_named_property::<JsObject>("versions")?;
let napi_version = versions.get_named_property::<JsString>("napi")?;
let process: JsObject = global.get_named_property("process")?;
let versions: JsObject = process.get_named_property("versions")?;
let napi_version: JsString = versions.get_named_property("napi")?;
napi_version
.as_str()?
.parse()

View file

@ -1,7 +1,7 @@
use std::convert::TryFrom;
use std::ptr;
use super::{JsObject, JsUnknown, NapiValue, Value, ValueType};
use super::{JsNumber, JsObject, JsString, JsUnknown, NapiValue, Value, ValueType};
use crate::error::check_status;
use crate::{sys, Error, Result};
@ -24,6 +24,114 @@ impl JsArrayBuffer {
len: 0,
}
}
#[inline]
pub fn into_unknown(self) -> Result<JsUnknown> {
JsUnknown::from_raw(self.value.0.env, self.value.0.value)
}
#[inline]
pub fn coerce_to_number(self) -> Result<JsNumber> {
let mut new_raw_value = ptr::null_mut();
check_status(unsafe {
sys::napi_coerce_to_number(self.value.0.env, self.value.0.value, &mut new_raw_value)
})?;
Ok(JsNumber(Value {
env: self.value.0.env,
value: new_raw_value,
value_type: ValueType::Number,
}))
}
#[inline]
pub fn coerce_to_string(self) -> Result<JsString> {
let mut new_raw_value = ptr::null_mut();
check_status(unsafe {
sys::napi_coerce_to_string(self.value.0.env, self.value.0.value, &mut new_raw_value)
})?;
Ok(JsString(Value {
env: self.value.0.env,
value: new_raw_value,
value_type: ValueType::String,
}))
}
#[inline]
pub fn coerce_to_object(self) -> Result<JsObject> {
let mut new_raw_value = ptr::null_mut();
check_status(unsafe {
sys::napi_coerce_to_object(self.value.0.env, self.value.0.value, &mut new_raw_value)
})?;
Ok(JsObject(Value {
env: self.value.0.env,
value: new_raw_value,
value_type: ValueType::Object,
}))
}
#[inline]
#[cfg(napi5)]
pub fn is_date(&self) -> Result<bool> {
let mut is_date = true;
check_status(unsafe { sys::napi_is_date(self.value.0.env, self.value.0.value, &mut is_date) })?;
Ok(is_date)
}
#[inline]
pub fn is_error(&self) -> Result<bool> {
let mut result = false;
check_status(unsafe { sys::napi_is_error(self.value.0.env, self.value.0.value, &mut result) })?;
Ok(result)
}
#[inline]
pub fn is_typedarray(&self) -> Result<bool> {
let mut result = false;
check_status(unsafe {
sys::napi_is_typedarray(self.value.0.env, self.value.0.value, &mut result)
})?;
Ok(result)
}
#[inline]
pub fn is_dataview(&self) -> Result<bool> {
let mut result = false;
check_status(unsafe {
sys::napi_is_dataview(self.value.0.env, self.value.0.value, &mut result)
})?;
Ok(result)
}
#[inline]
pub fn is_array(&self) -> Result<bool> {
let mut is_array = false;
check_status(unsafe {
sys::napi_is_array(self.value.0.env, self.value.0.value, &mut is_array)
})?;
Ok(is_array)
}
#[inline]
pub fn is_buffer(&self) -> Result<bool> {
let mut is_buffer = false;
check_status(unsafe {
sys::napi_is_buffer(self.value.0.env, self.value.0.value, &mut is_buffer)
})?;
Ok(is_buffer)
}
#[inline]
pub fn instanceof<Constructor: NapiValue>(&self, constructor: Constructor) -> Result<bool> {
let mut result = false;
check_status(unsafe {
sys::napi_instanceof(
self.value.0.env,
self.value.0.value,
constructor.raw_value(),
&mut result,
)
})?;
Ok(result)
}
}
impl NapiValue for JsArrayBuffer {
@ -34,8 +142,7 @@ impl NapiValue for JsArrayBuffer {
fn from_raw(env: sys::napi_env, value: sys::napi_value) -> Result<Self> {
let mut data = ptr::null_mut();
let mut len: u64 = 0;
let status = unsafe { sys::napi_get_arraybuffer_info(env, value, &mut data, &mut len) };
check_status(status)?;
check_status(unsafe { sys::napi_get_arraybuffer_info(env, value, &mut data, &mut len) })?;
Ok(JsArrayBuffer {
value: JsObject(Value {
env,

View file

@ -35,9 +35,9 @@ impl JsBigint {
#[inline]
pub fn coerce_to_number(self) -> Result<JsNumber> {
let mut new_raw_value = ptr::null_mut();
let status =
unsafe { sys::napi_coerce_to_number(self.raw.env, self.raw.value, &mut new_raw_value) };
check_status(status)?;
check_status(unsafe {
sys::napi_coerce_to_number(self.raw.env, self.raw.value, &mut new_raw_value)
})?;
Ok(JsNumber(Value {
env: self.raw.env,
value: new_raw_value,
@ -48,9 +48,9 @@ impl JsBigint {
#[inline]
pub fn coerce_to_string(self) -> Result<JsString> {
let mut new_raw_value = ptr::null_mut();
let status =
unsafe { sys::napi_coerce_to_string(self.raw.env, self.raw.value, &mut new_raw_value) };
check_status(status)?;
check_status(unsafe {
sys::napi_coerce_to_string(self.raw.env, self.raw.value, &mut new_raw_value)
})?;
Ok(JsString(Value {
env: self.raw.env,
value: new_raw_value,
@ -60,9 +60,9 @@ impl JsBigint {
#[inline]
pub fn coerce_to_object(self) -> Result<JsObject> {
let mut new_raw_value = ptr::null_mut();
let status =
unsafe { sys::napi_coerce_to_object(self.raw.env, self.raw.value, &mut new_raw_value) };
check_status(status)?;
check_status(unsafe {
sys::napi_coerce_to_object(self.raw.env, self.raw.value, &mut new_raw_value)
})?;
Ok(JsObject(Value {
env: self.raw.env,
value: new_raw_value,
@ -74,8 +74,7 @@ impl JsBigint {
#[cfg(napi5)]
pub fn is_date(&self) -> Result<bool> {
let mut is_date = true;
let status = unsafe { sys::napi_is_date(self.raw.env, self.raw.value, &mut is_date) };
check_status(status)?;
check_status(unsafe { sys::napi_is_date(self.raw.env, self.raw.value, &mut is_date) })?;
Ok(is_date)
}
@ -100,6 +99,20 @@ impl JsBigint {
Ok(result)
}
#[inline]
pub fn is_array(&self) -> Result<bool> {
let mut is_array = false;
check_status(unsafe { sys::napi_is_array(self.raw.env, self.raw.value, &mut is_array) })?;
Ok(is_array)
}
#[inline]
pub fn is_buffer(&self) -> Result<bool> {
let mut is_buffer = false;
check_status(unsafe { sys::napi_is_buffer(self.raw.env, self.raw.value, &mut is_buffer) })?;
Ok(is_buffer)
}
#[inline]
pub fn instanceof<Constructor: NapiValue>(&self, constructor: Constructor) -> Result<bool> {
let mut result = false;

View file

@ -3,7 +3,7 @@ use std::ops::Deref;
use std::ptr;
use std::slice;
use super::{JsObject, JsUnknown, NapiValue, Value, ValueType};
use super::{JsNumber, JsObject, JsString, JsUnknown, NapiValue, Value, ValueType};
use crate::error::check_status;
use crate::{sys, Error, Result};
@ -30,8 +30,112 @@ impl JsBuffer {
}
}
#[inline]
pub fn into_unknown(self) -> Result<JsUnknown> {
self.value.into_unknown()
JsUnknown::from_raw(self.value.0.env, self.value.0.value)
}
#[inline]
pub fn coerce_to_number(self) -> Result<JsNumber> {
let mut new_raw_value = ptr::null_mut();
check_status(unsafe {
sys::napi_coerce_to_number(self.value.0.env, self.value.0.value, &mut new_raw_value)
})?;
Ok(JsNumber(Value {
env: self.value.0.env,
value: new_raw_value,
value_type: ValueType::Number,
}))
}
#[inline]
pub fn coerce_to_string(self) -> Result<JsString> {
let mut new_raw_value = ptr::null_mut();
check_status(unsafe {
sys::napi_coerce_to_string(self.value.0.env, self.value.0.value, &mut new_raw_value)
})?;
Ok(JsString(Value {
env: self.value.0.env,
value: new_raw_value,
value_type: ValueType::String,
}))
}
#[inline]
pub fn coerce_to_object(self) -> Result<JsObject> {
let mut new_raw_value = ptr::null_mut();
check_status(unsafe {
sys::napi_coerce_to_object(self.value.0.env, self.value.0.value, &mut new_raw_value)
})?;
Ok(JsObject(Value {
env: self.value.0.env,
value: new_raw_value,
value_type: ValueType::Object,
}))
}
#[inline]
#[cfg(napi5)]
pub fn is_date(&self) -> Result<bool> {
let mut is_date = true;
check_status(unsafe { sys::napi_is_date(self.value.0.env, self.value.0.value, &mut is_date) })?;
Ok(is_date)
}
#[inline]
pub fn is_error(&self) -> Result<bool> {
let mut result = false;
check_status(unsafe { sys::napi_is_error(self.value.0.env, self.value.0.value, &mut result) })?;
Ok(result)
}
#[inline]
pub fn is_typedarray(&self) -> Result<bool> {
let mut result = false;
check_status(unsafe {
sys::napi_is_typedarray(self.value.0.env, self.value.0.value, &mut result)
})?;
Ok(result)
}
#[inline]
pub fn is_dataview(&self) -> Result<bool> {
let mut result = false;
check_status(unsafe {
sys::napi_is_dataview(self.value.0.env, self.value.0.value, &mut result)
})?;
Ok(result)
}
#[inline]
pub fn is_array(&self) -> Result<bool> {
let mut is_array = false;
check_status(unsafe {
sys::napi_is_array(self.value.0.env, self.value.0.value, &mut is_array)
})?;
Ok(is_array)
}
#[inline]
pub fn is_buffer(&self) -> Result<bool> {
let mut is_buffer = false;
check_status(unsafe {
sys::napi_is_buffer(self.value.0.env, self.value.0.value, &mut is_buffer)
})?;
Ok(is_buffer)
}
#[inline]
pub fn instanceof<Constructor: NapiValue>(&self, constructor: Constructor) -> Result<bool> {
let mut result = false;
check_status(unsafe {
sys::napi_instanceof(
self.value.0.env,
self.value.0.value,
constructor.raw_value(),
&mut result,
)
})?;
Ok(result)
}
}

View file

@ -1,47 +0,0 @@
use std::ptr;
use crate::{sys, Callback, Env, NapiValue, Result};
#[derive(Debug)]
pub struct Property {
name: String,
raw_descriptor: sys::napi_property_descriptor,
}
impl Property {
pub fn new(name: &str) -> Self {
Property {
name: String::from(name),
raw_descriptor: sys::napi_property_descriptor {
utf8name: ptr::null_mut(),
name: ptr::null_mut(),
method: None,
getter: None,
setter: None,
value: ptr::null_mut(),
attributes: sys::napi_property_attributes::napi_default,
data: ptr::null_mut(),
},
}
}
pub fn with_value<T: NapiValue>(mut self, value: T) -> Self {
self.raw_descriptor.value = T::raw_value(&value);
self
}
pub fn with_method(mut self, callback: Callback) -> Self {
self.raw_descriptor.method = Some(callback);
self
}
pub fn with_getter(mut self, callback: Callback) -> Self {
self.raw_descriptor.getter = Some(callback);
self
}
pub(crate) fn into_raw(mut self, env: &Env) -> Result<sys::napi_property_descriptor> {
self.raw_descriptor.name = env.create_string(&self.name)?.raw_value();
Ok(self.raw_descriptor)
}
}

View file

@ -122,7 +122,7 @@ impl<'x, 'de, 'env> serde::de::Deserializer<'x> for &'de mut De<'env> {
),
))
} else {
let key = properties.get_index::<JsString>(0)?;
let key = properties.get_element::<JsString>(0)?;
let value: JsUnknown = js_object.get_property(&key)?;
visitor.visit_enum(JsEnumAccess::new(key.as_str()?.to_owned(), Some(&value.0)))
}
@ -289,7 +289,7 @@ impl<'de, 'env> SeqAccess<'de> for JsArrayAccess<'env> {
if self.idx >= self.len {
return Ok(None);
}
let v = self.input.get_index::<JsUnknown>(self.idx)?;
let v = self.input.get_element::<JsUnknown>(self.idx)?;
self.idx += 1;
let mut de = De(&v.0);
@ -331,7 +331,7 @@ impl<'de, 'env> MapAccess<'de> for JsObjectAccess<'env> {
return Ok(None);
}
let prop_name = self.properties.get_index::<JsUnknown>(self.idx)?;
let prop_name = self.properties.get_element::<JsUnknown>(self.idx)?;
let mut de = De(&prop_name.0);
seed.deserialize(&mut de).map(Some)
@ -347,7 +347,7 @@ impl<'de, 'env> MapAccess<'de> for JsObjectAccess<'env> {
format!("Index:{} out of range: {}", self.property_len, self.idx),
));
}
let prop_name = self.properties.get_index::<JsString>(self.idx)?;
let prop_name = self.properties.get_element::<JsString>(self.idx)?;
let value: JsUnknown = self.value.get_property(&prop_name)?;
self.idx += 1;

View file

@ -42,7 +42,7 @@ impl JsFunction {
raw_args[i] = arg.0.value;
}
let mut return_value = ptr::null_mut();
let status = unsafe {
check_status(unsafe {
sys::napi_call_function(
self.0.env,
raw_this,
@ -51,8 +51,7 @@ impl JsFunction {
&raw_args[0],
&mut return_value,
)
};
check_status(status)?;
})?;
JsUnknown::from_raw(self.0.env, return_value)
}

View file

@ -14,11 +14,11 @@ mod arraybuffer;
mod bigint;
mod boolean;
mod buffer;
mod class_property;
mod either;
mod function;
mod number;
mod object;
mod object_property;
mod string;
mod tagged_object;
mod undefined;
@ -31,13 +31,13 @@ pub use arraybuffer::JsArrayBuffer;
pub use bigint::JsBigint;
pub use boolean::JsBoolean;
pub use buffer::JsBuffer;
pub use class_property::Property;
#[cfg(feature = "serde-json")]
pub(crate) use de::De;
pub use either::Either;
pub use function::JsFunction;
pub use number::JsNumber;
pub use object::JsObject;
pub use object_property::Property;
#[cfg(feature = "serde-json")]
pub(crate) use ser::Ser;
pub use string::JsString;
@ -145,6 +145,7 @@ macro_rules! impl_js_value_methods {
value_type: ValueType::String,
}))
}
#[inline]
pub fn coerce_to_object(self) -> Result<JsObject> {
let mut new_raw_value = ptr::null_mut();
@ -188,6 +189,20 @@ macro_rules! impl_js_value_methods {
Ok(result)
}
#[inline]
pub fn is_array(&self) -> Result<bool> {
let mut is_array = false;
check_status(unsafe { sys::napi_is_array(self.0.env, self.0.value, &mut is_array) })?;
Ok(is_array)
}
#[inline]
pub fn is_buffer(&self) -> Result<bool> {
let mut is_buffer = false;
check_status(unsafe { sys::napi_is_buffer(self.0.env, self.0.value, &mut is_buffer) })?;
Ok(is_buffer)
}
#[inline]
pub fn instanceof<Constructor: NapiValue>(&self, constructor: Constructor) -> Result<bool> {
let mut result = false;

View file

@ -12,8 +12,7 @@ impl TryFrom<JsNumber> for usize {
fn try_from(value: JsNumber) -> Result<usize> {
let mut result = 0;
let status = unsafe { sys::napi_get_value_int64(value.0.env, value.0.value, &mut result) };
check_status(status)?;
check_status(unsafe { sys::napi_get_value_int64(value.0.env, value.0.value, &mut result) })?;
Ok(result as usize)
}
}
@ -23,8 +22,7 @@ impl TryFrom<JsNumber> for u32 {
fn try_from(value: JsNumber) -> Result<u32> {
let mut result = 0;
let status = unsafe { sys::napi_get_value_uint32(value.0.env, value.0.value, &mut result) };
check_status(status)?;
check_status(unsafe { sys::napi_get_value_uint32(value.0.env, value.0.value, &mut result) })?;
Ok(result)
}
}
@ -34,8 +32,7 @@ impl TryFrom<JsNumber> for i32 {
fn try_from(value: JsNumber) -> Result<i32> {
let mut result = 0;
let status = unsafe { sys::napi_get_value_int32(value.0.env, value.0.value, &mut result) };
check_status(status)?;
check_status(unsafe { sys::napi_get_value_int32(value.0.env, value.0.value, &mut result) })?;
Ok(result)
}
}
@ -45,8 +42,7 @@ impl TryFrom<JsNumber> for i64 {
fn try_from(value: JsNumber) -> Result<i64> {
let mut result = 0;
let status = unsafe { sys::napi_get_value_int64(value.0.env, value.0.value, &mut result) };
check_status(status)?;
check_status(unsafe { sys::napi_get_value_int64(value.0.env, value.0.value, &mut result) })?;
Ok(result)
}
}
@ -56,8 +52,7 @@ impl TryFrom<JsNumber> for f64 {
fn try_from(value: JsNumber) -> Result<f64> {
let mut result = 0_f64;
let status = unsafe { sys::napi_get_value_double(value.0.env, value.0.value, &mut result) };
check_status(status)?;
check_status(unsafe { sys::napi_get_value_double(value.0.env, value.0.value, &mut result) })?;
Ok(result)
}
}

View file

@ -3,37 +3,47 @@ use std::ptr;
use super::Value;
use crate::error::check_status;
use crate::{sys, Env, Error, JsBuffer, JsNumber, JsString, NapiValue, Result, Status};
use crate::{sys, Error, JsString, NapiValue, Property, Result, Status};
#[derive(Debug)]
pub struct JsObject(pub(crate) Value);
impl JsObject {
pub fn set_property<V: NapiValue>(&mut self, key: JsString, value: V) -> Result<()> {
let status =
unsafe { sys::napi_set_property(self.0.env, self.0.value, key.0.value, value.raw_value()) };
check_status(status)?;
Ok(())
}
pub fn set_number_indexed_property<V: NapiValue>(
&mut self,
key: JsNumber,
value: V,
) -> Result<()> {
pub fn set_property<V>(&mut self, key: JsString, value: V) -> Result<()>
where
V: NapiValue,
{
check_status(unsafe {
sys::napi_set_property(self.0.env, self.0.value, key.0.value, value.raw_value())
})
}
pub fn set_named_property<T: NapiValue>(&mut self, name: &str, value: T) -> Result<()> {
pub fn get_property<K, T>(&self, key: &K) -> Result<T>
where
K: NapiValue,
T: NapiValue,
{
let mut raw_value = ptr::null_mut();
check_status(unsafe {
sys::napi_get_property(self.0.env, self.0.value, key.raw_value(), &mut raw_value)
})?;
T::from_raw(self.0.env, raw_value)
}
pub fn set_named_property<T>(&mut self, name: &str, value: T) -> Result<()>
where
T: NapiValue,
{
let key = CString::new(name)?;
check_status(unsafe {
sys::napi_set_named_property(self.0.env, self.0.value, key.as_ptr(), value.raw_value())
})
}
pub fn get_named_property<T: NapiValue>(&self, name: &str) -> Result<T> {
pub fn get_named_property<T>(&self, name: &str) -> Result<T>
where
T: NapiValue,
{
let key = CString::new(name)?;
let mut raw_value = ptr::null_mut();
check_status(unsafe {
@ -42,26 +52,134 @@ impl JsObject {
T::from_raw(self.0.env, raw_value)
}
pub fn get_property<K: NapiValue, T: NapiValue>(&self, key: &K) -> Result<T> {
let mut raw_value = ptr::null_mut();
pub fn has_named_property<S>(&self, name: S) -> Result<bool>
where
S: AsRef<str>,
{
let mut result = false;
let key = CString::new(name.as_ref())?;
check_status(unsafe {
sys::napi_get_property(self.0.env, self.0.value, key.raw_value(), &mut raw_value)
sys::napi_has_named_property(self.0.env, self.0.value, key.as_ptr(), &mut result)
})?;
T::from_raw(self.0.env, raw_value)
Ok(result)
}
pub fn get_property_names<T: NapiValue>(&self) -> Result<T> {
pub fn delete_property<S>(&mut self, name: S) -> Result<bool>
where
S: NapiValue,
{
let mut result = false;
check_status(unsafe {
sys::napi_delete_property(self.0.env, self.0.value, name.raw_value(), &mut result)
})?;
Ok(result)
}
pub fn delete_named_property(&mut self, name: &str) -> Result<bool> {
let mut result = false;
let key_str = CString::new(name)?;
let mut js_key = ptr::null_mut();
check_status(unsafe {
sys::napi_create_string_utf8(self.0.env, key_str.as_ptr(), name.len() as _, &mut js_key)
})?;
check_status(unsafe {
sys::napi_delete_property(self.0.env, self.0.value, js_key, &mut result)
})?;
Ok(result)
}
pub fn has_own_property(&self, key: &str) -> Result<bool> {
let mut result = false;
let string = CString::new(key)?;
let mut js_key = ptr::null_mut();
check_status(unsafe {
sys::napi_create_string_utf8(self.0.env, string.as_ptr(), key.len() as _, &mut js_key)
})?;
check_status(unsafe {
sys::napi_has_own_property(self.0.env, self.0.value, js_key, &mut result)
})?;
Ok(result)
}
pub fn has_own_property_js<K>(&self, key: K) -> Result<bool>
where
K: NapiValue,
{
let mut result = false;
check_status(unsafe {
sys::napi_has_own_property(self.0.env, self.0.value, key.raw_value(), &mut result)
})?;
Ok(result)
}
pub fn has_property(&self, name: &str) -> Result<bool> {
let string = CString::new(name)?;
let mut js_key = ptr::null_mut();
let mut result = false;
check_status(unsafe {
sys::napi_create_string_utf8(self.0.env, string.as_ptr(), name.len() as _, &mut js_key)
})?;
check_status(unsafe { sys::napi_has_property(self.0.env, self.0.value, js_key, &mut result) })?;
Ok(result)
}
pub fn has_property_js<K>(&self, name: K) -> Result<bool>
where
K: NapiValue,
{
let mut result = false;
check_status(unsafe {
sys::napi_has_property(self.0.env, self.0.value, name.raw_value(), &mut result)
})?;
Ok(result)
}
pub fn get_property_names<T>(&self) -> Result<T>
where
T: NapiValue,
{
let mut raw_value = ptr::null_mut();
let status = unsafe { sys::napi_get_property_names(self.0.env, self.0.value, &mut raw_value) };
check_status(status)?;
T::from_raw(self.0.env, raw_value)
}
pub fn set_index<T: NapiValue>(&mut self, index: usize, value: T) -> Result<()> {
self.set_number_indexed_property(Env::from_raw(self.0.env).create_int64(index as i64)?, value)
pub fn get_prototype<T>(&self) -> Result<T>
where
T: NapiValue,
{
let mut result = ptr::null_mut();
check_status(unsafe { sys::napi_get_prototype(self.0.env, self.0.value, &mut result) })?;
T::from_raw(self.0.env, result)
}
pub fn get_index<T: NapiValue>(&self, index: u32) -> Result<T> {
pub fn set_element<T>(&mut self, index: u32, value: T) -> Result<()>
where
T: NapiValue,
{
check_status(unsafe {
sys::napi_set_element(self.0.env, self.0.value, index, value.raw_value())
})
}
pub fn has_element(&self, index: u32) -> Result<bool> {
let mut result = false;
check_status(unsafe { sys::napi_has_element(self.0.env, self.0.value, index, &mut result) })?;
Ok(result)
}
pub fn delete_element(&mut self, index: u32) -> Result<bool> {
let mut result = false;
check_status(unsafe {
sys::napi_delete_element(self.0.env, self.0.value, index, &mut result)
})?;
Ok(result)
}
pub fn get_element<T>(&self, index: u32) -> Result<T>
where
T: NapiValue,
{
let mut raw_value = ptr::null_mut();
check_status(unsafe {
sys::napi_get_element(self.0.env, self.0.value, index, &mut raw_value)
@ -69,20 +187,19 @@ impl JsObject {
T::from_raw(self.0.env, raw_value)
}
pub fn is_array(&self) -> Result<bool> {
let mut is_array = false;
check_status(unsafe { sys::napi_is_array(self.0.env, self.0.value, &mut is_array) })?;
Ok(is_array)
}
pub fn is_buffer(&self) -> Result<bool> {
let mut is_buffer = false;
check_status(unsafe { sys::napi_is_buffer(self.0.env, self.0.value, &mut is_buffer) })?;
Ok(is_buffer)
}
pub fn to_buffer(&self) -> Result<JsBuffer> {
JsBuffer::from_raw(self.0.env, self.0.value)
pub fn define_properties(&mut self, properties: &[Property]) -> Result<()> {
check_status(unsafe {
sys::napi_define_properties(
self.0.env,
self.0.value,
properties.len() as _,
properties
.iter()
.map(|property| property.raw())
.collect::<Vec<sys::napi_property_descriptor>>()
.as_ptr(),
)
})
}
pub fn get_array_length(&self) -> Result<u32> {

View file

@ -0,0 +1,84 @@
use std::convert::From;
use std::ffi::CString;
use std::ptr;
use crate::{error::check_status, sys, Callback, Env, NapiValue, Result};
#[derive(Debug, Clone, Copy)]
pub struct Property<'env> {
name: &'env str,
pub(crate) raw_descriptor: sys::napi_property_descriptor,
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum PropertyAttributes {
Default = sys::napi_property_attributes::napi_default as _,
Writable = sys::napi_property_attributes::napi_writable as _,
Enumerable = sys::napi_property_attributes::napi_enumerable as _,
Configurable = sys::napi_property_attributes::napi_configurable as _,
Static = sys::napi_property_attributes::napi_static as _,
}
impl From<PropertyAttributes> for sys::napi_property_attributes {
fn from(value: PropertyAttributes) -> Self {
match value {
PropertyAttributes::Default => sys::napi_property_attributes::napi_default,
PropertyAttributes::Writable => sys::napi_property_attributes::napi_writable,
PropertyAttributes::Enumerable => sys::napi_property_attributes::napi_enumerable,
PropertyAttributes::Configurable => sys::napi_property_attributes::napi_configurable,
PropertyAttributes::Static => sys::napi_property_attributes::napi_static,
}
}
}
impl<'env> Property<'env> {
pub fn new(env: &'env Env, name: &'env str) -> Result<Self> {
let string_value = CString::new(name)?;
let mut result = ptr::null_mut();
check_status(unsafe {
sys::napi_create_string_utf8(env.0, string_value.as_ptr(), name.len() as _, &mut result)
})?;
Ok(Property {
name,
raw_descriptor: sys::napi_property_descriptor {
utf8name: ptr::null_mut(),
name: result,
method: None,
getter: None,
setter: None,
value: ptr::null_mut(),
attributes: sys::napi_property_attributes::napi_default,
data: ptr::null_mut(),
},
})
}
pub fn with_value<T: NapiValue>(mut self, value: T) -> Self {
self.raw_descriptor.value = T::raw_value(&value);
self
}
pub fn with_method(mut self, callback: Callback) -> Self {
self.raw_descriptor.method = Some(callback);
self
}
pub fn with_getter(mut self, callback: Callback) -> Self {
self.raw_descriptor.getter = Some(callback);
self
}
pub fn with_setter(mut self, callback: Callback) -> Self {
self.raw_descriptor.setter = Some(callback);
self
}
pub fn with_property_attributes(mut self, attributes: PropertyAttributes) {
self.raw_descriptor.attributes = attributes.into();
}
pub(crate) fn raw(&self) -> sys::napi_property_descriptor {
self.raw_descriptor
}
}

View file

@ -310,8 +310,8 @@ impl ser::SerializeSeq for SeqSerializer {
T: Serialize,
{
let env = Env::from_raw(self.array.0.env);
self.array.set_index(
self.current_index,
self.array.set_element(
self.current_index as _,
JsUnknown(value.serialize(Ser::new(&env))?),
)?;
self.current_index = self.current_index + 1;
@ -334,8 +334,8 @@ impl ser::SerializeTuple for SeqSerializer {
T: Serialize,
{
let env = Env::from_raw(self.array.0.env);
self.array.set_index(
self.current_index,
self.array.set_element(
self.current_index as _,
JsUnknown(value.serialize(Ser::new(&env))?),
)?;
self.current_index = self.current_index + 1;
@ -359,8 +359,8 @@ impl ser::SerializeTupleStruct for SeqSerializer {
T: Serialize,
{
let env = Env::from_raw(self.array.0.env);
self.array.set_index(
self.current_index,
self.array.set_element(
self.current_index as _,
JsUnknown(value.serialize(Ser::new(&env))?),
)?;
self.current_index = self.current_index + 1;
@ -384,8 +384,8 @@ impl ser::SerializeTupleVariant for SeqSerializer {
T: Serialize,
{
let env = Env::from_raw(self.array.0.env);
self.array.set_index(
self.current_index,
self.array.set_element(
self.current_index as _,
JsUnknown(value.serialize(Ser::new(&env))?),
)?;
self.current_index = self.current_index + 1;

View file

@ -29,15 +29,13 @@ impl JsString {
let len = self.len()? + 1;
let mut result = Vec::with_capacity(len);
unsafe {
let status = sys::napi_get_value_string_utf8(
check_status(sys::napi_get_value_string_utf8(
self.0.env,
self.0.value,
result.as_mut_ptr(),
len as u64,
&mut written_char_count,
);
check_status(status)?;
))?;
let ptr = result.as_ptr();
mem::forget(result);
Ok(slice::from_raw_parts(
@ -53,15 +51,14 @@ impl JsString {
let len = self.len()? + 1;
let mut result = Vec::with_capacity(len);
unsafe {
let status = sys::napi_get_value_string_utf8(
check_status(sys::napi_get_value_string_utf8(
self.0.env,
self.0.value,
result.as_mut_ptr(),
len as u64,
&mut written_char_count,
);
))?;
check_status(status)?;
let ptr = result.as_ptr();
mem::forget(result);
Ok(slice::from_raw_parts(
@ -81,15 +78,14 @@ impl JsString {
let len = self.len()? + 1;
let mut result = Vec::with_capacity(len);
unsafe {
let status = sys::napi_get_value_string_utf8(
check_status(sys::napi_get_value_string_utf8(
self.0.env,
self.0.value,
result.as_mut_ptr(),
len as u64,
&mut written_char_count,
);
))?;
check_status(status)?;
let ptr = result.as_ptr();
mem::forget(result);
Ok(slice::from_raw_parts_mut(
@ -108,14 +104,13 @@ impl TryFrom<JsString> for Vec<u16> {
unsafe {
let mut written_char_count = 0;
let status = sys::napi_get_value_string_utf16(
check_status(sys::napi_get_value_string_utf16(
value.0.env,
value.0.value,
result.as_mut_ptr(),
result.capacity() as u64,
&mut written_char_count,
);
check_status(status)?;
))?;
result.set_len(written_char_count as usize);
}

View file

@ -60,11 +60,11 @@
"@istanbuljs/nyc-config-typescript": "^1.0.1",
"@swc-node/register": "^0.4.5",
"@types/inquirer": "^7.3.1",
"@types/node": "^14.6.2",
"@types/node": "^14.6.3",
"@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1",
"ava": "^3.12.1",
"eslint": "^7.8.0",
"eslint": "^7.8.1",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-prettier": "^3.1.4",

View file

@ -0,0 +1,226 @@
import test from 'ava'
const bindings = require('../index.node')
test('setProperty', (t) => {
const obj = {}
const key = 'jsPropertyKey'
bindings.testSetProperty(obj, key)
t.snapshot(obj[key])
})
test('testGetProperty', (t) => {
const name = Symbol('JsSymbol')
const value = Symbol('JsValue')
const obj = {
[name]: value,
}
t.is(bindings.testGetProperty(obj, name), value)
})
test('setNamedProperty', (t) => {
const obj = {}
const property = Symbol('JsSymbol')
bindings.testSetNamedProperty(obj, property)
const keys = Object.keys(obj)
const [key] = keys
t.is(keys.length, 1)
t.snapshot(key)
t.is(obj[key], property)
})
test('testGetNamedProperty', (t) => {
const obj = {
p: Symbol('JsSymbol'),
}
t.is(bindings.testGetNamedProperty(obj), obj.p)
})
test('testHasNamedProperty', (t) => {
const obj = {
a: 1,
b: undefined,
}
t.true(bindings.testHasNamedProperty(obj, 'a'))
t.true(bindings.testHasNamedProperty(obj, 'b'))
t.false(bindings.testHasNamedProperty(obj, 'c'))
})
test('testHasOwnProperty', (t) => {
const obj = {
a: '1',
b: undefined,
}
const child = Object.create(obj, {
d: {
value: 1,
enumerable: true,
configurable: true,
},
})
t.false(bindings.testHasOwnProperty(child, 'a'))
t.false(bindings.testHasOwnProperty(child, 'b'))
t.true(bindings.testHasOwnProperty(child, 'd'))
})
test('testHasOwnPropertyJs', (t) => {
const obj = {
a: '1',
b: undefined,
}
const child = Object.create(obj)
child.c = 'k1'
t.false(bindings.testHasOwnPropertyJs(child, 'a'))
t.false(bindings.testHasOwnPropertyJs(child, 'b'))
t.true(bindings.testHasOwnPropertyJs(child, 'c'))
})
test('testHasProperty', (t) => {
const obj = {
a: '1',
b: undefined,
}
const child = Object.create(obj)
child.c = 'k1'
t.true(bindings.testHasProperty(child, 'a'))
t.true(bindings.testHasProperty(child, 'b'))
t.true(bindings.testHasProperty(child, 'c'))
t.false(bindings.testHasProperty(child, '__NOT_EXISTED__'))
})
test('testHasPropertJs', (t) => {
const key = Symbol('JsString')
const obj = {
[key]: 1,
a: 0,
b: undefined,
2: 'c',
}
t.true(bindings.testHasPropertyJs(obj, key))
t.true(bindings.testHasPropertyJs(obj, 'a'))
t.true(bindings.testHasPropertyJs(obj, 'b'))
t.true(bindings.testHasPropertyJs(obj, 2))
t.false(bindings.testHasPropertyJs(obj, {}))
t.false(bindings.testHasPropertyJs(obj, Symbol('JsString')))
})
test('testDeleteProperty', (t) => {
const k1 = Symbol()
const k2 = 2
const k3 = 'foo'
const obj = {
[k1]: 1,
[k2]: 2,
k4: 4,
}
Object.defineProperty(obj, k3, {
configurable: false,
enumerable: true,
value: 'k3',
})
t.true(bindings.testDeleteProperty(obj, k1))
t.true(bindings.testDeleteProperty(obj, k2))
t.false(bindings.testDeleteProperty(obj, k3))
t.true(bindings.testDeleteProperty(obj, 'k4'))
t.true(bindings.testDeleteProperty(obj, '__NOT_EXISTED__'))
t.true(bindings.testDeleteProperty(obj, k1))
// @ts-expect-error
t.deepEqual(obj, { [k3]: 'k3' })
})
test('testDeleteNamedProperty', (t) => {
const k1 = 'k1'
const k2 = 'k2'
const k3 = 'foo'
const obj = {
[k1]: 1,
[k2]: 2,
k4: 4,
}
Object.defineProperty(obj, k3, {
configurable: false,
enumerable: true,
value: 'k3',
})
t.true(bindings.testDeleteNamedProperty(obj, k1))
t.true(bindings.testDeleteNamedProperty(obj, k2))
t.false(bindings.testDeleteNamedProperty(obj, k3))
t.true(bindings.testDeleteNamedProperty(obj, 'k4'))
t.true(bindings.testDeleteNamedProperty(obj, '__NOT_EXISTED__'))
t.true(bindings.testDeleteNamedProperty(obj, k1))
// @ts-expect-error
t.deepEqual(obj, { [k3]: 'k3' })
})
test('testGetPropertyNames', (t) => {
const k1 = Symbol()
const k2 = 2
const k3 = 'k3'
const obj = {
[k1]: 1,
[k2]: 1,
[k3]: 1,
}
t.snapshot(
bindings
.testGetPropertyNames(obj)
.map((v: string | number) => v.toString()),
)
})
test('testGetPrototype', (t) => {
class A {}
class B extends A {}
const obj = new B()
t.is(bindings.testGetPrototype(obj), Object.getPrototypeOf(obj))
})
test('testSetElement', (t) => {
const arr: any[] = []
bindings.testSetElement(arr, 1, 1)
bindings.testSetElement(arr, 5, 'foo')
t.snapshot(arr)
})
test('testHasElement', (t) => {
const arr: number[] = []
arr[1] = 1
arr[4] = 0
t.false(bindings.testHasElement(arr, 0))
t.true(bindings.testHasElement(arr, 1))
t.false(bindings.testHasElement(arr, 2))
t.false(bindings.testHasElement(arr, 3))
t.true(bindings.testHasElement(arr, 4))
})
test('testGetElement', (t) => {
const arr = [Symbol(), Symbol()]
t.is(bindings.testGetElement(arr, 0), arr[0])
t.is(bindings.testGetElement(arr, 1), arr[1])
})
test('testDeleteElement', (t) => {
const arr = [0, 1, 2, 3]
bindings.testDeleteElement(arr, 1)
bindings.testDeleteElement(arr, 2)
t.snapshot(arr)
})
test('testDefineProperties', (t) => {
const obj: any = {}
bindings.testDefineProperties(obj)
t.is(obj.count, 0)
obj.add(10)
t.is(obj.count, 10)
const descriptor = Object.getOwnPropertyDescriptor(obj, 'ro')
t.is(descriptor?.value ?? descriptor?.get?.(), 'readonly')
})

View file

@ -0,0 +1,50 @@
# Snapshot report for `test_module/__test__/object.spec.ts`
The actual snapshot is saved in `object.spec.ts.snap`.
Generated by [AVA](https://avajs.dev).
## setProperty
> Snapshot 1
'Rust object property'
## setNamedProperty
> Snapshot 1
'RustPropertyKey'
## testGetPropertyNames
> Snapshot 1
[
'2',
'k3',
]
## testSetElement
> Snapshot 1
[
undefined,
1,
undefined,
undefined,
undefined,
'foo',
]
## testDeleteElement
> Snapshot 1
[
0,
undefined,
undefined,
3,
]

Binary file not shown.

View file

@ -1,6 +1,6 @@
use std::str;
use napi::{CallContext, Error, JsBuffer, JsNumber, JsString, Result, Status};
use napi::{CallContext, Error, JsBuffer, JsNumber, JsString, Module, Result, Status};
#[js_function(1)]
pub fn get_buffer_length(ctx: CallContext) -> Result<JsNumber> {
@ -15,3 +15,9 @@ pub fn buffer_to_string(ctx: CallContext) -> Result<JsString> {
str::from_utf8(&buffer).map_err(|e| Error::new(Status::StringExpected, format!("{}", e)))?,
)
}
pub fn register_js(module: &mut Module) -> Result<()> {
module.create_named_method("getBufferLength", get_buffer_length)?;
module.create_named_method("bufferToString", buffer_to_string)?;
Ok(())
}

View file

@ -1,18 +1,18 @@
use std::convert::TryInto;
use napi::{CallContext, JsFunction, JsNumber, JsObject, JsUndefined, Property, Result};
use napi::{CallContext, JsFunction, JsNumber, JsObject, JsUndefined, Module, Property, Result};
#[js_function(1)]
pub fn create_test_class(ctx: CallContext) -> Result<JsFunction> {
let add_count_method = Property::new("addCount").with_method(add_count);
fn create_test_class(ctx: CallContext) -> Result<JsFunction> {
let add_count_method = Property::new(&ctx.env, "addCount")?.with_method(add_count);
let properties = vec![add_count_method];
ctx
.env
.define_class("TestClass", test_class_constructor, properties)
.define_class("TestClass", test_class_constructor, properties.as_slice())
}
#[js_function(1)]
pub fn test_class_constructor(mut ctx: CallContext<JsObject>) -> Result<JsUndefined> {
fn test_class_constructor(mut ctx: CallContext<JsObject>) -> Result<JsUndefined> {
let count = ctx.get::<JsNumber>(0)?;
ctx
.this
@ -21,7 +21,7 @@ pub fn test_class_constructor(mut ctx: CallContext<JsObject>) -> Result<JsUndefi
}
#[js_function(1)]
pub fn add_count(mut ctx: CallContext<JsObject>) -> Result<JsUndefined> {
fn add_count(mut ctx: CallContext<JsObject>) -> Result<JsUndefined> {
let add: i32 = ctx.get::<JsNumber>(0)?.try_into()?;
let count: i32 = ctx
.this
@ -32,3 +32,8 @@ pub fn add_count(mut ctx: CallContext<JsObject>) -> Result<JsUndefined> {
.set_named_property("count", ctx.env.create_int32(count + add)?)?;
ctx.env.get_undefined()
}
pub fn register_js(module: &mut Module) -> Result<()> {
module.create_named_method("createTestClass", create_test_class)?;
Ok(())
}

View file

@ -1,6 +1,6 @@
use std::convert::TryInto;
use napi::{CallContext, Either, JsNumber, JsString, Result};
use napi::{CallContext, Either, JsNumber, JsString, Module, Result};
#[js_function(1)]
pub fn either_number_string(ctx: CallContext) -> Result<Either<JsNumber, JsString>> {
@ -27,3 +27,9 @@ pub fn dynamic_argument_length(ctx: CallContext) -> Result<JsNumber> {
ctx.env.create_uint32(42)
}
}
pub fn register_js(module: &mut Module) -> Result<()> {
module.create_named_method("eitherNumberString", either_number_string)?;
module.create_named_method("dynamicArgumentLength", dynamic_argument_length)?;
Ok(())
}

35
test_module/src/env.rs Normal file
View file

@ -0,0 +1,35 @@
use napi::{CallContext, JsBoolean, JsUnknown, Module, Result};
#[js_function(2)]
pub fn instanceof(ctx: CallContext) -> Result<JsBoolean> {
let object = ctx.get::<JsUnknown>(0)?;
let constructor = ctx.get::<JsUnknown>(1)?;
ctx.env.get_boolean(object.instanceof(constructor)?)
}
#[js_function(1)]
pub fn is_typedarray(ctx: CallContext) -> Result<JsBoolean> {
let js_value = ctx.get::<JsUnknown>(0)?;
ctx.env.get_boolean(js_value.is_typedarray()?)
}
#[js_function(1)]
pub fn is_dataview(ctx: CallContext) -> Result<JsBoolean> {
let js_value = ctx.get::<JsUnknown>(0)?;
ctx.env.get_boolean(js_value.is_dataview()?)
}
#[js_function(2)]
pub fn strict_equals(ctx: CallContext) -> Result<JsBoolean> {
let a: JsUnknown = ctx.get(0)?;
let b: JsUnknown = ctx.get(1)?;
ctx.env.get_boolean(ctx.env.strict_equals(a, b)?)
}
pub fn register_js(module: &mut Module) -> Result<()> {
module.create_named_method("instanceof", instanceof)?;
module.create_named_method("isTypedarray", is_typedarray)?;
module.create_named_method("isDataview", is_dataview)?;
module.create_named_method("strictEquals", strict_equals)?;
Ok(())
}

33
test_module/src/error.rs Normal file
View file

@ -0,0 +1,33 @@
use napi::{CallContext, Error, JsBoolean, JsString, JsUnknown, Module, Result, Status};
#[js_function]
fn test_throw(_ctx: CallContext) -> Result<JsUnknown> {
Err(Error::from_status(Status::GenericFailure))
}
#[js_function(1)]
fn test_throw_with_reason(ctx: CallContext) -> Result<JsUnknown> {
let reason = ctx.get::<JsString>(0)?;
Err(Error::new(
Status::GenericFailure,
reason.as_str()?.to_owned(),
))
}
#[js_function]
pub fn test_throw_with_panic(_ctx: CallContext) -> Result<JsUnknown> {
panic!("don't panic.");
}
#[js_function(1)]
pub fn is_error(ctx: CallContext) -> Result<JsBoolean> {
let js_value = ctx.get::<JsUnknown>(0)?;
ctx.env.get_boolean(js_value.is_error()?)
}
pub fn register_js(module: &mut Module) -> Result<()> {
module.create_named_method("testThrow", test_throw)?;
module.create_named_method("testThrowWithReason", test_throw_with_reason)?;
module.create_named_method("isError", is_error)?;
Ok(())
}

View file

@ -1,6 +1,6 @@
use std::convert::TryInto;
use napi::{CallContext, JsExternal, JsNumber, Result};
use napi::{CallContext, JsExternal, JsNumber, Module, Result};
struct NativeObject {
count: i32,
@ -19,3 +19,9 @@ pub fn get_external_count(ctx: CallContext) -> Result<JsNumber> {
let native_object = ctx.env.get_value_external::<NativeObject>(&attached_obj)?;
ctx.env.create_int32(native_object.count)
}
pub fn register_js(module: &mut Module) -> Result<()> {
module.create_named_method("createExternal", create_external)?;
module.create_named_method("getExternalCount", get_external_count)?;
Ok(())
}

View file

@ -1,4 +1,4 @@
use napi::{CallContext, JsFunction, JsNull, JsObject, Result};
use napi::{CallContext, JsFunction, JsNull, JsObject, Module, Result};
#[js_function(1)]
pub fn call_function(ctx: CallContext) -> Result<JsNull> {
@ -20,3 +20,9 @@ pub fn call_function_with_this(ctx: CallContext<JsObject>) -> Result<JsNull> {
ctx.env.get_null()
}
pub fn register_js(module: &mut Module) -> Result<()> {
module.create_named_method("testCallFunction", call_function)?;
module.create_named_method("testCallFunctionWithThis", call_function_with_this)?;
Ok(())
}

View file

@ -5,7 +5,7 @@ extern crate napi_derive;
#[macro_use]
extern crate serde_derive;
use napi::{CallContext, Error, JsBoolean, JsString, JsUnknown, Module, Result, Status};
use napi::{Module, Result};
#[cfg(napi4)]
mod libuv;
@ -21,142 +21,44 @@ mod tokio_rt;
mod buffer;
mod class;
mod either;
mod env;
mod error;
mod external;
mod function;
mod napi_version;
mod object;
mod serde;
mod string;
mod symbol;
mod task;
use buffer::{buffer_to_string, get_buffer_length};
use either::{dynamic_argument_length, either_number_string};
use external::{create_external, get_external_count};
use function::{call_function, call_function_with_this};
#[cfg(napi4)]
use libuv::read_file::uv_read_file;
#[cfg(napi4)]
use napi4::{test_threadsafe_function, test_tokio_readfile, test_tsfn_error};
#[cfg(napi5)]
use napi5::is_date::test_object_is_date;
#[cfg(napi6)]
use napi6::bigint::{
test_create_bigint_from_i128, test_create_bigint_from_i64, test_create_bigint_from_u128,
test_create_bigint_from_u64, test_create_bigint_from_words, test_get_bigint_i64,
test_get_bigint_u64, test_get_bigint_words,
};
use napi_version::get_napi_version;
use symbol::{create_named_symbol, create_symbol_from_js_string, create_unnamed_symbol};
use task::test_spawn_thread;
#[cfg(napi4)]
use tokio_rt::{error_from_tokio_future, test_execute_tokio_readfile};
register_module!(test_module, init);
fn init(module: &mut Module) -> Result<()> {
serde::register_serde_func(module)?;
module.create_named_method("testThrow", test_throw)?;
module.create_named_method("testThrowWithReason", test_throw_with_reason)?;
module.create_named_method("testSpawnThread", test_spawn_thread)?;
module.create_named_method("createExternal", create_external)?;
module.create_named_method("getExternalCount", get_external_count)?;
module.create_named_method("getBufferLength", get_buffer_length)?;
module.create_named_method("bufferToString", buffer_to_string)?;
module.create_named_method("createNamedSymbol", create_named_symbol)?;
module.create_named_method("createUnnamedSymbol", create_unnamed_symbol)?;
module.create_named_method("createSymbolFromJsString", create_symbol_from_js_string)?;
module.create_named_method("getNapiVersion", get_napi_version)?;
module.create_named_method("testCallFunction", call_function)?;
module.create_named_method("testCallFunctionWithThis", call_function_with_this)?;
module.create_named_method("eitherNumberString", either_number_string)?;
module.create_named_method("dynamicArgumentLength", dynamic_argument_length)?;
module.create_named_method("createTestClass", class::create_test_class)?;
module.create_named_method("concatString", string::concat_string)?;
module.create_named_method("instanceof", instanceof)?;
module.create_named_method("isError", is_error)?;
module.create_named_method("isTypedarray", is_typedarray)?;
module.create_named_method("isDataview", is_dataview)?;
module.create_named_method("strictEquals", strict_equals)?;
error::register_js(module)?;
string::register_js(module)?;
serde::register_js(module)?;
task::register_js(module)?;
external::register_js(module)?;
buffer::register_js(module)?;
either::register_js(module)?;
symbol::register_js(module)?;
function::register_js(module)?;
class::register_js(module)?;
env::register_js(module)?;
object::register_js(module)?;
#[cfg(napi4)]
module.create_named_method("testExecuteTokioReadfile", test_execute_tokio_readfile)?;
napi4::register_js(module)?;
#[cfg(napi4)]
module.create_named_method("testTsfnError", test_tsfn_error)?;
tokio_rt::register_js(module)?;
#[cfg(napi4)]
module.create_named_method("testThreadsafeFunction", test_threadsafe_function)?;
#[cfg(napi4)]
module.create_named_method("testTokioReadfile", test_tokio_readfile)?;
#[cfg(napi4)]
module.create_named_method("testTokioError", error_from_tokio_future)?;
#[cfg(napi4)]
module.create_named_method("uvReadFile", uv_read_file)?;
libuv::read_file::register_js(module)?;
#[cfg(napi5)]
module.create_named_method("testObjectIsDate", test_object_is_date)?;
napi5::register_js(module)?;
#[cfg(napi6)]
module.create_named_method("testCreateBigintFromI64", test_create_bigint_from_i64)?;
#[cfg(napi6)]
module.create_named_method("testCreateBigintFromU64", test_create_bigint_from_u64)?;
#[cfg(napi6)]
module.create_named_method("testCreateBigintFromI128", test_create_bigint_from_i128)?;
#[cfg(napi6)]
module.create_named_method("testCreateBigintFromU128", test_create_bigint_from_u128)?;
#[cfg(napi6)]
module.create_named_method("testCreateBigintFromWords", test_create_bigint_from_words)?;
#[cfg(napi6)]
module.create_named_method("testGetBigintI64", test_get_bigint_i64)?;
#[cfg(napi6)]
module.create_named_method("testGetBigintU64", test_get_bigint_u64)?;
#[cfg(napi6)]
module.create_named_method("testGetBigintWords", test_get_bigint_words)?;
napi6::register_js(module)?;
Ok(())
}
#[js_function]
fn test_throw(_ctx: CallContext) -> Result<JsUnknown> {
Err(Error::from_status(Status::GenericFailure))
}
#[js_function(1)]
fn test_throw_with_reason(ctx: CallContext) -> Result<JsUnknown> {
let reason = ctx.get::<JsString>(0)?;
Err(Error::new(
Status::GenericFailure,
reason.as_str()?.to_owned(),
))
}
#[js_function]
pub fn test_throw_with_panic(_ctx: CallContext) -> Result<JsUnknown> {
panic!("don't panic.");
}
#[js_function(2)]
pub fn instanceof(ctx: CallContext) -> Result<JsBoolean> {
let object = ctx.get::<JsUnknown>(0)?;
let constructor = ctx.get::<JsUnknown>(1)?;
ctx.env.get_boolean(object.instanceof(constructor)?)
}
#[js_function(1)]
pub fn is_error(ctx: CallContext) -> Result<JsBoolean> {
let js_value = ctx.get::<JsUnknown>(0)?;
ctx.env.get_boolean(js_value.is_error()?)
}
#[js_function(1)]
pub fn is_typedarray(ctx: CallContext) -> Result<JsBoolean> {
let js_value = ctx.get::<JsUnknown>(0)?;
ctx.env.get_boolean(js_value.is_typedarray()?)
}
#[js_function(1)]
pub fn is_dataview(ctx: CallContext) -> Result<JsBoolean> {
let js_value = ctx.get::<JsUnknown>(0)?;
ctx.env.get_boolean(js_value.is_dataview()?)
}
#[js_function(2)]
pub fn strict_equals(ctx: CallContext) -> Result<JsBoolean> {
let a: JsUnknown = ctx.get(0)?;
let b: JsUnknown = ctx.get(1)?;
ctx.env.get_boolean(ctx.env.strict_equals(a, b)?)
}

View file

@ -1,9 +1,9 @@
use std::thread;
use std::fs;
use std::thread;
use futures::prelude::*;
use futures::channel::oneshot;
use napi::{CallContext, Result, JsString, JsObject, Status, Error};
use futures::prelude::*;
use napi::{CallContext, Error, JsObject, JsString, Module, Result, Status};
#[js_function(1)]
pub fn uv_read_file(ctx: CallContext) -> Result<JsObject> {
@ -14,7 +14,15 @@ pub fn uv_read_file(ctx: CallContext) -> Result<JsObject> {
let res = fs::read(p).map_err(|e| Error::new(Status::Unknown, format!("{}", e)));
sender.send(res).expect("Send data failed");
});
ctx.env.execute(receiver.map_err(|e| Error::new(Status::Unknown, format!("{}", e))).map(|x| x.and_then(|x| x)), |&mut env, data| {
env.create_buffer_with_data(data)
})
ctx.env.execute(
receiver
.map_err(|e| Error::new(Status::Unknown, format!("{}", e)))
.map(|x| x.and_then(|x| x)),
|&mut env, data| env.create_buffer_with_data(data),
)
}
pub fn register_js(module: &mut Module) -> Result<()> {
module.create_named_method("uvReadFile", uv_read_file)?;
Ok(())
}

View file

@ -1,3 +1,12 @@
use napi::{Module, Result};
mod tsfn;
pub use tsfn::*;
use tsfn::*;
pub fn register_js(module: &mut Module) -> Result<()> {
module.create_named_method("testTsfnError", test_tsfn_error)?;
module.create_named_method("testThreadsafeFunction", test_threadsafe_function)?;
module.create_named_method("testTokioReadfile", test_tokio_readfile)?;
Ok(())
}

View file

@ -1 +1,8 @@
pub mod is_date;
use napi::{Module, Result};
mod date;
pub fn register_js(module: &mut Module) -> Result<()> {
module.create_named_method("testObjectIsDate", date::test_object_is_date)?;
Ok(())
}

View file

@ -49,13 +49,7 @@ pub fn test_get_bigint_words(ctx: CallContext) -> Result<JsObject> {
.create_bigint_from_words(true, vec![i64::max_value() as u64, i64::max_value() as u64])?;
let mut js_arr = ctx.env.create_array_with_length(2)?;
let (_signed, words) = js_bigint.get_words()?;
js_arr.set_number_indexed_property(
ctx.env.create_int64(0)?,
ctx.env.create_bigint_from_u64(words[0])?,
)?;
js_arr.set_number_indexed_property(
ctx.env.create_int64(1)?,
ctx.env.create_bigint_from_u64(words[1])?,
)?;
js_arr.set_element(0, ctx.env.create_bigint_from_u64(words[0])?)?;
js_arr.set_element(1, ctx.env.create_bigint_from_u64(words[1])?)?;
Ok(js_arr)
}

View file

@ -1 +1,17 @@
pub mod bigint;
use napi::{Module, Result};
mod bigint;
use bigint::*;
pub fn register_js(module: &mut Module) -> Result<()> {
module.create_named_method("testCreateBigintFromI64", test_create_bigint_from_i64)?;
module.create_named_method("testCreateBigintFromU64", test_create_bigint_from_u64)?;
module.create_named_method("testCreateBigintFromI128", test_create_bigint_from_i128)?;
module.create_named_method("testCreateBigintFromU128", test_create_bigint_from_u128)?;
module.create_named_method("testCreateBigintFromWords", test_create_bigint_from_words)?;
module.create_named_method("testGetBigintI64", test_get_bigint_i64)?;
module.create_named_method("testGetBigintU64", test_get_bigint_u64)?;
module.create_named_method("testGetBigintWords", test_get_bigint_words)?;
Ok(())
}

181
test_module/src/object.rs Normal file
View file

@ -0,0 +1,181 @@
use std::convert::TryInto;
use napi::{
CallContext, JsBoolean, JsNumber, JsObject, JsString, JsUndefined, JsUnknown, Module, Property,
Result,
};
#[js_function(2)]
fn test_set_property(ctx: CallContext) -> Result<JsUndefined> {
let mut obj = ctx.get::<JsObject>(0)?;
let key = ctx.get::<JsString>(1)?;
obj.set_property(key, ctx.env.create_string("Rust object property")?)?;
ctx.env.get_undefined()
}
#[js_function(2)]
fn test_set_named_property(ctx: CallContext) -> Result<JsUndefined> {
let mut obj = ctx.get::<JsObject>(0)?;
let property = ctx.get::<JsUnknown>(1)?;
obj.set_named_property("RustPropertyKey", property)?;
ctx.env.get_undefined()
}
#[js_function(1)]
fn test_get_named_property(ctx: CallContext) -> Result<JsUnknown> {
let obj = ctx.get::<JsObject>(0)?;
obj.get_named_property("p")
}
#[js_function(2)]
fn test_has_named_property(ctx: CallContext) -> Result<JsBoolean> {
let obj = ctx.get::<JsObject>(0)?;
let key = ctx.get::<JsString>(1)?;
ctx.env.get_boolean(obj.has_named_property(key.as_str()?)?)
}
#[js_function(2)]
fn test_has_own_property(ctx: CallContext) -> Result<JsBoolean> {
let obj = ctx.get::<JsObject>(0)?;
let key = ctx.get::<JsString>(1)?;
ctx.env.get_boolean(obj.has_own_property(key.as_str()?)?)
}
#[js_function(2)]
fn test_has_own_property_js(ctx: CallContext) -> Result<JsBoolean> {
let obj = ctx.get::<JsObject>(0)?;
let key = ctx.get::<JsUnknown>(1)?;
ctx.env.get_boolean(obj.has_own_property_js(key)?)
}
#[js_function(2)]
fn test_has_property(ctx: CallContext) -> Result<JsBoolean> {
let obj = ctx.get::<JsObject>(0)?;
let key = ctx.get::<JsString>(1)?;
ctx.env.get_boolean(obj.has_property(key.as_str()?)?)
}
#[js_function(2)]
fn test_has_property_js(ctx: CallContext) -> Result<JsBoolean> {
let obj = ctx.get::<JsObject>(0)?;
let key = ctx.get::<JsUnknown>(1)?;
ctx.env.get_boolean(obj.has_property_js(key)?)
}
#[js_function(2)]
fn test_delete_property(ctx: CallContext) -> Result<JsBoolean> {
let mut obj = ctx.get::<JsObject>(0)?;
let key = ctx.get::<JsUnknown>(1)?;
ctx.env.get_boolean(obj.delete_property(key)?)
}
#[js_function(2)]
fn test_delete_named_property(ctx: CallContext) -> Result<JsBoolean> {
let mut obj = ctx.get::<JsObject>(0)?;
let key = ctx.get::<JsString>(1)?;
ctx
.env
.get_boolean(obj.delete_named_property(key.as_str()?)?)
}
#[js_function(2)]
fn test_get_property(ctx: CallContext) -> Result<JsUnknown> {
let obj = ctx.get::<JsObject>(0)?;
let key = ctx.get::<JsUnknown>(1)?;
obj.get_property(&key)
}
#[js_function(1)]
fn test_get_property_names(ctx: CallContext) -> Result<JsUnknown> {
let obj = ctx.get::<JsObject>(0)?;
obj.get_property_names()
}
#[js_function(1)]
fn test_get_prototype(ctx: CallContext) -> Result<JsUnknown> {
let obj = ctx.get::<JsObject>(0)?;
obj.get_prototype()
}
#[js_function(3)]
fn test_set_element(ctx: CallContext) -> Result<JsUndefined> {
let mut obj = ctx.get::<JsObject>(0)?;
let index = ctx.get::<JsNumber>(1)?;
let js_value = ctx.get::<JsUnknown>(2)?;
obj.set_element(index.try_into()?, js_value)?;
ctx.env.get_undefined()
}
#[js_function(2)]
fn test_has_element(ctx: CallContext) -> Result<JsBoolean> {
let obj = ctx.get::<JsObject>(0)?;
let index = ctx.get::<JsNumber>(1)?;
ctx.env.get_boolean(obj.has_element(index.try_into()?)?)
}
#[js_function(2)]
fn test_get_element(ctx: CallContext) -> Result<JsUnknown> {
let obj = ctx.get::<JsObject>(0)?;
let index = ctx.get::<JsNumber>(1)?;
obj.get_element(index.try_into()?)
}
#[js_function(2)]
fn test_delete_element(ctx: CallContext) -> Result<JsBoolean> {
let mut obj: JsObject = ctx.get(0)?;
let index = ctx.get::<JsNumber>(1)?;
ctx.env.get_boolean(obj.delete_element(index.try_into()?)?)
}
#[js_function(1)]
fn test_define_properties(ctx: CallContext) -> Result<JsUndefined> {
let mut obj = ctx.get::<JsObject>(0)?;
let add_method = Property::new(&ctx.env, "add")?.with_method(add);
let readonly_property = Property::new(&ctx.env, "ro")?.with_getter(readonly_getter);
let properties = vec![add_method, readonly_property];
obj.define_properties(&properties)?;
obj.set_named_property("count", ctx.env.create_int32(0)?)?;
ctx.env.get_undefined()
}
#[js_function(1)]
fn add(mut ctx: CallContext<JsObject>) -> Result<JsUndefined> {
let count: i32 = ctx
.this
.get_named_property::<JsNumber>("count")?
.try_into()?;
let value_to_add: i32 = ctx.get::<JsNumber>(0)?.try_into()?;
ctx
.this
.set_named_property("count", ctx.env.create_int32(count + value_to_add)?)?;
ctx.env.get_undefined()
}
#[js_function]
fn readonly_getter(ctx: CallContext) -> Result<JsString> {
ctx.env.create_string("readonly")
}
pub fn register_js(module: &mut Module) -> Result<()> {
module.create_named_method("testSetProperty", test_set_property)?;
module.create_named_method("testGetProperty", test_get_property)?;
module.create_named_method("testSetNamedProperty", test_set_named_property)?;
module.create_named_method("testGetNamedProperty", test_get_named_property)?;
module.create_named_method("testHasNamedProperty", test_has_named_property)?;
module.create_named_method("testHasOwnProperty", test_has_own_property)?;
module.create_named_method("testHasOwnPropertyJs", test_has_own_property_js)?;
module.create_named_method("testHasProperty", test_has_property)?;
module.create_named_method("testHasPropertyJs", test_has_property_js)?;
module.create_named_method("testDeleteProperty", test_delete_property)?;
module.create_named_method("testDeleteNamedProperty", test_delete_named_property)?;
module.create_named_method("testGetPropertyNames", test_get_property_names)?;
module.create_named_method("testGetPrototype", test_get_prototype)?;
module.create_named_method("testSetElement", test_set_element)?;
module.create_named_method("testHasElement", test_has_element)?;
module.create_named_method("testGetElement", test_get_element)?;
module.create_named_method("testDeleteElement", test_delete_element)?;
module.create_named_method("testDefineProperties", test_define_properties)?;
Ok(())
}

View file

@ -162,7 +162,7 @@ fn roundtrip_object(ctx: CallContext) -> Result<JsUnknown> {
ctx.env.to_js_value(&de_serialized)
}
pub fn register_serde_func(m: &mut Module) -> Result<()> {
pub fn register_js(m: &mut Module) -> Result<()> {
m.create_named_method("make_num_77", make_num_77)?;
m.create_named_method("make_num_32", make_num_32)?;
m.create_named_method("make_str_hello", make_str_hello)?;

View file

@ -1,4 +1,4 @@
use napi::{CallContext, JsString, Result};
use napi::{CallContext, JsString, Module, Result};
#[js_function(1)]
pub fn concat_string(ctx: CallContext) -> Result<JsString> {
@ -6,3 +6,8 @@ pub fn concat_string(ctx: CallContext) -> Result<JsString> {
let out_string = format!("{} + Rust 🦀 string!", in_string.as_str()?);
ctx.env.create_string_from_std(out_string)
}
pub fn register_js(module: &mut Module) -> Result<()> {
module.create_named_method("concatString", concat_string)?;
Ok(())
}

View file

@ -1,4 +1,4 @@
use napi::{CallContext, JsString, JsSymbol, Result};
use napi::{CallContext, JsString, JsSymbol, Module, Result};
#[js_function]
pub fn create_named_symbol(ctx: CallContext) -> Result<JsSymbol> {
@ -15,3 +15,10 @@ pub fn create_symbol_from_js_string(ctx: CallContext) -> Result<JsSymbol> {
let name = ctx.get::<JsString>(0)?;
ctx.env.create_symbol_from_js_string(name)
}
pub fn register_js(module: &mut Module) -> Result<()> {
module.create_named_method("createNamedSymbol", create_named_symbol)?;
module.create_named_method("createUnnamedSymbol", create_unnamed_symbol)?;
module.create_named_method("createSymbolFromJsString", create_symbol_from_js_string)?;
Ok(())
}

View file

@ -1,6 +1,6 @@
use std::convert::TryInto;
use napi::{CallContext, Env, JsNumber, JsObject, Result, Task};
use napi::{CallContext, Env, JsNumber, JsObject, Module, Result, Task};
struct ComputeFib {
n: u32,
@ -34,8 +34,13 @@ fn fibonacci_native(n: u32) -> u32 {
}
#[js_function(1)]
pub fn test_spawn_thread(ctx: CallContext) -> Result<JsObject> {
fn test_spawn_thread(ctx: CallContext) -> Result<JsObject> {
let n = ctx.get::<JsNumber>(0)?;
let task = ComputeFib::new(n.try_into()?);
ctx.env.spawn(task)
}
pub fn register_js(module: &mut Module) -> Result<()> {
module.create_named_method("testSpawnThread", test_spawn_thread)?;
Ok(())
}

View file

@ -1,3 +1,11 @@
use napi::{Module, Result};
mod read_file;
pub use read_file::*;
use read_file::*;
pub fn register_js(module: &mut Module) -> Result<()> {
module.create_named_method("testExecuteTokioReadfile", test_execute_tokio_readfile)?;
module.create_named_method("testTokioError", error_from_tokio_future)?;
Ok(())
}

View file

@ -183,14 +183,20 @@
dependencies:
arrify "^1.0.1"
"@eslint/eslintrc@^0.1.0":
version "0.1.0"
resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.0.tgz#3d1f19fb797d42fb1c85458c1c73541eeb1d9e76"
integrity sha512-bfL5365QSCmH6cPeFT7Ywclj8C7LiF7sO6mUGzZhtAMV7iID1Euq6740u/SRi4C80NOnVz/CEfK8/HO+nCAPJg==
"@eslint/eslintrc@^0.1.3":
version "0.1.3"
resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz#7d1a2b2358552cc04834c0979bd4275362e37085"
integrity sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA==
dependencies:
ajv "^6.12.4"
debug "^4.1.1"
espree "^7.3.0"
globals "^12.1.0"
ignore "^4.0.6"
import-fresh "^3.2.1"
js-yaml "^3.13.1"
lodash "^4.17.19"
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
"@istanbuljs/load-nyc-config@^1.0.0":
@ -340,10 +346,10 @@
resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
"@types/node@*", "@types/node@^14.6.2":
version "14.6.2"
resolved "https://registry.npmjs.org/@types/node/-/node-14.6.2.tgz#264b44c5a28dfa80198fc2f7b6d3c8a054b9491f"
integrity sha512-onlIwbaeqvZyniGPfdw/TEhKIh79pz66L1q06WUQqJLnAb6wbjvOtepLYTGHTqzdXgBYIE3ZdmqHDGsRsbBz7A==
"@types/node@*", "@types/node@^14.6.3":
version "14.6.3"
resolved "https://registry.npmjs.org/@types/node/-/node-14.6.3.tgz#cc4f979548ca4d8e7b90bc0180052ab99ee64224"
integrity sha512-pC/hkcREG6YfDfui1FBmj8e20jFU5Exjw4NYDm8kEdrW+mOh0T1Zve8DWKnS7ZIZvgncrctcNCXF4Q2I+loyww==
"@types/normalize-package-data@^2.4.0":
version "2.4.0"
@ -1318,13 +1324,13 @@ eslint-visitor-keys@^2.0.0:
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
eslint@^7.8.0:
version "7.8.0"
resolved "https://registry.npmjs.org/eslint/-/eslint-7.8.0.tgz#9a3e2e6e4d0a3f8c42686073c25ebf2e91443e8a"
integrity sha512-qgtVyLZqKd2ZXWnLQA4NtVbOyH56zivOAdBFWE54RFkSZjokzNrcP4Z0eVWsZ+84ByXv+jL9k/wE1ENYe8xRFw==
eslint@^7.8.1:
version "7.8.1"
resolved "https://registry.npmjs.org/eslint/-/eslint-7.8.1.tgz#e59de3573fb6a5be8ff526c791571646d124a8fa"
integrity sha512-/2rX2pfhyUG0y+A123d0ccXtMm7DV7sH1m3lk9nk2DZ2LReq39FXHueR9xZwshE5MdfSf0xunSaMWRqyIA6M1w==
dependencies:
"@babel/code-frame" "^7.0.0"
"@eslint/eslintrc" "^0.1.0"
"@eslint/eslintrc" "^0.1.3"
ajv "^6.10.0"
chalk "^4.0.0"
cross-spawn "^7.0.2"
@ -2127,9 +2133,9 @@ json-parse-better-errors@^1.0.1:
integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
json-parse-even-better-errors@^2.3.0:
version "2.3.0"
resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.0.tgz#371873c5ffa44304a6ba12419bcfa95f404ae081"
integrity sha512-o3aP+RsWDJZayj1SbHNQAI8x0v3T3SKiGoZlNYfbUP1S3omJQ6i9CnqADqkSPaOAxwua4/1YWx5CM7oiChJt2Q==
version "2.3.1"
resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
json-schema-traverse@^0.4.1:
version "0.4.1"