neon/handle/mod.rs
1//! References to garbage-collected JavaScript values.
2//!
3//! A _handle_ is a safe reference to a JavaScript value that is owned and managed
4//! by the JavaScript engine's memory management system (the garbage collector).
5//!
6//! Neon APIs that accept and return JavaScript values never use raw pointer types
7//! ([`*T`](pointer)) or reference types ([`&T`](reference)). Instead they use the
8//! special Neon type [`Handle`], which encapsulates a JavaScript
9//! [`Value`] and ensures that Rust only maintains access to
10//! the value while it is guaranteed to be valid.
11//!
12//! ## Working with Handles
13//!
14//! The `Handle<T>` type automatically dereferences to `T` (via the standard
15//! [`Deref`] trait), so you can call `T`'s methods on a value of
16//! type `Handle<T>`. For example, we can call
17//! [`JsNumber::value()`](crate::types::JsNumber::value) on a `Handle<JsNumber>`:
18//!
19//! ```
20//! # use neon::prelude::*;
21//! # fn run(mut cx: FunctionContext) -> JsResult<JsUndefined> {
22//! let n: Handle<JsNumber> = cx.argument(0)?;
23//! let v = n.value(&mut cx); // JsNumber::value()
24//! # Ok(cx.undefined())
25//! # }
26//! ```
27//!
28//! ## Example
29//!
30//! This Neon function takes an object as its argument, extracts an object property,
31//! `homeAddress`, and then extracts a string property, `zipCode` from that second
32//! object. Each JavaScript value in the calculation is stored locally in a `Handle`.
33//!
34//! ```
35//! # use neon::prelude::*;
36//! # use neon::export;
37//! #[export]
38//! fn customer_zip_code<'cx>(cx: &mut FunctionContext<'cx>, customer: Handle<'cx, JsObject>) -> JsResult<'cx, JsString> {
39//! let home_address: Handle<JsObject> = customer.prop(cx, "homeAddress").get()?;
40//! let zip_code: Handle<JsString> = home_address.prop(cx, "zipCode").get()?;
41//! Ok(zip_code)
42//! }
43//! ```
44
45pub(crate) mod internal;
46
47pub(crate) mod root;
48
49use std::{
50 error::Error,
51 fmt::{self, Debug, Display},
52 marker::PhantomData,
53 mem,
54 ops::{Deref, DerefMut},
55};
56
57pub use self::root::Root;
58
59use crate::{
60 context::Context,
61 handle::internal::{SuperType, TransparentNoCopyWrapper},
62 result::{JsResult, ResultExt},
63 sys,
64 types::Value,
65};
66
67/// A handle to a JavaScript value that is owned by the JavaScript engine.
68#[derive(Debug)]
69#[repr(transparent)]
70pub struct Handle<'a, V: Value + 'a> {
71 // Contains the actual `Copy` JavaScript value data. It will be wrapped in
72 // in a `!Copy` type when dereferencing. Only `V` should be visible to the user.
73 value: <V as TransparentNoCopyWrapper>::Inner,
74 phantom: PhantomData<&'a V>,
75}
76
77impl<'a, V: Value> Clone for Handle<'a, V> {
78 fn clone(&self) -> Self {
79 *self
80 }
81}
82
83impl<'a, V: Value> Copy for Handle<'a, V> {}
84
85impl<'a, V: Value + 'a> Handle<'a, V> {
86 pub(crate) fn new_internal(value: V) -> Handle<'a, V> {
87 Handle {
88 value: value.into_inner(),
89 phantom: PhantomData,
90 }
91 }
92}
93
94/// An error representing a failed downcast.
95#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
96pub struct DowncastError<F: Value, T: Value> {
97 phantom_from: PhantomData<F>,
98 phantom_to: PhantomData<T>,
99}
100
101impl<F: Value, T: Value> Debug for DowncastError<F, T> {
102 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
103 write!(f, "DowncastError")
104 }
105}
106
107impl<F: Value, T: Value> DowncastError<F, T> {
108 fn new() -> Self {
109 DowncastError {
110 phantom_from: PhantomData,
111 phantom_to: PhantomData,
112 }
113 }
114}
115
116impl<F: Value, T: Value> Display for DowncastError<F, T> {
117 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
118 write!(f, "failed to downcast {} to {}", F::name(), T::name())
119 }
120}
121
122impl<F: Value, T: Value> Error for DowncastError<F, T> {}
123
124/// The result of a call to [`Handle::downcast()`](Handle::downcast).
125pub type DowncastResult<'a, F, T> = Result<Handle<'a, T>, DowncastError<F, T>>;
126
127impl<'a, F: Value, T: Value> ResultExt<Handle<'a, T>> for DowncastResult<'a, F, T> {
128 fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, T> {
129 match self {
130 Ok(v) => Ok(v),
131 Err(e) => cx.throw_type_error(e.to_string()),
132 }
133 }
134}
135
136impl<'a, T: Value> Handle<'a, T> {
137 /// Safely upcast a handle to a supertype.
138 ///
139 /// This method does not require an execution context because it only copies a handle.
140 pub fn upcast<U: Value + SuperType<T>>(&self) -> Handle<'a, U> {
141 Handle::new_internal(SuperType::upcast_internal(self.deref()))
142 }
143
144 /// Tests whether this value is an instance of the given type.
145 ///
146 /// # Example:
147 ///
148 /// ```no_run
149 /// # use neon::prelude::*;
150 /// # fn my_neon_function(mut cx: FunctionContext) -> JsResult<JsUndefined> {
151 /// let v: Handle<JsValue> = cx.number(17).upcast();
152 /// v.is_a::<JsString, _>(&mut cx); // false
153 /// v.is_a::<JsNumber, _>(&mut cx); // true
154 /// v.is_a::<JsValue, _>(&mut cx); // true
155 /// # Ok(cx.undefined())
156 /// # }
157 /// ```
158 pub fn is_a<'b, U: Value, C: Context<'b>>(&self, cx: &mut C) -> bool {
159 U::is_typeof(cx.cx_mut(), self.deref())
160 }
161
162 /// Attempts to downcast a handle to another type, which may fail. A failure
163 /// to downcast **does not** throw a JavaScript exception, so it's OK to
164 /// continue interacting with the JS engine if this method produces an `Err`
165 /// result.
166 pub fn downcast<'b, U: Value, C: Context<'b>>(&self, cx: &mut C) -> DowncastResult<'a, T, U> {
167 match U::downcast(cx.cx_mut(), self.deref()) {
168 Some(v) => Ok(Handle::new_internal(v)),
169 None => Err(DowncastError::new()),
170 }
171 }
172
173 /// Attempts to downcast a handle to another type, raising a JavaScript `TypeError`
174 /// exception on failure. This method is a convenient shorthand, equivalent to
175 /// `self.downcast::<U>().or_throw::<C>(cx)`.
176 pub fn downcast_or_throw<'b, U: Value, C: Context<'b>>(&self, cx: &mut C) -> JsResult<'a, U> {
177 self.downcast(cx).or_throw(cx)
178 }
179
180 pub fn strict_equals<'b, U: Value, C: Context<'b>>(
181 &self,
182 cx: &mut C,
183 other: Handle<'b, U>,
184 ) -> bool {
185 unsafe { sys::mem::strict_equals(cx.env().to_raw(), self.to_local(), other.to_local()) }
186 }
187}
188
189impl<'a, V: Value> Deref for Handle<'a, V> {
190 type Target = V;
191 fn deref(&self) -> &V {
192 unsafe { mem::transmute(&self.value) }
193 }
194}
195
196impl<'a, V: Value> DerefMut for Handle<'a, V> {
197 fn deref_mut(&mut self) -> &mut V {
198 unsafe { mem::transmute(&mut self.value) }
199 }
200}