Skip to main content

neon/context/
mod.rs

1//! Provides runtime access to the JavaScript engine.
2//!
3//! An _execution context_ represents the current state of a thread of execution in the
4//! JavaScript engine. Internally, it tracks things like the set of pending function calls,
5//! whether the engine is currently throwing an exception or not, and whether the engine is
6//! in the process of shutting down. The context uses this internal state to manage what
7//! operations are safely available and when.
8//!
9//! The [`Context`] trait provides an abstract interface to the JavaScript
10//! execution context. All interaction with the JavaScript engine in Neon code is mediated
11//! through instances of this trait.
12//!
13//! One particularly useful context type is [`FunctionContext`], which is passed
14//! to all Neon functions as their initial execution context.
15//!
16//! ```
17//! # use neon::prelude::*;
18//! fn hello(mut cx: FunctionContext) -> JsResult<JsString> {
19//!     Ok(cx.string("hello Neon"))
20//! }
21//! ```
22//!
23//! Another important context type is [`ModuleContext`], which is provided
24//! to a Neon module's [`main`](crate::main) function to enable sharing Neon functions back
25//! with JavaScript:
26//!
27//! ```
28//! # use neon::prelude::*;
29//! # fn hello(_: FunctionContext) -> JsResult<JsValue> { todo!() }
30//! #[neon::main]
31//! fn lib(mut cx: ModuleContext) -> NeonResult<()> {
32//!     cx.export_function("hello", hello)?;
33//!     Ok(())
34//! }
35//! ```
36//!
37//! ## Writing Generic Helpers
38//!
39//! Depending on the entrypoint, a user may have a [`FunctionContext`], [`ModuleContext`], or
40//! generic [`Cx`]. While it is possible to write a helper that is generic over the [`Context`]
41//! trait, it is often simpler to accept a [`Cx`] argument. Due to deref coercion, other contexts
42//! may be passed into a function that accepts a reference to [`Cx`].
43//!
44//! ```
45//! # use neon::prelude::*;
46//! fn log(cx: &mut Cx, msg: &str) -> NeonResult<()> {
47//!     cx.global::<JsObject>("console")?
48//!         .method(cx, "log")?
49//!         .arg(msg)?
50//!         .exec()?;
51//!     Ok(())
52//! }
53//!
54//! fn print(mut cx: FunctionContext) -> JsResult<JsUndefined> {
55//!     let msg = cx.argument::<JsString>(0)?.value(&mut cx);
56//!     log(&mut cx, &msg)?;
57//!     Ok(cx.undefined())
58//! }
59//! ```
60//!
61//! ## Memory Management
62//!
63//! Because contexts represent the engine at a point in time, they are associated with a
64//! [_lifetime_][lifetime], which limits how long Rust code is allowed to access them. This
65//! is also used to determine the lifetime of [`Handle`]s, which
66//! provide safe references to JavaScript memory managed by the engine's garbage collector.
67//!
68//! For example, we can
69//! write a simple string scanner that counts whitespace in a JavaScript string and
70//! returns a [`JsNumber`]:
71//!
72//! ```
73//! # use neon::prelude::*;
74//! fn count_whitespace(mut cx: FunctionContext) -> JsResult<JsNumber> {
75//!     let s: Handle<JsString> = cx.argument(0)?;
76//!     let contents = s.value(&mut cx);
77//!     let count = contents
78//!         .chars()                       // iterate over the characters
79//!         .filter(|c| c.is_whitespace()) // select the whitespace chars
80//!         .count();                      // count the resulting chars
81//!     Ok(cx.number(count as f64))
82//! }
83//! ```
84//!
85//! In this example, `s` is assigned a handle to a string, which ensures that the string
86//! is _kept alive_ (i.e., prevented from having its storage reclaimed by the JavaScript
87//! engine's garbage collector) for the duration of the `count_whitespace` function. This
88//! is how Neon takes advantage of Rust's type system to allow your Rust code to safely
89//! interact with JavaScript values.
90//!
91//! ### Temporary Scopes
92//!
93//! Sometimes it can be useful to limit the scope of a handle's lifetime, to allow the
94//! engine to reclaim memory sooner. This can be important when, for example, an expensive inner loop generates
95//! temporary JavaScript values that are only needed inside the loop. In these cases,
96//! the [`execute_scoped`](Context::execute_scoped) and [`compute_scoped`](Context::compute_scoped)
97//! methods allow you to create temporary contexts in order to allocate temporary
98//! handles.
99//!
100//! For example, to extract the elements of a JavaScript [iterator][iterator] from Rust,
101//! a Neon function has to work with several temporary handles on each pass through
102//! the loop:
103//!
104//! ```
105//! # use neon::prelude::*;
106//! # fn iterate(mut cx: FunctionContext) -> JsResult<JsUndefined> {
107//!     let iterator = cx.argument::<JsObject>(0)?;         // iterator object
108//!     let next: Handle<JsFunction> =                      // iterator's `next` method
109//!         iterator.prop(&mut cx, "next").get()?;
110//!     let mut numbers: Vec<f64> = vec![];                 // results vector
111//!     let mut done = false;                               // loop controller
112//!
113//!     while !done {
114//!         done = cx.execute_scoped(|mut cx| {                   // temporary scope
115//!             let obj: Handle<JsObject> = next                  // temporary object
116//!                 .bind(&mut cx)
117//!                 .this(iterator)?
118//!                 .call()?;
119//!             numbers.push(obj.prop(&mut cx, "value").get()?);  // temporary number
120//!             obj.prop(&mut cx, "done").get()                   // temporary boolean
121//!         })?;
122//!     }
123//! #   Ok(cx.undefined())
124//! # }
125//! ```
126//!
127//! The temporary scope ensures that the temporary values are only kept alive
128//! during a single pass through the loop, since the temporary context is
129//! discarded (and all of its handles released) on the inside of the loop.
130//!
131//! ## Throwing Exceptions
132//!
133//! When a Neon API causes a JavaScript exception to be thrown, it returns an
134//! [`Err`] result, indicating that the thread associated
135//! with the context is now throwing. This allows Rust code to perform any
136//! cleanup before returning, but with an important restriction:
137//!
138//! > **While a JavaScript thread is throwing, its context cannot be used.**
139//!
140//! Unless otherwise documented, any Neon API that uses a context (as `self` or as
141//! a parameter) immediately panics if called while the context's thread is throwing.
142//!
143//! Typically, Neon code can manage JavaScript exceptions correctly and conveniently
144//! by using Rust's [question mark (`?`)][question-mark] operator. This ensures that
145//! Rust code "short-circuits" when an exception is thrown and returns back to
146//! JavaScript without calling any throwing APIs.
147//!
148//! Alternatively, to invoke a Neon API and catch any JavaScript exceptions, use the
149//! [`Context::try_catch`] method, which catches any thrown
150//! exception and restores the context to non-throwing state.
151//!
152//! ## See also
153//!
154//! 1. Ecma International. [Execution contexts](https://tc39.es/ecma262/#sec-execution-contexts), _ECMAScript Language Specification_.
155//! 2. Madhavan Nagarajan. [What is the Execution Context and Stack in JavaScript?](https://medium.com/@itIsMadhavan/what-is-the-execution-context-stack-in-javascript-e169812e851a)
156//! 3. Rupesh Mishra. [Execution context, Scope chain and JavaScript internals](https://medium.com/@happymishra66/execution-context-in-javascript-319dd72e8e2c).
157//!
158//! [lifetime]: https://doc.rust-lang.org/book/ch10-00-generics.html
159//! [iterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators
160//! [question-mark]: https://doc.rust-lang.org/edition-guide/rust-2018/error-handling-and-panics/the-question-mark-operator-for-easier-error-handling.html
161
162pub(crate) mod internal;
163
164use std::{
165    convert::Into,
166    marker::PhantomData,
167    ops::{Deref, DerefMut},
168    panic::UnwindSafe,
169};
170
171pub use crate::types::buffer::lock::Lock;
172
173use crate::{
174    event::TaskBuilder,
175    handle::Handle,
176    object::Object,
177    result::{JsResult, NeonResult, Throw},
178    sys::{
179        self, raw,
180        scope::{EscapableHandleScope, HandleScope},
181    },
182    types::{
183        boxed::{Finalize, JsBox},
184        error::JsError,
185        extract::{FromArgs, TryFromJs},
186        private::ValueInternal,
187        Deferred, JsArray, JsArrayBuffer, JsBoolean, JsBuffer, JsFunction, JsNull, JsNumber,
188        JsObject, JsPromise, JsString, JsUndefined, JsValue, StringResult, Value,
189    },
190};
191
192use self::internal::{ContextInternal, Env};
193
194#[cfg(feature = "napi-4")]
195use crate::event::Channel;
196
197#[cfg(feature = "napi-5")]
198use crate::types::date::{DateError, JsDate};
199
200#[cfg(feature = "napi-6")]
201use crate::lifecycle::InstanceData;
202
203#[doc(hidden)]
204/// An execution context of a task completion callback.
205pub type TaskContext<'cx> = Cx<'cx>;
206
207/// An execution context of a scope created by [`Context::execute_scoped()`](Context::execute_scoped).
208pub type ExecuteContext<'outer, 'inner> = ScopedCx<'outer, 'inner>;
209
210/// An execution context of a scope created by [`Context::compute_scoped()`](Context::compute_scoped).
211pub type ComputeContext<'outer, 'inner> = ScopedCx<'outer, 'inner>;
212
213#[doc(hidden)]
214/// A view of the JS engine in the context of a finalize method on garbage collection
215pub type FinalizeContext<'cx> = Cx<'cx>;
216
217/// An execution context constructed from a raw [`Env`](crate::sys::bindings::Env).
218#[cfg(feature = "sys")]
219#[cfg_attr(docsrs, doc(cfg(feature = "sys")))]
220#[doc(hidden)]
221pub type SysContext<'cx> = Cx<'cx>;
222
223/// Context representing access to the JavaScript runtime
224pub struct Cx<'cx> {
225    env: Env,
226    _phantom_inner: PhantomData<&'cx ()>,
227}
228
229impl<'cx> Cx<'cx> {
230    /// Creates a context from a raw `Env`.
231    ///
232    /// # Safety
233    ///
234    /// Once a [`Cx`] has been created, it is unsafe to use
235    /// the `Env`. The handle scope for the `Env` must be valid for
236    /// the lifetime `'cx`.
237    #[cfg(feature = "sys")]
238    #[cfg_attr(docsrs, doc(cfg(feature = "sys")))]
239    pub unsafe fn from_raw(env: sys::Env) -> Self {
240        Self {
241            env: env.into(),
242            _phantom_inner: PhantomData,
243        }
244    }
245
246    fn new(env: Env) -> Self {
247        Self {
248            env,
249            _phantom_inner: PhantomData,
250        }
251    }
252
253    pub(crate) fn with_context<T, F: for<'b> FnOnce(Cx<'b>) -> T>(env: Env, f: F) -> T {
254        f(Self {
255            env,
256            _phantom_inner: PhantomData,
257        })
258    }
259}
260
261impl<'cx> ContextInternal<'cx> for Cx<'cx> {
262    fn cx(&self) -> &Cx<'cx> {
263        self
264    }
265
266    fn cx_mut(&mut self) -> &mut Cx<'cx> {
267        self
268    }
269}
270
271impl<'cx> Context<'cx> for Cx<'cx> {}
272
273impl<'cx> From<FunctionContext<'cx>> for Cx<'cx> {
274    fn from(cx: FunctionContext<'cx>) -> Self {
275        cx.cx
276    }
277}
278
279impl<'cx> From<ModuleContext<'cx>> for Cx<'cx> {
280    fn from(cx: ModuleContext<'cx>) -> Self {
281        cx.cx
282    }
283}
284
285/// A temporary execution context created by [`Context::execute_scoped()`] or
286/// [`Context::compute_scoped()`].
287///
288/// `ScopedCx` carries two lifetimes:
289///
290/// * `'outer` &mdash; the lifetime of the surrounding [`Context`] that created the
291///   temporary scope. Handles brought in from the outer scope (e.g. captured by
292///   the closure) carry this lifetime and remain valid for the entire enclosing
293///   computation.
294/// * `'inner` &mdash; the lifetime of this temporary scope. New handles allocated
295///   through this context carry `'inner` and are released as soon as the scope
296///   ends. Because the closure passed to `execute_scoped`/`compute_scoped` is
297///   required to be valid [for every choice][hrtb] of `'inner`, the type system
298///   prevents an inner-scope handle from escaping into outer state through a
299///   captured `&mut`.
300///
301/// The implicit bound `'outer: 'inner` carried by `ScopedCx` allows existing
302/// outer-scope handles to be used freely inside the temporary scope via the
303/// usual covariance of [`Handle`].
304///
305/// [hrtb]: https://doc.rust-lang.org/nomicon/hrtb.html
306pub struct ScopedCx<'outer, 'inner> {
307    cx: Cx<'inner>,
308    // Encodes the implicit bound `'outer: 'inner` without imposing it on the
309    // (universally quantified) HRTB used by the trait methods that introduce
310    // this type.
311    _outer: PhantomData<&'inner &'outer ()>,
312}
313
314impl<'outer, 'inner> ScopedCx<'outer, 'inner> {
315    /// Constructs a `ScopedCx` for an already-open inner handle scope.
316    ///
317    /// # Safety
318    ///
319    /// All of the following must hold when this constructor is called:
320    ///
321    /// * `env` must point to a Node-API environment that is live on the
322    ///   current thread.
323    /// * A Node-API [`HandleScope`] (or [`EscapableHandleScope`]) must be
324    ///   currently open for `env` and must outlive every use of the returned
325    ///   [`ScopedCx`]. In practice this means the constructor must be called
326    ///   immediately after opening such a scope, and the scope must be kept
327    ///   alive across all subsequent uses of the returned value.
328    /// * The caller-chosen lifetime `'inner` must not be longer than the
329    ///   actually-open inner scope; the [`ScopedCx`] (and every [`Handle`]
330    ///   derived from it) must be dropped before the inner scope is closed.
331    /// * The caller-chosen lifetime `'outer` must correspond to an
332    ///   actually-enclosing context's scope, and must satisfy
333    ///   `'outer: 'inner` (this is enforced structurally by the type's
334    ///   phantom data).
335    ///
336    /// Violating any of these invariants permits handles whose backing N-API
337    /// values have been released, which is undefined behavior.
338    unsafe fn new(env: Env) -> Self {
339        Self {
340            cx: Cx::new(env),
341            _outer: PhantomData,
342        }
343    }
344}
345
346impl<'outer, 'inner> Deref for ScopedCx<'outer, 'inner> {
347    type Target = Cx<'inner>;
348
349    fn deref(&self) -> &Self::Target {
350        &self.cx
351    }
352}
353
354impl<'outer, 'inner> DerefMut for ScopedCx<'outer, 'inner> {
355    fn deref_mut(&mut self) -> &mut Self::Target {
356        &mut self.cx
357    }
358}
359
360impl<'outer, 'inner> ContextInternal<'inner> for ScopedCx<'outer, 'inner> {
361    fn cx(&self) -> &Cx<'inner> {
362        &self.cx
363    }
364
365    fn cx_mut(&mut self) -> &mut Cx<'inner> {
366        &mut self.cx
367    }
368}
369
370impl<'outer, 'inner> Context<'inner> for ScopedCx<'outer, 'inner> {}
371
372#[repr(C)]
373pub(crate) struct CallbackInfo<'cx> {
374    info: raw::FunctionCallbackInfo,
375    _lifetime: PhantomData<&'cx raw::FunctionCallbackInfo>,
376}
377
378impl CallbackInfo<'_> {
379    pub unsafe fn new(info: raw::FunctionCallbackInfo) -> Self {
380        Self {
381            info,
382            _lifetime: PhantomData,
383        }
384    }
385
386    fn kind<'b, C: Context<'b>>(&self, cx: &C) -> CallKind {
387        if unsafe { sys::call::is_construct(cx.env().to_raw(), self.info) } {
388            CallKind::Construct
389        } else {
390            CallKind::Call
391        }
392    }
393
394    pub fn len<'b, C: Context<'b>>(&self, cx: &C) -> usize {
395        unsafe { sys::call::len(cx.env().to_raw(), self.info) }
396    }
397
398    pub fn argv<'b, C: Context<'b>>(&self, cx: &mut C) -> sys::call::Arguments {
399        unsafe { sys::call::argv(cx.env().to_raw(), self.info) }
400    }
401
402    pub fn this<'b, C: Context<'b>>(&self, cx: &mut C) -> raw::Local {
403        let env = cx.env();
404        unsafe {
405            let mut local: raw::Local = std::mem::zeroed();
406            sys::call::this(env.to_raw(), self.info, &mut local);
407            local
408        }
409    }
410
411    pub(crate) fn argv_exact<'b, C: Context<'b>, const N: usize>(
412        &self,
413        cx: &mut C,
414    ) -> [Handle<'b, JsValue>; N] {
415        use std::ptr;
416
417        let mut argv = [JsValue::new_internal(ptr::null_mut()); N];
418        let mut argc = argv.len();
419
420        // # Safety
421        // * Node-API fills empty slots with `undefined`
422        // * `Handle` and `JsValue` are transparent wrappers around a raw pointer
423        unsafe {
424            sys::get_cb_info(
425                cx.env().to_raw(),
426                self.info,
427                &mut argc,
428                argv.as_mut_ptr().cast(),
429                ptr::null_mut(),
430                ptr::null_mut(),
431            )
432            .unwrap();
433        }
434
435        // Empty values will be filled with `undefined`
436        argv
437    }
438}
439
440/// Indicates whether a function was called with `new`.
441#[derive(Clone, Copy, Debug)]
442pub enum CallKind {
443    Construct,
444    Call,
445}
446
447/// An _execution context_, which represents the current state of a thread of execution in the JavaScript engine.
448///
449/// All interaction with the JavaScript engine in Neon code is mediated through instances of this trait.
450///
451/// A context has a lifetime `'a`, which ensures the safety of handles managed by the JS garbage collector. All handles created during the lifetime of a context are kept alive for that duration and cannot outlive the context.
452pub trait Context<'a>: ContextInternal<'a> {
453    /// Lock the JavaScript engine, returning an RAII guard that keeps the lock active as long as the guard is alive.
454    ///
455    /// If this is not the currently active context (for example, if it was used to spawn a scoped context with `execute_scoped` or `compute_scoped`), this method will panic.
456    fn lock<'b>(&'b mut self) -> Lock<'b, Self>
457    where
458        'a: 'b,
459    {
460        Lock::new(self)
461    }
462
463    /// Executes a computation in a new memory management scope.
464    ///
465    /// Handles created in the new scope are kept alive only for the duration of the computation and cannot escape.
466    ///
467    /// This method can be useful for limiting the life of temporary values created during long-running computations, to prevent leaks.
468    ///
469    /// The closure receives a [`ScopedCx`] whose inner lifetime `'b` is bound
470    /// by a higher-ranked trait bound. This ensures that any handle allocated
471    /// inside the scope is tied to the temporary [`HandleScope`] and cannot
472    /// escape into the surrounding context.
473    fn execute_scoped<T, F>(&mut self, f: F) -> T
474    where
475        F: for<'b> FnOnce(ScopedCx<'a, 'b>) -> T,
476    {
477        let env = self.env();
478        let scope = unsafe { HandleScope::new(env.to_raw()) };
479        // SAFETY: `scope` is an `HandleScope` we just opened for `env` and
480        // hold (via the `drop(scope)` below) across the call to `f`. The
481        // inferred `'b` is bounded by the borrow of `scope` that the
482        // closure transitively performs through the `ScopedCx`, so it
483        // cannot outlive the open scope. `'a` is the enclosing context's
484        // lifetime, which (by `Context<'a>`) outlives `'b`.
485        let result = f(unsafe { ScopedCx::new(env) });
486
487        drop(scope);
488
489        result
490    }
491
492    /// Executes a computation in a new memory management scope and computes a single result value that outlives the computation.
493    ///
494    /// Handles created in the new scope are kept alive only for the duration of the computation and cannot escape, with the exception of the result value, which is rooted in the outer context.
495    ///
496    /// This method can be useful for limiting the life of temporary values created during long-running computations, to prevent leaks.
497    ///
498    /// The closure receives a [`ScopedCx`] whose inner lifetime `'b` is bound
499    /// by a higher-ranked trait bound. Only the returned [`Handle`] escapes
500    /// the temporary scope; it is rooted in the outer context via the
501    /// underlying [`EscapableHandleScope`]. Any other inner-scope handle is
502    /// prevented from leaking into the surrounding context by the type system.
503    fn compute_scoped<V, F>(&mut self, f: F) -> JsResult<'a, V>
504    where
505        V: Value,
506        F: for<'b> FnOnce(ScopedCx<'a, 'b>) -> JsResult<'b, V>,
507    {
508        let env = self.env();
509        let scope = unsafe { EscapableHandleScope::new(env.to_raw()) };
510        // SAFETY: `scope` is an `EscapableHandleScope` we just opened for
511        // `env` and hold across the call to `f` and the subsequent
512        // `scope.escape(...)`. The inferred `'b` is bounded by the borrow
513        // of `scope` that the closure transitively performs through the
514        // `ScopedCx`, so it cannot outlive the open scope. `'a` is the
515        // enclosing context's lifetime, which (by `Context<'a>`) outlives
516        // `'b`.
517        let cx = unsafe { ScopedCx::new(env) };
518
519        let escapee = unsafe { scope.escape(f(cx)?.to_local()) };
520
521        Ok(Handle::new_internal(unsafe {
522            V::from_local(self.env(), escapee)
523        }))
524    }
525
526    fn try_catch<T, F>(&mut self, f: F) -> Result<T, Handle<'a, JsValue>>
527    where
528        F: FnOnce(&mut Self) -> NeonResult<T>,
529    {
530        unsafe {
531            self.env()
532                .try_catch(move || f(self))
533                .map_err(JsValue::new_internal)
534        }
535    }
536
537    /// Convenience method for creating a `JsBoolean` value.
538    fn boolean(&mut self, b: bool) -> Handle<'a, JsBoolean> {
539        JsBoolean::new(self, b)
540    }
541
542    /// Convenience method for creating a `JsNumber` value.
543    fn number<T: Into<f64>>(&mut self, x: T) -> Handle<'a, JsNumber> {
544        JsNumber::new(self, x.into())
545    }
546
547    /// Convenience method for creating a `JsString` value.
548    ///
549    /// If the string exceeds the limits of the JS engine, this method panics.
550    fn string<S: AsRef<str>>(&mut self, s: S) -> Handle<'a, JsString> {
551        JsString::new(self, s)
552    }
553
554    /// Convenience method for creating a `JsString` value.
555    ///
556    /// If the string exceeds the limits of the JS engine, this method returns an `Err` value.
557    fn try_string<S: AsRef<str>>(&mut self, s: S) -> StringResult<'a> {
558        JsString::try_new(self, s)
559    }
560
561    /// Convenience method for creating a `JsNull` value.
562    fn null(&mut self) -> Handle<'a, JsNull> {
563        JsNull::new(self)
564    }
565
566    /// Convenience method for creating a `JsUndefined` value.
567    fn undefined(&mut self) -> Handle<'a, JsUndefined> {
568        JsUndefined::new(self)
569    }
570
571    /// Convenience method for creating an empty `JsObject` value.
572    fn empty_object(&mut self) -> Handle<'a, JsObject> {
573        JsObject::new(self)
574    }
575
576    /// Convenience method for creating an empty `JsArray` value.
577    fn empty_array(&mut self) -> Handle<'a, JsArray> {
578        JsArray::new(self, 0)
579    }
580
581    /// Convenience method for creating an empty `JsArrayBuffer` value.
582    fn array_buffer(&mut self, size: usize) -> JsResult<'a, JsArrayBuffer> {
583        JsArrayBuffer::new(self, size)
584    }
585
586    /// Convenience method for creating an empty `JsBuffer` value.
587    fn buffer(&mut self, size: usize) -> JsResult<'a, JsBuffer> {
588        JsBuffer::new(self, size)
589    }
590    /// Convenience method for creating a `JsDate` value.
591    #[cfg(feature = "napi-5")]
592    #[cfg_attr(docsrs, doc(cfg(feature = "napi-5")))]
593    fn date(&mut self, value: impl Into<f64>) -> Result<Handle<'a, JsDate>, DateError> {
594        JsDate::new(self, value)
595    }
596
597    /// Convenience method for looking up a global property by name.
598    ///
599    /// Equivalent to:
600    ///
601    /// ```
602    /// # use neon::prelude::*;
603    /// # fn get_array_global<'cx>(cx: &mut Cx<'cx>) -> JsResult<'cx, JsFunction> {
604    /// #     let name = "Array";
605    /// #     let v: Handle<JsFunction> =
606    /// {
607    ///     let global = cx.global_object();
608    ///     global.prop(cx, name).get()
609    /// }
610    /// #     ?;
611    /// #     Ok(v)
612    /// # }
613    /// ```
614    fn global<T: Value>(&mut self, name: &str) -> JsResult<'a, T> {
615        let global = self.global_object();
616        global.get(self, name)
617    }
618
619    /// Produces a handle to the JavaScript global object.
620    fn global_object(&mut self) -> Handle<'a, JsObject> {
621        JsObject::build(|out| unsafe {
622            sys::scope::get_global(self.env().to_raw(), out);
623        })
624    }
625
626    /// Throws a JS value.
627    fn throw<T: Value, U>(&mut self, v: Handle<T>) -> NeonResult<U> {
628        unsafe {
629            sys::error::throw(self.env().to_raw(), v.to_local());
630            Err(Throw::new())
631        }
632    }
633
634    /// Creates a direct instance of the [`Error`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error) class.
635    fn error<S: AsRef<str>>(&mut self, msg: S) -> JsResult<'a, JsError> {
636        JsError::error(self, msg)
637    }
638
639    /// Creates an instance of the [`TypeError`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/TypeError) class.
640    fn type_error<S: AsRef<str>>(&mut self, msg: S) -> JsResult<'a, JsError> {
641        JsError::type_error(self, msg)
642    }
643
644    /// Creates an instance of the [`RangeError`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RangeError) class.
645    fn range_error<S: AsRef<str>>(&mut self, msg: S) -> JsResult<'a, JsError> {
646        JsError::range_error(self, msg)
647    }
648
649    /// Throws a direct instance of the [`Error`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error) class.
650    fn throw_error<S: AsRef<str>, T>(&mut self, msg: S) -> NeonResult<T> {
651        let err = JsError::error(self, msg)?;
652        self.throw(err)
653    }
654
655    /// Throws an instance of the [`TypeError`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/TypeError) class.
656    fn throw_type_error<S: AsRef<str>, T>(&mut self, msg: S) -> NeonResult<T> {
657        let err = JsError::type_error(self, msg)?;
658        self.throw(err)
659    }
660
661    /// Throws an instance of the [`RangeError`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RangeError) class.
662    fn throw_range_error<S: AsRef<str>, T>(&mut self, msg: S) -> NeonResult<T> {
663        let err = JsError::range_error(self, msg)?;
664        self.throw(err)
665    }
666
667    /// Convenience method for wrapping a value in a `JsBox`.
668    ///
669    /// # Example:
670    ///
671    /// ```rust
672    /// # use neon::prelude::*;
673    /// struct Point(usize, usize);
674    ///
675    /// impl Finalize for Point {}
676    ///
677    /// fn my_neon_function(mut cx: FunctionContext) -> JsResult<JsBox<Point>> {
678    ///     let point = cx.boxed(Point(0, 1));
679    ///
680    ///     Ok(point)
681    /// }
682    /// ```
683    fn boxed<U: Finalize + 'static>(&mut self, v: U) -> Handle<'a, JsBox<U>> {
684        JsBox::new(self, v)
685    }
686
687    #[cfg(feature = "napi-4")]
688    #[deprecated(since = "0.9.0", note = "Please use the channel() method instead")]
689    #[doc(hidden)]
690    fn queue(&mut self) -> Channel {
691        self.channel()
692    }
693
694    #[cfg(feature = "napi-4")]
695    #[cfg_attr(docsrs, doc(cfg(feature = "napi-4")))]
696    /// Returns an unbounded channel for scheduling events to be executed on the JavaScript thread.
697    ///
698    /// When using N-API >= 6,the channel returned by this method is backed by a shared queue.
699    /// To create a channel backed by a _new_ queue see [`Channel`].
700    fn channel(&mut self) -> Channel {
701        #[cfg(feature = "napi-6")]
702        let channel = InstanceData::channel(self);
703
704        #[cfg(not(feature = "napi-6"))]
705        let channel = Channel::new(self);
706
707        channel
708    }
709
710    /// Creates a [`Deferred`] and [`JsPromise`] pair. The [`Deferred`] handle can be
711    /// used to resolve or reject the [`JsPromise`].
712    ///
713    /// ```
714    /// # use neon::prelude::*;
715    /// fn resolve_promise(mut cx: FunctionContext) -> JsResult<JsPromise> {
716    ///     let (deferred, promise) = cx.promise();
717    ///     let msg = cx.string("Hello, World!");
718    ///
719    ///     deferred.resolve(&mut cx, msg);
720    ///
721    ///     Ok(promise)
722    /// }
723    /// ```
724    fn promise(&mut self) -> (Deferred, Handle<'a, JsPromise>) {
725        JsPromise::new(self)
726    }
727
728    /// Creates a [`TaskBuilder`] which can be used to schedule the `execute`
729    /// callback to asynchronously execute on the
730    /// [Node worker pool](https://nodejs.org/en/docs/guides/dont-block-the-event-loop/).
731    ///
732    /// ```
733    /// # use neon::prelude::*;
734    /// fn greet(mut cx: FunctionContext) -> JsResult<JsPromise> {
735    ///     let name = cx.argument::<JsString>(0)?.value(&mut cx);
736    ///
737    ///     let promise = cx
738    ///         .task(move || format!("Hello, {}!", name))
739    ///         .promise(move |mut cx, greeting| Ok(cx.string(greeting)));
740    ///
741    ///     Ok(promise)
742    /// }
743    /// ```
744    fn task<'cx, O, E>(&'cx mut self, execute: E) -> TaskBuilder<'cx, Self, E>
745    where
746        'a: 'cx,
747        O: Send + 'static,
748        E: FnOnce() -> O + Send + 'static,
749    {
750        TaskBuilder::new(self, execute)
751    }
752
753    #[cfg(feature = "sys")]
754    #[cfg_attr(docsrs, doc(cfg(feature = "sys")))]
755    /// Gets the raw `sys::Env` for usage with Node-API.
756    fn to_raw(&self) -> sys::Env {
757        self.env().to_raw()
758    }
759}
760
761/// An execution context of module initialization.
762pub struct ModuleContext<'cx> {
763    cx: Cx<'cx>,
764    exports: Handle<'cx, JsObject>,
765}
766
767impl<'cx> Deref for ModuleContext<'cx> {
768    type Target = Cx<'cx>;
769
770    fn deref(&self) -> &Self::Target {
771        self.cx()
772    }
773}
774
775impl<'cx> DerefMut for ModuleContext<'cx> {
776    fn deref_mut(&mut self) -> &mut Self::Target {
777        self.cx_mut()
778    }
779}
780
781impl<'cx> UnwindSafe for ModuleContext<'cx> {}
782
783impl<'cx> ModuleContext<'cx> {
784    pub(crate) fn with<T, F: for<'b> FnOnce(ModuleContext<'b>) -> T>(
785        env: Env,
786        exports: Handle<'cx, JsObject>,
787        f: F,
788    ) -> T {
789        f(ModuleContext {
790            cx: Cx::new(env),
791            exports,
792        })
793    }
794
795    #[cfg(not(feature = "napi-5"))]
796    /// Convenience method for exporting a Neon function from a module.
797    pub fn export_function<T: Value>(
798        &mut self,
799        key: &str,
800        f: fn(FunctionContext) -> JsResult<T>,
801    ) -> NeonResult<()> {
802        let value = JsFunction::new(self, f)?.upcast::<JsValue>();
803        self.exports.clone().set(self, key, value)?;
804        Ok(())
805    }
806
807    #[cfg(feature = "napi-5")]
808    /// Convenience method for exporting a Neon function from a module.
809    pub fn export_function<F, V>(&mut self, key: &str, f: F) -> NeonResult<()>
810    where
811        F: Fn(FunctionContext) -> JsResult<V> + 'static,
812        V: Value,
813    {
814        let value = JsFunction::new(self, f)?.upcast::<JsValue>();
815        // Note: Cloning `exports` is necessary to avoid holding a shared reference to
816        // `self` while attempting to use it mutably in `set`.
817        self.exports.clone().set(self, key, value)?;
818        Ok(())
819    }
820
821    /// Exports a JavaScript value from a Neon module.
822    pub fn export_value<T: Value>(&mut self, key: &str, val: Handle<T>) -> NeonResult<()> {
823        self.exports.clone().set(self, key, val)?;
824        Ok(())
825    }
826
827    /// Produces a handle to a module's exports object.
828    pub fn exports_object(&mut self) -> JsResult<'cx, JsObject> {
829        Ok(self.exports)
830    }
831}
832
833impl<'cx> ContextInternal<'cx> for ModuleContext<'cx> {
834    fn cx(&self) -> &Cx<'cx> {
835        &self.cx
836    }
837
838    fn cx_mut(&mut self) -> &mut Cx<'cx> {
839        &mut self.cx
840    }
841}
842
843impl<'cx> Context<'cx> for ModuleContext<'cx> {}
844
845/// An execution context of a function call.
846///
847/// The type parameter `T` is the type of the `this`-binding.
848pub struct FunctionContext<'cx> {
849    cx: Cx<'cx>,
850    info: &'cx CallbackInfo<'cx>,
851
852    arguments: Option<sys::call::Arguments>,
853}
854
855impl<'cx> Deref for FunctionContext<'cx> {
856    type Target = Cx<'cx>;
857
858    fn deref(&self) -> &Self::Target {
859        &self.cx
860    }
861}
862
863impl<'cx> DerefMut for FunctionContext<'cx> {
864    fn deref_mut(&mut self) -> &mut Self::Target {
865        &mut self.cx
866    }
867}
868
869impl<'cx> UnwindSafe for FunctionContext<'cx> {}
870
871impl<'cx> FunctionContext<'cx> {
872    /// Indicates whether the function was called with `new`.
873    pub fn kind(&self) -> CallKind {
874        self.info.kind(self)
875    }
876
877    pub(crate) fn with<U, F: for<'b> FnOnce(FunctionContext<'b>) -> U>(
878        env: Env,
879        info: &'cx CallbackInfo<'cx>,
880        f: F,
881    ) -> U {
882        f(FunctionContext {
883            cx: Cx::new(env),
884            info,
885            arguments: None,
886        })
887    }
888
889    /// Indicates the number of arguments that were passed to the function.
890    pub fn len(&self) -> usize {
891        self.info.len(self)
892    }
893
894    /// Indicates if no arguments were passed to the function.
895    pub fn is_empty(&self) -> bool {
896        self.len() == 0
897    }
898
899    /// Produces the `i`th argument, or `None` if `i` is greater than or equal to `self.len()`.
900    pub fn argument_opt(&mut self, i: usize) -> Option<Handle<'cx, JsValue>> {
901        let argv = if let Some(argv) = self.arguments.as_ref() {
902            argv
903        } else {
904            let argv = self.info.argv(self);
905            self.arguments.insert(argv)
906        };
907
908        argv.get(i)
909            .map(|v| Handle::new_internal(unsafe { JsValue::from_local(self.env(), v) }))
910    }
911
912    /// Produces the `i`th argument and casts it to the type `V`, or throws an exception if `i` is greater than or equal to `self.len()` or cannot be cast to `V`.
913    pub fn argument<V: Value>(&mut self, i: usize) -> JsResult<'cx, V> {
914        match self.argument_opt(i) {
915            Some(v) => v.downcast_or_throw(self),
916            None => self.throw_type_error("not enough arguments"),
917        }
918    }
919
920    /// Produces a handle to the `this`-binding and attempts to downcast as a specific type.
921    /// Equivalent to calling `cx.this_value().downcast_or_throw(&mut cx)`.
922    ///
923    /// Throws an exception if the value is a different type.
924    pub fn this<T: Value>(&mut self) -> JsResult<'cx, T> {
925        self.this_value().downcast_or_throw(self)
926    }
927
928    /// Produces a handle to the function's [`this`-binding](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#function_context).
929    pub fn this_value(&mut self) -> Handle<'cx, JsValue> {
930        JsValue::new_internal(self.info.this(self))
931    }
932
933    /// Extract Rust data from the JavaScript arguments.
934    ///
935    /// This is frequently more efficient and ergonomic than getting arguments
936    /// individually. See the [`extract`](crate::types::extract) module documentation
937    /// for more examples.
938    ///
939    /// ```
940    /// # use neon::{prelude::*, types::extract::*};
941    /// fn add(mut cx: FunctionContext) -> JsResult<JsNumber> {
942    ///     let (a, b): (f64, f64) = cx.args()?;
943    ///
944    ///     Ok(cx.number(a + b))
945    /// }
946    /// ```
947    pub fn args<T>(&mut self) -> NeonResult<T>
948    where
949        T: FromArgs<'cx>,
950    {
951        T::from_args(self)
952    }
953
954    /// Extract a single argument from a unary function. See [`Context::args`] for more details.
955    pub fn arg<T>(&mut self) -> NeonResult<T>
956    where
957        T: TryFromJs<'cx>,
958    {
959        self.args::<(T,)>().map(|(v,)| v)
960    }
961
962    /// Extract Rust data from the JavaScript arguments.
963    ///
964    /// Similar to [`FunctionContext::args`], but does not throw a JavaScript exception on errors. Useful
965    /// for function overloading.
966    ///
967    /// ```
968    /// # use neon::{prelude::*, types::extract::*};
969    /// fn combine(mut cx: FunctionContext) -> JsResult<JsValue> {
970    ///     if let Some((a, b)) = cx.args_opt::<(f64, f64)>()? {
971    ///         return Ok(cx.number(a + b).upcast());
972    ///     }
973    ///
974    ///     let (a, b): (String, String) = cx.args()?;
975    ///
976    ///     Ok(cx.string(a + &b).upcast())
977    /// }
978    /// ```
979    pub fn args_opt<T>(&mut self) -> NeonResult<Option<T>>
980    where
981        T: FromArgs<'cx>,
982    {
983        T::from_args_opt(self)
984    }
985
986    /// Extract a single optional argument from a unary function. See [`Context::args_opt`] for more details.
987    pub fn arg_opt<T>(&mut self) -> NeonResult<Option<T>>
988    where
989        T: TryFromJs<'cx>,
990    {
991        self.args_opt::<(T,)>().map(|v| v.map(|(v,)| v))
992    }
993
994    pub(crate) fn argv<const N: usize>(&mut self) -> [Handle<'cx, JsValue>; N] {
995        self.info.argv_exact(self)
996    }
997}
998
999impl<'cx> ContextInternal<'cx> for FunctionContext<'cx> {
1000    fn cx(&self) -> &Cx<'cx> {
1001        &self.cx
1002    }
1003
1004    fn cx_mut(&mut self) -> &mut Cx<'cx> {
1005        &mut self.cx
1006    }
1007}
1008
1009impl<'cx> Context<'cx> for FunctionContext<'cx> {}