Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change(neon): Change TryIntoJs and TryFromJs accept Cx instead of being generic over Context #1062

Merged
merged 2 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/neon/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ pub trait Context<'a>: ContextInternal<'a> {
///
/// ```
/// # use neon::prelude::*;
/// # fn get_array_global<'cx, C: Context<'cx>>(cx: &mut C) -> JsResult<'cx, JsFunction> {
/// # fn get_array_global<'cx>(cx: &mut Cx<'cx>) -> JsResult<'cx, JsFunction> {
/// # let name = "Array";
/// # let v: Handle<JsFunction> =
/// {
Expand Down
25 changes: 6 additions & 19 deletions crates/neon/src/macro_internal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pub use linkme;

use crate::{
context::{Context, ModuleContext},
context::{Cx, ModuleContext},
handle::Handle,
result::{JsResult, NeonResult},
types::{extract::TryIntoJs, JsValue},
Expand All @@ -19,19 +19,14 @@ pub static MAIN: [for<'cx> fn(ModuleContext<'cx>) -> NeonResult<()>];

// Provides an identically named method to `NeonExportReturnJson` for easy swapping in macros
pub trait NeonExportReturnValue<'cx> {
fn try_neon_export_return<C>(self, cx: &mut C) -> JsResult<'cx, JsValue>
where
C: Context<'cx>;
fn try_neon_export_return(self, cx: &mut Cx<'cx>) -> JsResult<'cx, JsValue>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is such a quality of life improvement. Wow.

}

impl<'cx, T> NeonExportReturnValue<'cx> for T
where
T: TryIntoJs<'cx>,
{
fn try_neon_export_return<C>(self, cx: &mut C) -> JsResult<'cx, JsValue>
where
C: Context<'cx>,
{
fn try_neon_export_return(self, cx: &mut Cx<'cx>) -> JsResult<'cx, JsValue> {
self.try_into_js(cx).map(|v| v.upcast())
}
}
Expand All @@ -40,9 +35,7 @@ where
// Trait used for specializing `Json` wrapping of `T` or `Result<T, _>` in macros
// Leverages the [autoref specialization](https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md) technique
pub trait NeonExportReturnJson<'cx> {
fn try_neon_export_return<C>(self, cx: &mut C) -> JsResult<'cx, JsValue>
where
C: Context<'cx>;
fn try_neon_export_return(self, cx: &mut Cx<'cx>) -> JsResult<'cx, JsValue>;
}

#[cfg(feature = "serde")]
Expand All @@ -52,10 +45,7 @@ where
T: serde::Serialize,
E: TryIntoJs<'cx>,
{
fn try_neon_export_return<C>(self, cx: &mut C) -> JsResult<'cx, JsValue>
where
C: Context<'cx>,
{
fn try_neon_export_return(self, cx: &mut Cx<'cx>) -> JsResult<'cx, JsValue> {
self.map(crate::types::extract::Json).try_into_js(cx)
}
}
Expand All @@ -66,10 +56,7 @@ impl<'cx, T> NeonExportReturnJson<'cx> for &T
where
T: serde::Serialize,
{
fn try_neon_export_return<C>(self, cx: &mut C) -> JsResult<'cx, JsValue>
where
C: Context<'cx>,
{
fn try_neon_export_return(self, cx: &mut Cx<'cx>) -> JsResult<'cx, JsValue> {
crate::types::extract::Json(self).try_into_js(cx)
}
}
2 changes: 1 addition & 1 deletion crates/neon/src/thread/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
//! # use neon::thread::LocalKey;
//! static THREAD_ID: LocalKey<u32> = LocalKey::new();
//!
//! pub fn thread_id<'cx, C: Context<'cx>>(cx: &mut C) -> NeonResult<u32> {
//! pub fn thread_id(cx: &mut Cx) -> NeonResult<u32> {
//! THREAD_ID.get_or_try_init(cx, |cx| {
//! let require: Handle<JsFunction> = cx.global("require")?;
//! let worker: Handle<JsObject> = require.call_with(cx)
Expand Down
7 changes: 2 additions & 5 deletions crates/neon/src/types_impl/extract/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{error, fmt};

use crate::{
context::Context,
context::{Context, Cx},
result::JsResult,
types::{extract::TryIntoJs, JsError},
};
Expand Down Expand Up @@ -114,10 +114,7 @@ impl fmt::Display for Error {
impl<'cx> TryIntoJs<'cx> for Error {
type Value = JsError;

fn try_into_js<C>(self, cx: &mut C) -> JsResult<'cx, Self::Value>
where
C: Context<'cx>,
{
fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {
let message = self.cause.to_string();

match self.kind {
Expand Down
60 changes: 15 additions & 45 deletions crates/neon/src/types_impl/extract/json.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
context::Context,
context::{Context, Cx},
handle::Handle,
object::Object,
result::{JsResult, NeonResult},
Expand All @@ -12,10 +12,7 @@ use crate::{
#[cfg(feature = "napi-6")]
use crate::{handle::Root, thread::LocalKey};

fn global_json_stringify<'cx, C>(cx: &mut C) -> JsResult<'cx, JsFunction>
where
C: Context<'cx>,
{
fn global_json_stringify<'cx>(cx: &mut Cx<'cx>) -> JsResult<'cx, JsFunction> {
cx.global::<JsObject>("JSON")?.get(cx, "stringify")
}

Expand All @@ -24,66 +21,45 @@ where
// method could cause differences between calls. However, threading a `Root` through
// would require a significant refactor and "don't do this or things will break" is
// fairly common in JS.
fn json_stringify<'cx, C>(cx: &mut C) -> JsResult<'cx, JsFunction>
where
C: Context<'cx>,
{
fn json_stringify<'cx, C>(cx: &mut Cx<'cx>) -> JsResult<'cx, JsFunction> {
global_json_stringify(cx)
}

#[cfg(feature = "napi-6")]
fn json_stringify<'cx, C>(cx: &mut C) -> JsResult<'cx, JsFunction>
where
C: Context<'cx>,
{
fn json_stringify<'cx>(cx: &mut Cx<'cx>) -> JsResult<'cx, JsFunction> {
static STRINGIFY: LocalKey<Root<JsFunction>> = LocalKey::new();

STRINGIFY
.get_or_try_init(cx, |cx| global_json_stringify(cx).map(|f| f.root(cx)))
.map(|f| f.to_inner(cx))
}

fn stringify<'cx, C>(cx: &mut C, v: Handle<JsValue>) -> NeonResult<String>
where
C: Context<'cx>,
{
fn stringify<'cx>(cx: &mut Cx<'cx>, v: Handle<JsValue>) -> NeonResult<String> {
json_stringify(cx)?
.call(cx, v, [v])?
.downcast_or_throw::<JsString, _>(cx)
.map(|s| s.value(cx))
}

fn global_json_parse<'cx, C>(cx: &mut C) -> JsResult<'cx, JsFunction>
where
C: Context<'cx>,
{
fn global_json_parse<'cx>(cx: &mut Cx<'cx>) -> JsResult<'cx, JsFunction> {
cx.global::<JsObject>("JSON")?.get(cx, "parse")
}

#[cfg(not(feature = "napi-6"))]
fn json_parse<'cx, C>(cx: &mut C) -> JsResult<'cx, JsFunction>
where
C: Context<'cx>,
{
fn json_parse<'cx>(cx: &mut Cx<'cx>) -> JsResult<'cx, JsFunction> {
global_json_parse(cx)
}

#[cfg(feature = "napi-6")]
fn json_parse<'cx, C>(cx: &mut C) -> JsResult<'cx, JsFunction>
where
C: Context<'cx>,
{
fn json_parse<'cx>(cx: &mut Cx<'cx>) -> JsResult<'cx, JsFunction> {
static PARSE: LocalKey<Root<JsFunction>> = LocalKey::new();

PARSE
.get_or_try_init(cx, |cx| global_json_parse(cx).map(|f| f.root(cx)))
.map(|f| f.to_inner(cx))
}

fn parse<'cx, C>(cx: &mut C, s: &str) -> JsResult<'cx, JsValue>
where
C: Context<'cx>,
{
fn parse<'cx>(cx: &mut Cx<'cx>, s: &str) -> JsResult<'cx, JsValue> {
let s = cx.string(s).upcast();

json_parse(cx)?.call(cx, s, [s])
Expand All @@ -99,17 +75,14 @@ where
{
type Error = serde_json::Error;

fn try_from_js<C>(cx: &mut C, v: Handle<'cx, JsValue>) -> NeonResult<Result<Self, Self::Error>>
where
C: Context<'cx>,
{
fn try_from_js(
cx: &mut Cx<'cx>,
v: Handle<'cx, JsValue>,
) -> NeonResult<Result<Self, Self::Error>> {
Ok(serde_json::from_str(&stringify(cx, v)?).map(Json))
}

fn from_js<C>(cx: &mut C, v: Handle<'cx, JsValue>) -> NeonResult<Self>
where
C: Context<'cx>,
{
fn from_js(cx: &mut Cx<'cx>, v: Handle<'cx, JsValue>) -> NeonResult<Self> {
Self::try_from_js(cx, v)?.or_else(|err| cx.throw_error(err.to_string()))
}
}
Expand All @@ -120,10 +93,7 @@ where
{
type Value = JsValue;

fn try_into_js<C>(self, cx: &mut C) -> JsResult<'cx, Self::Value>
where
C: Context<'cx>,
{
fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {
let s = serde_json::to_string(&self.0).or_else(|err| cx.throw_error(err.to_string()))?;

parse(cx, &s)
Expand Down
17 changes: 7 additions & 10 deletions crates/neon/src/types_impl/extract/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
use std::{fmt, marker::PhantomData};

use crate::{
context::{Context, FunctionContext},
context::{Context, Cx, FunctionContext},
handle::Handle,
result::{JsResult, NeonResult, ResultExt},
types::{JsValue, Value},
Expand Down Expand Up @@ -133,14 +133,13 @@ where
type Error;

/// Extract this Rust type from a JavaScript value
fn try_from_js<C>(cx: &mut C, v: Handle<'cx, JsValue>) -> NeonResult<Result<Self, Self::Error>>
where
C: Context<'cx>;
fn try_from_js(
cx: &mut Cx<'cx>,
v: Handle<'cx, JsValue>,
) -> NeonResult<Result<Self, Self::Error>>;

/// Same as [`TryFromJs`], but all errors are converted to JavaScript exceptions
fn from_js<C>(cx: &mut C, v: Handle<'cx, JsValue>) -> NeonResult<Self>
where
C: Context<'cx>;
fn from_js(cx: &mut Cx<'cx>, v: Handle<'cx, JsValue>) -> NeonResult<Self>;
}

/// Convert Rust data into a JavaScript value
Expand All @@ -152,9 +151,7 @@ where
type Value: Value;

/// Convert `self` into a JavaScript value
fn try_into_js<C>(self, cx: &mut C) -> JsResult<'cx, Self::Value>
where
C: Context<'cx>;
fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value>;
}

#[cfg_attr(docsrs, doc(cfg(feature = "napi-5")))]
Expand Down
Loading