From fb64b869c8df08d0ba612aa27132027fa835143d Mon Sep 17 00:00:00 2001 From: "K.J. Valencik" Date: Fri, 10 Jan 2025 17:29:16 -0500 Subject: [PATCH] feat(neon): Allow getting a `&'cx T` from a `Handle<'cx, JsBox>` Resolves https://github.com/neon-bindings/neon/issues/678 --- crates/neon/src/types_impl/boxed.rs | 31 +++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/crates/neon/src/types_impl/boxed.rs b/crates/neon/src/types_impl/boxed.rs index 02d3557f6..d1910a5a4 100644 --- a/crates/neon/src/types_impl/boxed.rs +++ b/crates/neon/src/types_impl/boxed.rs @@ -259,12 +259,39 @@ impl JsBox { } } +impl JsBox { + /// Gets a reference to the inner value of a [`JsBox`]. This method is similar to + /// [dereferencing](JsBox::deref) a `JsBox` (e.g., `&*boxed`), but the lifetime + /// is _safely_ extended to `'cx`. + /// + /// See also [`Handle::as_inner`]. + // N.B.: This would be cleaner with https://github.com/rust-lang/rust/issues/44874 + pub fn deref<'cx>(v: &Handle<'cx, Self>) -> &'cx T { + v.as_inner() + } +} + +impl<'cx, T: 'static> Handle<'cx, JsBox> { + /// Gets a reference to the inner value of a [`JsBox`]. This method is similar to + /// [dereferencing](JsBox::deref) a `JsBox` (e.g., `&*boxed`), but the lifetime + /// is _safely_ extended to `'cx`. + /// + /// See also [`JsBox::deref`]. + pub fn as_inner(&self) -> &'cx T { + // # Safety + // JS values associated with an in-scope `Context` *cannot* garbage collected. This + // value is guaranteed to live at least as long as `'cx`. + unsafe { &*self.0.raw_data } + } +} + impl Deref for JsBox { type Target = T; fn deref(&self) -> &Self::Target { - // Safety: This depends on a `Handle<'a, JsBox>` wrapper to provide - // a proper lifetime. + // # Safety + // `T` will live at least as long as `JsBox` because it may not be garbage + // collected while in scope and only immutable references can be obtained. unsafe { &*self.0.raw_data } } }