From 6c95d86d2f129a2beeacbd5fbbcb6cf8423f73d4 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 10 Oct 2020 14:50:35 +0800 Subject: [PATCH] feat(napi): implement date related API --- .github/workflows/test.yaml | 3 +-- README.md | 4 ++-- napi/src/env.rs | 13 ++++++++++--- napi/src/js_values/date.rs | 14 ++++++++++++++ napi/src/js_values/mod.rs | 8 ++++++++ .../napi5/{is-date.spec.ts => date.spec.ts} | 18 ++++++++++++++++++ test_module/src/napi5/date.rs | 16 +++++++++++++++- test_module/src/napi5/mod.rs | 2 ++ 8 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 napi/src/js_values/date.rs rename test_module/__test__/napi5/{is-date.spec.ts => date.spec.ts} (58%) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index e6478f8c..154a8e1c 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -87,8 +87,7 @@ jobs: - name: Unit tests run: | - yarn - yarn --cwd ./test_module build + yarn build:test yarn test env: RUST_BACKTRACE: 1 diff --git a/README.md b/README.md index 50a91f94..5e23a903 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,7 @@ yarn test | [napi_create_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_create_arraybuffer) | 1 | v8.0.0 | ✅ | | [napi_create_buffer](https://nodejs.org/api/n-api.html#n_api_napi_create_buffer) | 1 | v8.0.0 | ✅ | | [napi_create_buffer_copy](https://nodejs.org/api/n-api.html#n_api_napi_create_buffer_copy) | 1 | v8.0.0 | ⛔️ | -| [napi_create_date](https://nodejs.org/api/n-api.html#n_api_napi_create_date) | 5 | v11.11.0 | ⛔️ | +| [napi_create_date](https://nodejs.org/api/n-api.html#n_api_napi_create_date) | 5 | v11.11.0 | ✅ | | [napi_create_external](https://nodejs.org/api/n-api.html#n_api_napi_create_external) | 1 | v8.0.0 | ✅ | | [napi_create_external_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_create_external_arraybuffer) | 1 | v8.0.0 | ✅ | | [napi_create_external_buffer](https://nodejs.org/api/n-api.html#n_api_napi_create_external_buffer) | 1 | v8.0.0 | ✅ | @@ -187,7 +187,7 @@ yarn test | [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 | ⛔️ | +| [napi_get_date_value](https://nodejs.org/api/n-api.html#n_api_napi_get_date_value) | 5 | v11.11.0 | ✅ | | [napi_get_value_bool](https://nodejs.org/api/n-api.html#n_api_napi_get_value_bool) | 1 | v8.0.0 | ✅ | | [napi_get_value_double](https://nodejs.org/api/n-api.html#n_api_napi_get_value_double) | 1 | v8.0.0 | ✅ | | [napi_get_value_bigint_int64](https://nodejs.org/api/n-api.html#n_api_napi_get_value_bigint_int64) | 6 | v10.7.0 | ✅ | diff --git a/napi/src/env.rs b/napi/src/env.rs index 8311dc78..904bbd89 100644 --- a/napi/src/env.rs +++ b/napi/src/env.rs @@ -629,13 +629,20 @@ impl Env { Ok(JsObject::from_raw_unchecked(self.0, raw_promise)) } + #[cfg(napi5)] + pub fn create_date(&self, time: f64) -> Result { + let mut js_value = ptr::null_mut(); + check_status(unsafe { sys::napi_create_date(self.0, time, &mut js_value) })?; + Ok(JsDate::from_raw_unchecked(self.0, js_value)) + } + /// # Serialize `Rust Struct` into `JavaScript Value` /// ``` /// #[derive(Serialize, Debug, Deserialize)] /// struct AnObject { - /// a: u32, - /// b: Vec, - /// c: String, + /// a: u32, + /// b: Vec, + /// c: String, /// } /// /// #[js_function] diff --git a/napi/src/js_values/date.rs b/napi/src/js_values/date.rs new file mode 100644 index 00000000..8c17c48c --- /dev/null +++ b/napi/src/js_values/date.rs @@ -0,0 +1,14 @@ +use super::check_status; +use crate::{sys, Result, Value}; + +#[repr(transparent)] +#[derive(Debug)] +pub struct JsDate(pub(crate) Value); + +impl JsDate { + pub fn value_of(&self) -> Result { + let mut timestamp: f64 = 0.0; + check_status(unsafe { sys::napi_get_date_value(self.0.env, self.0.value, &mut timestamp) })?; + Ok(timestamp) + } +} diff --git a/napi/src/js_values/mod.rs b/napi/src/js_values/mod.rs index 1eb7f065..d17fc07b 100644 --- a/napi/src/js_values/mod.rs +++ b/napi/src/js_values/mod.rs @@ -15,6 +15,8 @@ mod arraybuffer; mod bigint; mod boolean; mod buffer; +#[cfg(napi5)] +mod date; mod either; mod escapable_handle_scope; mod function; @@ -34,6 +36,8 @@ pub use arraybuffer::*; pub use bigint::JsBigint; pub use boolean::JsBoolean; pub use buffer::*; +#[cfg(napi5)] +pub use date::*; #[cfg(feature = "serde-json")] pub(crate) use de::De; pub use either::Either; @@ -440,6 +444,8 @@ impl_js_value_methods!(JsNumber); impl_js_value_methods!(JsString); impl_js_value_methods!(JsObject); impl_js_value_methods!(JsGlobal); +#[cfg(napi5)] +impl_js_value_methods!(JsDate); impl_js_value_methods!(JsFunction); impl_js_value_methods!(JsExternal); impl_js_value_methods!(JsSymbol); @@ -461,6 +467,8 @@ impl_napi_value_trait!(JsNumber, Number); impl_napi_value_trait!(JsString, String); impl_napi_value_trait!(JsObject, Object); impl_napi_value_trait!(JsGlobal, Object); +#[cfg(napi5)] +impl_napi_value_trait!(JsDate, Object); impl_napi_value_trait!(JsTimeout, Object); impl_napi_value_trait!(JsFunction, Function); impl_napi_value_trait!(JsExternal, External); diff --git a/test_module/__test__/napi5/is-date.spec.ts b/test_module/__test__/napi5/date.spec.ts similarity index 58% rename from test_module/__test__/napi5/is-date.spec.ts rename to test_module/__test__/napi5/date.spec.ts index e27fb186..e3583e6e 100644 --- a/test_module/__test__/napi5/is-date.spec.ts +++ b/test_module/__test__/napi5/date.spec.ts @@ -22,3 +22,21 @@ test('should return true if value is date', (t) => { t.is(bindings.testObjectIsDate, undefined) } }) + +test('should create date', (t) => { + if (napiVersion >= 5) { + const timestamp = new Date().valueOf() + t.deepEqual(bindings.testCreateDate(timestamp), new Date(timestamp)) + } else { + t.is(bindings.testObjectIsDate, undefined) + } +}) + +test('should get date value', (t) => { + if (napiVersion >= 5) { + const date = new Date() + t.is(bindings.testGetDateValue(date), date.valueOf()) + } else { + t.is(bindings.testObjectIsDate, undefined) + } +}) diff --git a/test_module/src/napi5/date.rs b/test_module/src/napi5/date.rs index a115503d..c23ca7c4 100644 --- a/test_module/src/napi5/date.rs +++ b/test_module/src/napi5/date.rs @@ -1,7 +1,21 @@ -use napi::{CallContext, JsBoolean, JsUnknown, Result}; +use std::convert::TryInto; + +use napi::{CallContext, JsBoolean, JsDate, JsNumber, JsUnknown, Result}; #[js_function(1)] pub fn test_object_is_date(ctx: CallContext) -> Result { let obj = ctx.get::(0)?; ctx.env.get_boolean(obj.is_date()?) } + +#[js_function(1)] +pub fn test_create_date(ctx: CallContext) -> Result { + let timestamp: f64 = ctx.get::(0)?.try_into()?; + ctx.env.create_date(timestamp) +} + +#[js_function(1)] +pub fn test_get_date_value(ctx: CallContext) -> Result { + let date = ctx.get::(0)?; + ctx.env.create_double(date.value_of()?) +} diff --git a/test_module/src/napi5/mod.rs b/test_module/src/napi5/mod.rs index 2554cc82..7abded31 100644 --- a/test_module/src/napi5/mod.rs +++ b/test_module/src/napi5/mod.rs @@ -4,5 +4,7 @@ mod date; pub fn register_js(module: &mut Module) -> Result<()> { module.create_named_method("testObjectIsDate", date::test_object_is_date)?; + module.create_named_method("testCreateDate", date::test_create_date)?; + module.create_named_method("testGetDateValue", date::test_get_date_value)?; Ok(()) }