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` — 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` — 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> {}