Skip to content

Commit

Permalink
Merge pull request #1062 from neon-bindings/kv/concrete-try-js
Browse files Browse the repository at this point in the history
change(neon): Change TryIntoJs and TryFromJs accept Cx instead of being generic over Context
  • Loading branch information
kjvalencik authored Sep 3, 2024
2 parents 471a70e + 88581a0 commit 63551b1
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 206 deletions.
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>;
}

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

0 comments on commit 63551b1

Please sign in to comment.