[go: up one dir, main page]

v8/
scope.rs

1// Copyright 2019-2021 the Deno authors. All rights reserved. MIT license.
2
3//! This module's public API exports a number of 'scope' types.
4//!
5//! These types carry information about the state of the V8 Isolate, as well as
6//! lifetimes for certain (return) values. More specialized scopes typically
7//! deref to more generic scopes, and ultimately they all deref to `Isolate`.
8//!
9//! The scope types in the public API are all pointer wrappers, and they all
10//! point at a heap-allocated struct `data::ScopeData`. `ScopeData` allocations
11//! are never shared between scopes; each Handle/Context/CallbackScope gets
12//! its own instance.
13//!
14//! Notes about the available scope types:
15//! See also the tests at the end of this file.
16//!
17//! - `HandleScope<'s, ()>`
18//!   - 's = lifetime of local handles created in this scope, and of the scope
19//!     itself.
20//!   - This type is returned when a HandleScope is constructed from a direct
21//!     reference to an isolate (`&mut Isolate` or `&mut OwnedIsolate`).
22//!   - A `Context` is _not_ available. Only certain types JavaScript values can
23//!     be created: primitive values, templates, and instances of `Context`.
24//!   - Derefs to `Isolate`.
25//!
26//! - `HandleScope<'s>`
27//!   - 's = lifetime of local handles created in this scope, and of the scope
28//!     itself.
29//!   - A `Context` is available; any type of value can be created.
30//!   - Derefs to `HandleScope<'s, ()>`
31//!
32//! - `ContextScope<'s, P>`
33//!   - 's = lifetime of the scope itself.
34//!   - A `Context` is available; any type of value can be created.
35//!   - Derefs to `P`.
36//!   - When constructed as the child of a `HandleScope<'a, ()>`, the returned
37//!     type is `ContextScope<'s, HandleScope<'p>>`. In other words, the parent
38//!     HandleScope gets an upgrade to indicate the availability of a `Context`.
39//!   - When a new scope is constructed inside this type of scope, the
40//!     `ContextScope` wrapper around `P` is erased first, which means that the
41//!     child scope is set up as if it had been created with `P` as its parent.
42//!
43//! - `EscapableHandleScope<'s, 'e>`
44//!   - 's = lifetime of local handles created in this scope, and of the scope
45//!     itself.
46//!   - 'e = lifetime of the HandleScope that will receive the local handle that
47//!     is created by `EscapableHandleScope::escape()`.
48//!   - A `Context` is available; any type of value can be created.
49//!   - Derefs to `HandleScope<'s>`.
50//!
51//! - `TryCatch<'s, P>`
52//!   - 's = lifetime of the TryCatch scope.
53//!   - `P` is either a `HandleScope` or an `EscapableHandleScope`. This type
54//!     also determines for how long the values returned by `TryCatch` methods
55//!     `exception()`, `message()`, and `stack_trace()` are valid.
56//!   - Derefs to `P`.
57//!   - Creating a new scope inside the `TryCatch` block makes its methods
58//!     inaccessible until the inner scope is dropped. However, the `TryCatch`
59//!     object will nonetheless catch all exception thrown during its lifetime.
60//!
61//! - `CallbackScope<'s, ()>`
62//!   - 's = lifetime of local handles created in this scope, and the value
63//!     returned from the callback, and of the scope itself.
64//!   - A `Context` is _not_ available. Only certain types JavaScript values can
65//!     be created: primitive values, templates, and instances of `Context`.
66//!   - Derefs to `HandleScope<'s, ()>`.
67//!   - This scope type is only to be constructed inside embedder defined
68//!     callbacks when these are called by V8.
69//!   - When a scope is created inside, type is erased to `HandleScope<'s, ()>`.
70//!
71//! - `CallbackScope<'s>`
72//!   - 's = lifetime of local handles created in this scope, and the value
73//!     returned from the callback, and of the scope itself.
74//!   - A `Context` is available; any type of value can be created.
75//!   - Derefs to `HandleScope<'s>`.
76//!   - This scope type is only to be constructed inside embedder defined
77//!     callbacks when these are called by V8.
78//!   - When a scope is created inside, type is erased to `HandleScope<'s>`.
79//!
80//! - `DisallowJavascriptExecutionScope<'s, P>`
81//!   - 's = lifetime of the `DisallowJavascriptExecutionScope` scope.
82//!   - `P` is either a `HandleScope`, `ContextScope`, `EscapableHandleScope`
83//!     or a `TryCatch`.
84//!   - Derefs to `P`.
85//!
86//! - `AllowJavascriptExecutionScope<'s, P>`
87//!   - 's = lifetime of the `AllowJavascriptExecutionScope` scope.
88//!   - `P` is `DisallowJavascriptExecutionScope`.
89//!   - Derefs to `HandleScope<'s, ()>`.
90
91use std::alloc::Layout;
92use std::alloc::alloc;
93use std::any::type_name;
94use std::cell::Cell;
95use std::convert::TryInto;
96
97use std::marker::PhantomData;
98use std::mem::MaybeUninit;
99use std::num::NonZeroUsize;
100use std::ops::Deref;
101use std::ops::DerefMut;
102use std::ptr;
103use std::ptr::NonNull;
104
105use crate::Context;
106use crate::Data;
107use crate::DataError;
108use crate::Function;
109use crate::Handle;
110use crate::Isolate;
111use crate::Local;
112use crate::Message;
113use crate::Object;
114use crate::OwnedIsolate;
115use crate::Primitive;
116use crate::PromiseRejectMessage;
117use crate::SealedLocal;
118use crate::Value;
119use crate::fast_api::FastApiCallbackOptions;
120use crate::function::FunctionCallbackInfo;
121use crate::function::PropertyCallbackInfo;
122
123/// Stack-allocated class which sets the execution context for all operations
124/// executed within a local scope. After entering a context, all code compiled
125/// and run is compiled and run in this context.
126#[derive(Debug)]
127pub struct ContextScope<'s, P> {
128  _data: NonNull<data::ScopeData>,
129  _phantom: PhantomData<&'s mut P>,
130}
131
132impl<'s, P: param::NewContextScope<'s>> ContextScope<'s, P> {
133  #[allow(clippy::new_ret_no_self)]
134  pub fn new(param: &'s mut P, context: Local<Context>) -> P::NewScope {
135    let scope_data = param.get_scope_data_mut();
136    if scope_data.get_isolate_ptr()
137      != unsafe { raw::v8__Context__GetIsolate(&*context) }
138    {
139      panic!(
140        "{} and Context do not belong to the same Isolate",
141        type_name::<P>()
142      )
143    }
144    let new_scope_data = scope_data.new_context_scope_data(context);
145    new_scope_data.as_scope()
146  }
147}
148
149/// A stack-allocated class that governs a number of local handles.
150/// After a handle scope has been created, all local handles will be
151/// allocated within that handle scope until either the handle scope is
152/// deleted or another handle scope is created.  If there is already a
153/// handle scope and a new one is created, all allocations will take
154/// place in the new handle scope until it is deleted.  After that,
155/// new handles will again be allocated in the original handle scope.
156///
157/// After the handle scope of a local handle has been deleted the
158/// garbage collector will no longer track the object stored in the
159/// handle and may deallocate it.  The behavior of accessing a handle
160/// for which the handle scope has been deleted is undefined.
161#[derive(Debug)]
162pub struct HandleScope<'s, C = Context> {
163  _data: NonNull<data::ScopeData>,
164  _phantom: PhantomData<&'s mut C>,
165}
166
167impl<'s> HandleScope<'s> {
168  #[allow(clippy::new_ret_no_self)]
169  pub fn new<P: param::NewHandleScope<'s>>(param: &'s mut P) -> P::NewScope {
170    param
171      .get_scope_data_mut()
172      .new_handle_scope_data()
173      .as_scope()
174  }
175
176  /// Opens a new `HandleScope` and enters a `Context` in one step.
177  /// The first argument should be an `Isolate` or `OwnedIsolate`.
178  /// The second argument can be any handle that refers to a `Context` object;
179  /// usually this will be a `Global<Context>`.
180  pub fn with_context<
181    P: param::NewHandleScopeWithContext<'s>,
182    H: Handle<Data = Context>,
183  >(
184    param: &'s mut P,
185    context: H,
186  ) -> Self {
187    let context_ref = context.open(param.get_isolate_mut());
188    param
189      .get_scope_data_mut()
190      .new_handle_scope_data_with_context(context_ref)
191      .as_scope()
192  }
193
194  /// Returns the context of the currently running JavaScript, or the context
195  /// on the top of the stack if no JavaScript is running.
196  #[inline(always)]
197  pub fn get_current_context(&self) -> Local<'s, Context> {
198    let context_ptr = data::ScopeData::get(self).get_current_context();
199    unsafe { Local::from_raw(context_ptr) }.unwrap()
200  }
201
202  /// Returns either the last context entered through V8's C++ API, or the
203  /// context of the currently running microtask while processing microtasks.
204  /// If a context is entered while executing a microtask, that context is
205  /// returned.
206  pub fn get_entered_or_microtask_context(&self) -> Local<'s, Context> {
207    let data = data::ScopeData::get(self);
208    let isolate_ptr = data.get_isolate_ptr();
209    let context_ptr =
210      unsafe { raw::v8__Isolate__GetEnteredOrMicrotaskContext(isolate_ptr) };
211    unsafe { Local::from_raw(context_ptr) }.unwrap()
212  }
213
214  /// Returns the host defined options set for currently running script or
215  /// module, if available.
216  #[inline(always)]
217  pub fn get_current_host_defined_options(&self) -> Option<Local<'s, Data>> {
218    let data = data::ScopeData::get(self);
219    let isolate_ptr = data.get_isolate_ptr();
220    unsafe {
221      Local::from_raw(raw::v8__Isolate__GetCurrentHostDefinedOptions(
222        isolate_ptr,
223      ))
224    }
225  }
226}
227
228impl<'s> HandleScope<'s, ()> {
229  /// Schedules an exception to be thrown when returning to JavaScript. When
230  /// an exception has been scheduled it is illegal to invoke any
231  /// JavaScript operation; the caller must return immediately and only
232  /// after the exception has been handled does it become legal to invoke
233  /// JavaScript operations.
234  ///
235  /// This function always returns the `undefined` value.
236  #[inline(always)]
237  pub fn throw_exception(
238    &mut self,
239    exception: Local<Value>,
240  ) -> Local<'s, Value> {
241    unsafe {
242      self.cast_local(|sd| {
243        raw::v8__Isolate__ThrowException(sd.get_isolate_ptr(), &*exception)
244      })
245    }
246    .unwrap()
247  }
248
249  #[inline(always)]
250  pub(crate) unsafe fn cast_local<T>(
251    &mut self,
252    f: impl FnOnce(&mut data::ScopeData) -> *const T,
253  ) -> Option<Local<'s, T>> {
254    unsafe { Local::from_raw(f(data::ScopeData::get_mut(self))) }
255  }
256
257  #[inline(always)]
258  pub(crate) fn get_isolate_ptr(&self) -> *mut Isolate {
259    data::ScopeData::get(self).get_isolate_ptr()
260  }
261
262  /// Open a handle passed from V8 in the current scope.
263  ///
264  /// # Safety
265  ///
266  /// The handle must be rooted in this scope.
267  #[inline(always)]
268  pub unsafe fn unseal<T>(&self, v: SealedLocal<T>) -> Local<'s, T> {
269    unsafe { Local::from_non_null(v.0) }
270  }
271}
272
273// TODO(mmastrac): When the never type is stabilized, we can replace this trait
274// with type bounds (https://github.com/rust-lang/rust/issues/35121):
275
276// for<'l> DataError: From<<Local<'s, Data> as TryInto<Local<'l, T>>>::Error>,
277mod get_data_sealed {
278  use crate::DataError;
279  use std::convert::Infallible;
280
281  pub trait ToDataError {
282    fn to_data_error(self) -> DataError;
283  }
284  impl ToDataError for DataError {
285    fn to_data_error(self) -> DataError {
286      self
287    }
288  }
289  impl ToDataError for Infallible {
290    fn to_data_error(self) -> DataError {
291      unreachable!()
292    }
293  }
294}
295
296impl<'s> HandleScope<'s> {
297  /// Return data that was previously attached to the isolate snapshot via
298  /// SnapshotCreator, and removes the reference to it. If called again with
299  /// same `index` argument, this function returns `DataError::NoData`.
300  ///
301  /// The value that was stored in the snapshot must either match or be
302  /// convertible to type parameter `T`, otherwise `DataError::BadType` is
303  /// returned.
304  pub fn get_isolate_data_from_snapshot_once<T>(
305    &mut self,
306    index: usize,
307  ) -> Result<Local<'s, T>, DataError>
308  where
309    T: 'static,
310    for<'l> <Local<'l, Data> as TryInto<Local<'l, T>>>::Error:
311      get_data_sealed::ToDataError,
312    for<'l> Local<'l, Data>: TryInto<Local<'l, T>>,
313  {
314    unsafe {
315      let Some(res) = self.cast_local(|sd| {
316        raw::v8__Isolate__GetDataFromSnapshotOnce(sd.get_isolate_ptr(), index)
317      }) else {
318        return Err(DataError::no_data::<T>());
319      };
320      use get_data_sealed::ToDataError;
321      match res.try_into() {
322        Ok(x) => Ok(x),
323        Err(e) => Err(e.to_data_error()),
324      }
325    }
326  }
327
328  /// Return data that was previously attached to the context snapshot via
329  /// SnapshotCreator, and removes the reference to it. If called again with
330  /// same `index` argument, this function returns `DataError::NoData`.
331  ///
332  /// The value that was stored in the snapshot must either match or be
333  /// convertible to type parameter `T`, otherwise `DataError::BadType` is
334  /// returned.
335  pub fn get_context_data_from_snapshot_once<T>(
336    &mut self,
337    index: usize,
338  ) -> Result<Local<'s, T>, DataError>
339  where
340    T: 'static,
341    for<'l> <Local<'l, Data> as TryInto<Local<'l, T>>>::Error:
342      get_data_sealed::ToDataError,
343    for<'l> Local<'l, Data>: TryInto<Local<'l, T>>,
344  {
345    unsafe {
346      let Some(res) = self.cast_local(|sd| {
347        raw::v8__Context__GetDataFromSnapshotOnce(
348          sd.get_current_context(),
349          index,
350        )
351      }) else {
352        return Err(DataError::no_data::<T>());
353      };
354      use get_data_sealed::ToDataError;
355      match res.try_into() {
356        Ok(x) => Ok(x),
357        Err(e) => Err(e.to_data_error()),
358      }
359    }
360  }
361
362  #[inline(always)]
363  pub fn set_promise_hooks(
364    &mut self,
365    init_hook: Option<Local<Function>>,
366    before_hook: Option<Local<Function>>,
367    after_hook: Option<Local<Function>>,
368    resolve_hook: Option<Local<Function>>,
369  ) {
370    unsafe {
371      let sd = data::ScopeData::get_mut(self);
372      raw::v8__Context__SetPromiseHooks(
373        sd.get_current_context(),
374        init_hook.map_or_else(std::ptr::null, |v| &*v),
375        before_hook.map_or_else(std::ptr::null, |v| &*v),
376        after_hook.map_or_else(std::ptr::null, |v| &*v),
377        resolve_hook.map_or_else(std::ptr::null, |v| &*v),
378      );
379    }
380  }
381
382  #[inline(always)]
383  pub fn set_continuation_preserved_embedder_data(
384    &mut self,
385    data: Local<Value>,
386  ) {
387    unsafe {
388      let sd = data::ScopeData::get_mut(self);
389      raw::v8__Context__SetContinuationPreservedEmbedderData(
390        sd.get_isolate_ptr(),
391        &*data,
392      );
393    }
394  }
395
396  #[inline(always)]
397  pub fn get_continuation_preserved_embedder_data(
398    &mut self,
399  ) -> Local<'s, Value> {
400    unsafe {
401      self
402        .cast_local(|sd| {
403          raw::v8__Context__GetContinuationPreservedEmbedderData(
404            sd.get_isolate_ptr(),
405          )
406        })
407        .unwrap()
408    }
409  }
410}
411
412/// A HandleScope which first allocates a handle in the current scope
413/// which will be later filled with the escape value.
414// TODO(piscisaureus): type parameter `C` is not very useful in practice; being
415// a source of complexity and potential confusion, it is desirable to
416// eventually remove it. Blocker at the time of writing is that there are some
417// tests that enter an `EscapableHandleScope` without creating a `ContextScope`
418// at all. These tests need to updated first.
419#[derive(Debug)]
420pub struct EscapableHandleScope<'s, 'e: 's, C = Context> {
421  _data: NonNull<data::ScopeData>,
422  _phantom:
423    PhantomData<(&'s mut raw::HandleScope, &'e mut raw::EscapeSlot, &'s C)>,
424}
425
426impl<'s, 'e: 's> EscapableHandleScope<'s, 'e> {
427  #[allow(clippy::new_ret_no_self)]
428  pub fn new<P: param::NewEscapableHandleScope<'s, 'e>>(
429    param: &'s mut P,
430  ) -> P::NewScope {
431    param
432      .get_scope_data_mut()
433      .new_escapable_handle_scope_data()
434      .as_scope()
435  }
436}
437
438impl<'s, 'e: 's, C> EscapableHandleScope<'s, 'e, C> {
439  /// Pushes the value into the previous scope and returns a handle to it.
440  /// Cannot be called twice.
441  pub fn escape<T>(&mut self, value: Local<T>) -> Local<'e, T>
442  where
443    for<'l> Local<'l, T>: Into<Local<'l, Data>>,
444  {
445    let escape_slot = data::ScopeData::get_mut(self)
446      .get_escape_slot_mut()
447      .expect("internal error: EscapableHandleScope has no escape slot")
448      .take()
449      .expect("EscapableHandleScope::escape() called twice");
450    escape_slot.escape(value)
451  }
452}
453
454/// An external exception handler.
455#[derive(Debug)]
456pub struct TryCatch<'s, P> {
457  _data: NonNull<data::ScopeData>,
458  _phantom: PhantomData<&'s mut P>,
459}
460
461impl<'s, P: param::NewTryCatch<'s>> TryCatch<'s, P> {
462  #[allow(clippy::new_ret_no_self)]
463  pub fn new(param: &'s mut P) -> P::NewScope {
464    param.get_scope_data_mut().new_try_catch_data().as_scope()
465  }
466}
467
468impl<P> TryCatch<'_, P> {
469  /// Returns true if an exception has been caught by this try/catch block.
470  #[inline(always)]
471  pub fn has_caught(&self) -> bool {
472    unsafe { raw::v8__TryCatch__HasCaught(self.get_raw()) }
473  }
474
475  /// For certain types of exceptions, it makes no sense to continue execution.
476  ///
477  /// If CanContinue returns false, the correct action is to perform any C++
478  /// cleanup needed and then return. If CanContinue returns false and
479  /// HasTerminated returns true, it is possible to call
480  /// CancelTerminateExecution in order to continue calling into the engine.
481  #[inline(always)]
482  pub fn can_continue(&self) -> bool {
483    unsafe { raw::v8__TryCatch__CanContinue(self.get_raw()) }
484  }
485
486  /// Returns true if an exception has been caught due to script execution
487  /// being terminated.
488  ///
489  /// There is no JavaScript representation of an execution termination
490  /// exception. Such exceptions are thrown when the TerminateExecution
491  /// methods are called to terminate a long-running script.
492  ///
493  /// If such an exception has been thrown, HasTerminated will return true,
494  /// indicating that it is possible to call CancelTerminateExecution in order
495  /// to continue calling into the engine.
496  #[inline(always)]
497  pub fn has_terminated(&self) -> bool {
498    unsafe { raw::v8__TryCatch__HasTerminated(self.get_raw()) }
499  }
500
501  /// Returns true if verbosity is enabled.
502  #[inline(always)]
503  pub fn is_verbose(&self) -> bool {
504    unsafe { raw::v8__TryCatch__IsVerbose(self.get_raw()) }
505  }
506
507  /// Set verbosity of the external exception handler.
508  ///
509  /// By default, exceptions that are caught by an external exception
510  /// handler are not reported. Call SetVerbose with true on an
511  /// external exception handler to have exceptions caught by the
512  /// handler reported as if they were not caught.
513  #[inline(always)]
514  pub fn set_verbose(&mut self, value: bool) {
515    unsafe { raw::v8__TryCatch__SetVerbose(self.get_raw_mut(), value) };
516  }
517
518  /// Set whether or not this TryCatch should capture a Message object
519  /// which holds source information about where the exception
520  /// occurred. True by default.
521  #[inline(always)]
522  pub fn set_capture_message(&mut self, value: bool) {
523    unsafe { raw::v8__TryCatch__SetCaptureMessage(self.get_raw_mut(), value) };
524  }
525
526  /// Clears any exceptions that may have been caught by this try/catch block.
527  /// After this method has been called, HasCaught() will return false. Cancels
528  /// the scheduled exception if it is caught and ReThrow() is not called
529  /// before.
530  ///
531  /// It is not necessary to clear a try/catch block before using it again; if
532  /// another exception is thrown the previously caught exception will just be
533  /// overwritten. However, it is often a good idea since it makes it easier
534  /// to determine which operation threw a given exception.
535  #[inline(always)]
536  pub fn reset(&mut self) {
537    unsafe { raw::v8__TryCatch__Reset(self.get_raw_mut()) };
538  }
539
540  #[inline(always)]
541  fn get_raw(&self) -> &raw::TryCatch {
542    data::ScopeData::get(self).get_try_catch()
543  }
544
545  #[inline(always)]
546  fn get_raw_mut(&mut self) -> &mut raw::TryCatch {
547    data::ScopeData::get_mut(self).get_try_catch_mut()
548  }
549}
550
551impl<'s, 'p: 's, P> TryCatch<'s, P>
552where
553  Self: AsMut<HandleScope<'p, ()>>,
554{
555  /// Returns the exception caught by this try/catch block. If no exception has
556  /// been caught an empty handle is returned.
557  ///
558  /// Note: v8.h states that "the returned handle is valid until this TryCatch
559  /// block has been destroyed". This is incorrect; the return value lives
560  /// no longer and no shorter than the active HandleScope at the time this
561  /// method is called. An issue has been opened about this in the V8 bug
562  /// tracker: https://bugs.chromium.org/p/v8/issues/detail?id=10537.
563  pub fn exception(&mut self) -> Option<Local<'p, Value>> {
564    unsafe {
565      self
566        .as_mut()
567        .cast_local(|sd| raw::v8__TryCatch__Exception(sd.get_try_catch()))
568    }
569  }
570
571  /// Returns the message associated with this exception. If there is
572  /// no message associated an empty handle is returned.
573  ///
574  /// Note: the remark about the lifetime for the `exception()` return value
575  /// applies here too.
576  pub fn message(&mut self) -> Option<Local<'p, Message>> {
577    unsafe {
578      self
579        .as_mut()
580        .cast_local(|sd| raw::v8__TryCatch__Message(sd.get_try_catch()))
581    }
582  }
583
584  /// Throws the exception caught by this TryCatch in a way that avoids
585  /// it being caught again by this same TryCatch. As with ThrowException
586  /// it is illegal to execute any JavaScript operations after calling
587  /// ReThrow; the caller must return immediately to where the exception
588  /// is caught.
589  ///
590  /// This function returns the `undefined` value when successful, or `None` if
591  /// no exception was caught and therefore there was nothing to rethrow.
592  pub fn rethrow(&mut self) -> Option<Local<'_, Value>> {
593    unsafe {
594      self
595        .as_mut()
596        .cast_local(|sd| raw::v8__TryCatch__ReThrow(sd.get_try_catch_mut()))
597    }
598  }
599}
600
601impl<'s, 'p: 's, P> TryCatch<'s, P>
602where
603  Self: AsMut<HandleScope<'p>>,
604{
605  /// Returns the .stack property of the thrown object. If no .stack
606  /// property is present an empty handle is returned.
607  pub fn stack_trace(&mut self) -> Option<Local<'p, Value>> {
608    unsafe {
609      self.as_mut().cast_local(|sd| {
610        raw::v8__TryCatch__StackTrace(
611          sd.get_try_catch(),
612          sd.get_current_context(),
613        )
614      })
615    }
616  }
617}
618
619/// A `CallbackScope` can be used to bootstrap a `HandleScope` and
620/// `ContextScope` inside a callback function that gets called by V8.
621/// Bootstrapping a scope inside a callback is the only valid use case of this
622/// type; using it in other places leads to undefined behavior, which is also
623/// the reason `CallbackScope::new()` is marked as being an unsafe function.
624///
625/// For some callback types, rusty_v8 internally creates a scope and passes it
626/// as an argument to to embedder callback. Eventually we intend to wrap all
627/// callbacks in this fashion, so the embedder would never needs to construct
628/// a CallbackScope.
629///
630/// A `CallbackScope<()>`, without context, can be created from:
631///   - `&mut Isolate`
632///   - `&mut OwnedIsolate`
633///
634/// A `CallbackScope`, with context, can be created from:
635///   - `Local<Context>`
636///   - `Local<Message>`
637///   - `Local<Object>`
638///   - `Local<Promise>`
639///   - `Local<SharedArrayBuffer>`
640///   - `&FunctionCallbackInfo`
641///   - `&PropertyCallbackInfo`
642///   - `&PromiseRejectMessage`
643///   - `&FastApiCallbackOptions`
644#[derive(Debug)]
645pub struct CallbackScope<'s, C = Context> {
646  _data: NonNull<data::ScopeData>,
647  _phantom: PhantomData<&'s mut HandleScope<'s, C>>,
648}
649
650impl<'s> CallbackScope<'s> {
651  #[allow(clippy::new_ret_no_self)]
652  pub unsafe fn new<P: param::NewCallbackScope<'s>>(param: P) -> P::NewScope {
653    let context = param.get_context();
654    let scope_data =
655      data::ScopeData::get_current_mut(unsafe { param.get_isolate_mut() });
656    // A HandleScope is not implicitly created for
657    // fast functions, so one must be opened here.
658    let scope_data = if P::NEEDS_SCOPE {
659      if let Some(context) = context {
660        scope_data.new_handle_scope_data_with_context(&context)
661      } else {
662        scope_data.new_handle_scope_data()
663      }
664    } else {
665      scope_data.new_callback_scope_data(context)
666    };
667    // This scope needs to exit when dropped, as it
668    // must not live beyond the callback activation.
669    scope_data.disable_zombie();
670    scope_data.as_scope()
671  }
672}
673
674#[derive(Debug, Clone, Copy, PartialEq, Eq)]
675#[repr(C)]
676pub enum OnFailure {
677  CrashOnFailure,
678  ThrowOnFailure,
679  DumpOnFailure,
680}
681
682#[derive(Debug)]
683pub struct DisallowJavascriptExecutionScope<'s, P> {
684  _data: NonNull<data::ScopeData>,
685  _phantom: PhantomData<&'s mut P>,
686}
687
688impl<'s, P: param::NewDisallowJavascriptExecutionScope<'s>>
689  DisallowJavascriptExecutionScope<'s, P>
690{
691  #[allow(clippy::new_ret_no_self)]
692  pub fn new(param: &'s mut P, on_failure: OnFailure) -> P::NewScope {
693    param
694      .get_scope_data_mut()
695      .new_disallow_javascript_execution_scope_data(on_failure)
696      .as_scope()
697  }
698}
699
700#[derive(Debug)]
701pub struct AllowJavascriptExecutionScope<'s, P> {
702  _data: NonNull<data::ScopeData>,
703  _phantom: PhantomData<&'s mut P>,
704}
705
706impl<'s, P: param::NewAllowJavascriptExecutionScope<'s>>
707  AllowJavascriptExecutionScope<'s, P>
708{
709  #[allow(clippy::new_ret_no_self)]
710  pub fn new(param: &'s mut P) -> P::NewScope {
711    param
712      .get_scope_data_mut()
713      .new_allow_javascript_execution_scope_data()
714      .as_scope()
715  }
716}
717
718macro_rules! impl_as {
719  // Implements `AsRef<Isolate>` and AsMut<Isolate>` on a scope type.
720  (<$($params:tt),+> $src_type:ty as Isolate) => {
721    impl<$($params),*> AsRef<Isolate> for $src_type {
722      fn as_ref(&self) -> &Isolate {
723        data::ScopeData::get(self).get_isolate()
724      }
725    }
726
727    impl<$($params),*> AsMut<Isolate> for $src_type {
728      fn as_mut(&mut self) -> &mut Isolate {
729        data::ScopeData::get_mut(self).get_isolate_mut()
730      }
731    }
732  };
733
734  // Implements `AsRef` and `AsMut` traits for the purpose of converting a
735  // a scope reference to a scope reference with a different but compatible type.
736  (<$($params:tt),+> $src_type:ty as $tgt_type:ty) => {
737    impl<$($params),*> AsRef<$tgt_type> for $src_type {
738      fn as_ref(&self) -> &$tgt_type {
739        self.cast_ref()
740      }
741    }
742
743    impl<$($params),*> AsMut< $tgt_type> for $src_type {
744      fn as_mut(&mut self) -> &mut $tgt_type {
745        self.cast_mut()
746      }
747    }
748  };
749}
750
751impl_as!(<'s, 'p, P> ContextScope<'s, P> as Isolate);
752impl_as!(<'s, C> HandleScope<'s, C> as Isolate);
753impl_as!(<'s, 'e, C> EscapableHandleScope<'s, 'e, C> as Isolate);
754impl_as!(<'s, P> TryCatch<'s, P> as Isolate);
755impl_as!(<'s, P> DisallowJavascriptExecutionScope<'s, P> as Isolate);
756impl_as!(<'s, P> AllowJavascriptExecutionScope<'s, P> as Isolate);
757impl_as!(<'s, C> CallbackScope<'s, C> as Isolate);
758
759impl_as!(<'s, 'p> ContextScope<'s, HandleScope<'p>> as HandleScope<'p, ()>);
760impl_as!(<'s, 'p, 'e> ContextScope<'s, EscapableHandleScope<'p, 'e>> as HandleScope<'p, ()>);
761impl_as!(<'s, C> HandleScope<'s, C> as HandleScope<'s, ()>);
762impl_as!(<'s, 'e, C> EscapableHandleScope<'s, 'e, C> as HandleScope<'s, ()>);
763impl_as!(<'s, 'p, C> TryCatch<'s, HandleScope<'p, C>> as HandleScope<'p, ()>);
764impl_as!(<'s, 'p, 'e, C> TryCatch<'s, EscapableHandleScope<'p, 'e, C>> as HandleScope<'p, ()>);
765impl_as!(<'s, 'p, C> DisallowJavascriptExecutionScope<'s, HandleScope<'p, C>> as HandleScope<'p, ()>);
766impl_as!(<'s, 'p, 'e, C> DisallowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e, C>> as HandleScope<'p, ()>);
767impl_as!(<'s, 'p, C> AllowJavascriptExecutionScope<'s, HandleScope<'p, C>> as HandleScope<'p, ()>);
768impl_as!(<'s, 'p, 'e, C> AllowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e, C>> as HandleScope<'p, ()>);
769impl_as!(<'s, C> CallbackScope<'s, C> as HandleScope<'s, ()>);
770
771impl_as!(<'s, 'p> ContextScope<'s, HandleScope<'p>> as HandleScope<'p>);
772impl_as!(<'s, 'p, 'e> ContextScope<'s, EscapableHandleScope<'p, 'e>> as HandleScope<'p>);
773impl_as!(<'s> HandleScope<'s> as HandleScope<'s>);
774impl_as!(<'s, 'e> EscapableHandleScope<'s, 'e> as HandleScope<'s>);
775impl_as!(<'s, 'p> TryCatch<'s, HandleScope<'p>> as HandleScope<'p>);
776impl_as!(<'s, 'p, 'e> TryCatch<'s, EscapableHandleScope<'p, 'e>> as HandleScope<'p>);
777impl_as!(<'s, 'p> DisallowJavascriptExecutionScope<'s, HandleScope<'p>> as HandleScope<'p>);
778impl_as!(<'s, 'p, 'e> DisallowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e>> as HandleScope<'p>);
779impl_as!(<'s, 'p> AllowJavascriptExecutionScope<'s, HandleScope<'p>> as HandleScope<'p>);
780impl_as!(<'s, 'p, 'e> AllowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e>> as HandleScope<'p>);
781impl_as!(<'s> CallbackScope<'s> as HandleScope<'s>);
782
783impl_as!(<'s, 'p, 'e> ContextScope<'s, EscapableHandleScope<'p, 'e>> as EscapableHandleScope<'p, 'e, ()>);
784impl_as!(<'s, 'e, C> EscapableHandleScope<'s, 'e, C> as EscapableHandleScope<'s, 'e, ()>);
785impl_as!(<'s, 'p, 'e, C> TryCatch<'s, EscapableHandleScope<'p, 'e, C>> as EscapableHandleScope<'p, 'e, ()>);
786impl_as!(<'s, 'p, 'e, C> DisallowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e, C>> as EscapableHandleScope<'p, 'e, ()>);
787impl_as!(<'s, 'p, 'e, C> AllowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e, C>> as EscapableHandleScope<'p, 'e, ()>);
788
789impl_as!(<'s, 'p, 'e> ContextScope<'s, EscapableHandleScope<'p, 'e>> as EscapableHandleScope<'p, 'e>);
790impl_as!(<'s, 'e> EscapableHandleScope<'s, 'e> as EscapableHandleScope<'s, 'e>);
791impl_as!(<'s, 'p, 'e> TryCatch<'s, EscapableHandleScope<'p, 'e>> as EscapableHandleScope<'p, 'e>);
792impl_as!(<'s, 'p, 'e> DisallowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e>> as EscapableHandleScope<'p, 'e>);
793impl_as!(<'s, 'p, 'e> AllowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e>> as EscapableHandleScope<'p, 'e>);
794
795impl_as!(<'s, 'p, C> TryCatch<'s, HandleScope<'p, C>> as TryCatch<'s, HandleScope<'p, ()>>);
796impl_as!(<'s, 'p, 'e, C> TryCatch<'s, EscapableHandleScope<'p, 'e, C>> as TryCatch<'s, HandleScope<'p, ()>>);
797impl_as!(<'s, 'p, 'e, C> TryCatch<'s, EscapableHandleScope<'p, 'e, C>> as TryCatch<'s, EscapableHandleScope<'p, 'e, ()>>);
798
799impl_as!(<'s, 'p> TryCatch<'s, HandleScope<'p>> as TryCatch<'s, HandleScope<'p>>);
800impl_as!(<'s, 'p, 'e> TryCatch<'s, EscapableHandleScope<'p, 'e>> as TryCatch<'s, HandleScope<'p>>);
801impl_as!(<'s, 'p, 'e> TryCatch<'s, EscapableHandleScope<'p, 'e>> as TryCatch<'s, EscapableHandleScope<'p, 'e>>);
802
803impl_as!(<'s, 'p, C> DisallowJavascriptExecutionScope<'s, HandleScope<'p, C>> as DisallowJavascriptExecutionScope<'s, HandleScope<'p, ()>>);
804impl_as!(<'s, 'p, 'e, C> DisallowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e, C>> as DisallowJavascriptExecutionScope<'s, HandleScope<'p, ()>>);
805impl_as!(<'s, 'p, 'e, C> DisallowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e, C>> as DisallowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e, ()>>);
806
807impl_as!(<'s, 'p> DisallowJavascriptExecutionScope<'s, HandleScope<'p>> as DisallowJavascriptExecutionScope<'s, HandleScope<'p>>);
808impl_as!(<'s, 'p, 'e> DisallowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e>> as DisallowJavascriptExecutionScope<'s, HandleScope<'p>>);
809impl_as!(<'s, 'p, 'e> DisallowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e>> as DisallowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e>>);
810
811impl_as!(<'s, 'p, C> AllowJavascriptExecutionScope<'s, HandleScope<'p, C>> as AllowJavascriptExecutionScope<'s, HandleScope<'p, ()>>);
812impl_as!(<'s, 'p, 'e, C> AllowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e, C>> as AllowJavascriptExecutionScope<'s, HandleScope<'p, ()>>);
813impl_as!(<'s, 'p, 'e, C> AllowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e, C>> as AllowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e, ()>>);
814
815impl_as!(<'s, 'p> AllowJavascriptExecutionScope<'s, HandleScope<'p>> as AllowJavascriptExecutionScope<'s, HandleScope<'p>>);
816impl_as!(<'s, 'p, 'e> AllowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e>> as AllowJavascriptExecutionScope<'s, HandleScope<'p>>);
817impl_as!(<'s, 'p, 'e> AllowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e>> as AllowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e>>);
818
819impl_as!(<'s, 'p, P> DisallowJavascriptExecutionScope<'s, TryCatch<'p, P>> as TryCatch<'p, P>);
820impl_as!(<'s, 'p, P> AllowJavascriptExecutionScope<'s, TryCatch<'p, P>> as TryCatch<'p, P>);
821
822macro_rules! impl_deref {
823  (<$($params:tt),+> $src_type:ty as $tgt_type:ty) => {
824    impl<$($params),*> Deref for $src_type {
825      type Target = $tgt_type;
826      fn deref(&self) -> &Self::Target {
827        self.as_ref()
828      }
829    }
830
831    impl<$($params),*> DerefMut for $src_type {
832      fn deref_mut(&mut self) -> &mut Self::Target {
833        self.as_mut()
834      }
835    }
836  };
837}
838
839impl_deref!(<'s, 'p> ContextScope<'s, HandleScope<'p>> as HandleScope<'p>);
840impl_deref!(<'s, 'p, 'e> ContextScope<'s, EscapableHandleScope<'p, 'e>> as EscapableHandleScope<'p, 'e>);
841
842impl_deref!(<'s> HandleScope<'s, ()> as Isolate);
843impl_deref!(<'s> HandleScope<'s> as HandleScope<'s, ()>);
844
845impl_deref!(<'s, 'e> EscapableHandleScope<'s, 'e, ()> as HandleScope<'s, ()>);
846impl_deref!(<'s, 'e> EscapableHandleScope<'s, 'e> as HandleScope<'s>);
847
848impl_deref!(<'s, 'p> TryCatch<'s, HandleScope<'p, ()>> as HandleScope<'p, ()>);
849impl_deref!(<'s, 'p> TryCatch<'s, HandleScope<'p>> as HandleScope<'p>);
850impl_deref!(<'s, 'p, 'e> TryCatch<'s, EscapableHandleScope<'p, 'e, ()>> as EscapableHandleScope<'p, 'e, ()>);
851impl_deref!(<'s, 'p, 'e> TryCatch<'s, EscapableHandleScope<'p, 'e>> as EscapableHandleScope<'p, 'e>);
852
853impl_deref!(<'s, 'p> DisallowJavascriptExecutionScope<'s, HandleScope<'p, ()>> as HandleScope<'p, ()>);
854impl_deref!(<'s, 'p> DisallowJavascriptExecutionScope<'s, HandleScope<'p>> as HandleScope<'p>);
855impl_deref!(<'s, 'p, 'e> DisallowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e, ()>> as EscapableHandleScope<'p, 'e, ()>);
856impl_deref!(<'s, 'p, 'e> DisallowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e>> as EscapableHandleScope<'p, 'e>);
857impl_deref!(<'s, 'p, P> DisallowJavascriptExecutionScope<'s, TryCatch<'p, P>> as TryCatch<'p, P>);
858
859impl_deref!(<'s, 'p> AllowJavascriptExecutionScope<'s, HandleScope<'p, ()>> as HandleScope<'p, ()>);
860impl_deref!(<'s, 'p> AllowJavascriptExecutionScope<'s, HandleScope<'p>> as HandleScope<'p>);
861impl_deref!(<'s, 'p, 'e> AllowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e, ()>> as EscapableHandleScope<'p, 'e, ()>);
862impl_deref!(<'s, 'p, 'e> AllowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e>> as EscapableHandleScope<'p, 'e>);
863impl_deref!(<'s, 'p, P> AllowJavascriptExecutionScope<'s, TryCatch<'p, P>> as TryCatch<'p, P>);
864
865impl_deref!(<'s> CallbackScope<'s, ()> as HandleScope<'s, ()>);
866impl_deref!(<'s> CallbackScope<'s> as HandleScope<'s>);
867
868macro_rules! impl_scope_drop {
869  (<$($params:tt),+> $type:ty) => {
870    unsafe impl<$($params),*> Scope for $type {}
871
872    impl<$($params),*> Drop for $type {
873      #[inline(always)]
874      fn drop(&mut self) {
875        data::ScopeData::get_mut(self).notify_scope_dropped();
876      }
877    }
878  };
879}
880
881impl_scope_drop!(<'s, 'p, P> ContextScope<'s, P>);
882impl_scope_drop!(<'s, C> HandleScope<'s, C> );
883impl_scope_drop!(<'s, 'e, C> EscapableHandleScope<'s, 'e, C> );
884impl_scope_drop!(<'s, P> TryCatch<'s, P> );
885impl_scope_drop!(<'s, P> DisallowJavascriptExecutionScope<'s, P>);
886impl_scope_drop!(<'s, P> AllowJavascriptExecutionScope<'s, P>);
887impl_scope_drop!(<'s, C> CallbackScope<'s, C> );
888
889pub unsafe trait Scope: Sized {}
890
891trait ScopeCast: Sized {
892  fn cast_ref<S: Scope>(&self) -> &S;
893  fn cast_mut<S: Scope>(&mut self) -> &mut S;
894}
895
896impl<T: Scope> ScopeCast for T {
897  fn cast_ref<S: Scope>(&self) -> &S {
898    assert_eq!(Layout::new::<Self>(), Layout::new::<S>());
899    unsafe { &*(self as *const _ as *const S) }
900  }
901
902  fn cast_mut<S: Scope>(&mut self) -> &mut S {
903    assert_eq!(Layout::new::<Self>(), Layout::new::<S>());
904    unsafe { &mut *(self as *mut _ as *mut S) }
905  }
906}
907
908/// Scopes are typically constructed as the child of another scope. The scope
909/// that is returned from `«Child»Scope::new(parent: &mut «Parent»Scope)` does
910/// not necessarily have type `«Child»Scope`, but rather its type is a merger of
911/// both the the parent and child scope types.
912///
913/// For example: a `ContextScope` created inside `HandleScope<'a, ()>` does not
914/// produce a `ContextScope`, but rather a `HandleScope<'a, Context>`, which
915/// describes a scope that is both a `HandleScope` _and_ a `ContextScope`.
916///
917/// The Traits in the (private) `param` module define which types can be passed
918/// as a parameter to the `«Some»Scope::new()` constructor, and what the
919/// actual, merged scope type will be that `new()` returns for a specific
920/// parameter type.
921mod param {
922  use super::*;
923
924  pub trait NewContextScope<'s>: getter::GetScopeData {
925    type NewScope: Scope;
926  }
927
928  impl<'s, 'p: 's, P: Scope> NewContextScope<'s> for ContextScope<'p, P> {
929    type NewScope = ContextScope<'s, P>;
930  }
931
932  impl<'s, 'p: 's, C> NewContextScope<'s> for HandleScope<'p, C> {
933    type NewScope = ContextScope<'s, HandleScope<'p>>;
934  }
935
936  impl<'s, 'p: 's, 'e: 'p, C> NewContextScope<'s>
937    for EscapableHandleScope<'p, 'e, C>
938  {
939    type NewScope = ContextScope<'s, EscapableHandleScope<'p, 'e>>;
940  }
941
942  impl<'s, 'p: 's, P: NewContextScope<'s>> NewContextScope<'s>
943    for TryCatch<'p, P>
944  {
945    type NewScope = <P as NewContextScope<'s>>::NewScope;
946  }
947
948  impl<'s, 'p: 's, P: NewContextScope<'s>> NewContextScope<'s>
949    for DisallowJavascriptExecutionScope<'p, P>
950  {
951    type NewScope = <P as NewContextScope<'s>>::NewScope;
952  }
953
954  impl<'s, 'p: 's, P: NewContextScope<'s>> NewContextScope<'s>
955    for AllowJavascriptExecutionScope<'p, P>
956  {
957    type NewScope = <P as NewContextScope<'s>>::NewScope;
958  }
959
960  impl<'s, 'p: 's, C> NewContextScope<'s> for CallbackScope<'p, C> {
961    type NewScope = ContextScope<'s, HandleScope<'p>>;
962  }
963
964  pub trait NewHandleScope<'s>: getter::GetScopeData {
965    type NewScope: Scope;
966  }
967
968  impl<'s> NewHandleScope<'s> for Isolate {
969    type NewScope = HandleScope<'s, ()>;
970  }
971
972  impl<'s> NewHandleScope<'s> for OwnedIsolate {
973    type NewScope = HandleScope<'s, ()>;
974  }
975
976  impl<'s, 'p: 's, P: NewHandleScope<'s>> NewHandleScope<'s>
977    for ContextScope<'p, P>
978  {
979    type NewScope = <P as NewHandleScope<'s>>::NewScope;
980  }
981
982  impl<'s, 'p: 's, C> NewHandleScope<'s> for HandleScope<'p, C> {
983    type NewScope = HandleScope<'s, C>;
984  }
985
986  impl<'s, 'p: 's, 'e: 'p, C> NewHandleScope<'s>
987    for EscapableHandleScope<'p, 'e, C>
988  {
989    type NewScope = EscapableHandleScope<'s, 'e, C>;
990  }
991
992  impl<'s, 'p: 's, P: NewHandleScope<'s>> NewHandleScope<'s> for TryCatch<'p, P> {
993    type NewScope = <P as NewHandleScope<'s>>::NewScope;
994  }
995
996  impl<'s, 'p: 's, P: NewHandleScope<'s>> NewHandleScope<'s>
997    for DisallowJavascriptExecutionScope<'p, P>
998  {
999    type NewScope = <P as NewHandleScope<'s>>::NewScope;
1000  }
1001
1002  impl<'s, 'p: 's, P: NewHandleScope<'s>> NewHandleScope<'s>
1003    for AllowJavascriptExecutionScope<'p, P>
1004  {
1005    type NewScope = <P as NewHandleScope<'s>>::NewScope;
1006  }
1007
1008  impl<'s, 'p: 's, C> NewHandleScope<'s> for CallbackScope<'p, C> {
1009    type NewScope = HandleScope<'s, C>;
1010  }
1011
1012  pub trait NewHandleScopeWithContext<'s>: getter::GetScopeData {
1013    fn get_isolate_mut(&mut self) -> &mut Isolate;
1014  }
1015
1016  impl NewHandleScopeWithContext<'_> for Isolate {
1017    fn get_isolate_mut(&mut self) -> &mut Isolate {
1018      self
1019    }
1020  }
1021
1022  impl NewHandleScopeWithContext<'_> for OwnedIsolate {
1023    fn get_isolate_mut(&mut self) -> &mut Isolate {
1024      &mut *self
1025    }
1026  }
1027
1028  pub trait NewEscapableHandleScope<'s, 'e: 's>: getter::GetScopeData {
1029    type NewScope: Scope;
1030  }
1031
1032  impl<'s, 'p: 's, 'e: 'p, P: NewEscapableHandleScope<'s, 'e>>
1033    NewEscapableHandleScope<'s, 'e> for ContextScope<'p, P>
1034  {
1035    type NewScope = <P as NewEscapableHandleScope<'s, 'e>>::NewScope;
1036  }
1037
1038  impl<'s, 'p: 's, C> NewEscapableHandleScope<'s, 'p> for HandleScope<'p, C> {
1039    type NewScope = EscapableHandleScope<'s, 'p, C>;
1040  }
1041
1042  impl<'s, 'p: 's, 'e: 'p, C> NewEscapableHandleScope<'s, 'p>
1043    for EscapableHandleScope<'p, 'e, C>
1044  {
1045    type NewScope = EscapableHandleScope<'s, 'p, C>;
1046  }
1047
1048  impl<'s, 'p: 's, 'e: 'p, P: NewEscapableHandleScope<'s, 'e>>
1049    NewEscapableHandleScope<'s, 'e> for TryCatch<'p, P>
1050  {
1051    type NewScope = <P as NewEscapableHandleScope<'s, 'e>>::NewScope;
1052  }
1053
1054  impl<'s, 'p: 's, 'e: 'p, P: NewEscapableHandleScope<'s, 'e>>
1055    NewEscapableHandleScope<'s, 'e>
1056    for DisallowJavascriptExecutionScope<'p, P>
1057  {
1058    type NewScope = <P as NewEscapableHandleScope<'s, 'e>>::NewScope;
1059  }
1060
1061  impl<'s, 'p: 's, 'e: 'p, P: NewEscapableHandleScope<'s, 'e>>
1062    NewEscapableHandleScope<'s, 'e> for AllowJavascriptExecutionScope<'p, P>
1063  {
1064    type NewScope = <P as NewEscapableHandleScope<'s, 'e>>::NewScope;
1065  }
1066
1067  impl<'s, 'p: 's, C> NewEscapableHandleScope<'s, 'p> for CallbackScope<'p, C> {
1068    type NewScope = EscapableHandleScope<'s, 'p, C>;
1069  }
1070
1071  pub trait NewTryCatch<'s>: getter::GetScopeData {
1072    type NewScope: Scope;
1073  }
1074
1075  impl<'s, 'p: 's, P: NewTryCatch<'s>> NewTryCatch<'s> for ContextScope<'p, P> {
1076    type NewScope = <P as NewTryCatch<'s>>::NewScope;
1077  }
1078
1079  impl<'s, 'p: 's, C> NewTryCatch<'s> for HandleScope<'p, C> {
1080    type NewScope = TryCatch<'s, HandleScope<'p, C>>;
1081  }
1082
1083  impl<'s, 'p: 's, 'e: 'p, C> NewTryCatch<'s>
1084    for EscapableHandleScope<'p, 'e, C>
1085  {
1086    type NewScope = TryCatch<'s, EscapableHandleScope<'p, 'e, C>>;
1087  }
1088
1089  impl<'s, 'p: 's, P> NewTryCatch<'s> for TryCatch<'p, P> {
1090    type NewScope = TryCatch<'s, P>;
1091  }
1092
1093  impl<'s, 'p: 's, P> NewTryCatch<'s>
1094    for DisallowJavascriptExecutionScope<'p, P>
1095  {
1096    type NewScope = TryCatch<'s, P>;
1097  }
1098
1099  impl<'s, 'p: 's, P> NewTryCatch<'s> for AllowJavascriptExecutionScope<'p, P> {
1100    type NewScope = TryCatch<'s, P>;
1101  }
1102
1103  impl<'s, 'p: 's, C> NewTryCatch<'s> for CallbackScope<'p, C> {
1104    type NewScope = TryCatch<'s, HandleScope<'p, C>>;
1105  }
1106
1107  pub trait NewDisallowJavascriptExecutionScope<'s>:
1108    getter::GetScopeData
1109  {
1110    type NewScope: Scope;
1111  }
1112
1113  impl<'s, 'p: 's, P: NewDisallowJavascriptExecutionScope<'s>>
1114    NewDisallowJavascriptExecutionScope<'s> for ContextScope<'p, P>
1115  {
1116    type NewScope = <P as NewDisallowJavascriptExecutionScope<'s>>::NewScope;
1117  }
1118
1119  impl<'s, 'p: 's, C> NewDisallowJavascriptExecutionScope<'s>
1120    for HandleScope<'p, C>
1121  {
1122    type NewScope = DisallowJavascriptExecutionScope<'s, HandleScope<'p, C>>;
1123  }
1124
1125  impl<'s, 'p: 's, 'e: 'p, C> NewDisallowJavascriptExecutionScope<'s>
1126    for EscapableHandleScope<'p, 'e, C>
1127  {
1128    type NewScope =
1129      DisallowJavascriptExecutionScope<'s, EscapableHandleScope<'p, 'e, C>>;
1130  }
1131
1132  impl<'s, 'p: 's, P> NewDisallowJavascriptExecutionScope<'s>
1133    for TryCatch<'p, P>
1134  {
1135    type NewScope = DisallowJavascriptExecutionScope<'s, TryCatch<'p, P>>;
1136  }
1137
1138  impl<'s, 'p: 's, P> NewDisallowJavascriptExecutionScope<'s>
1139    for DisallowJavascriptExecutionScope<'p, P>
1140  {
1141    type NewScope = DisallowJavascriptExecutionScope<'s, P>;
1142  }
1143
1144  impl<'s, 'p: 's, P> NewDisallowJavascriptExecutionScope<'s>
1145    for AllowJavascriptExecutionScope<'p, P>
1146  {
1147    type NewScope = DisallowJavascriptExecutionScope<'s, P>;
1148  }
1149
1150  pub trait NewAllowJavascriptExecutionScope<'s>: getter::GetScopeData {
1151    type NewScope: Scope;
1152  }
1153
1154  impl<'s, 'p: 's, P: NewAllowJavascriptExecutionScope<'s>>
1155    NewAllowJavascriptExecutionScope<'s> for ContextScope<'p, P>
1156  {
1157    type NewScope = <P as NewAllowJavascriptExecutionScope<'s>>::NewScope;
1158  }
1159
1160  impl<'s, 'p: 's, C> NewAllowJavascriptExecutionScope<'s>
1161    for HandleScope<'p, C>
1162  {
1163    type NewScope = HandleScope<'p, C>;
1164  }
1165
1166  impl<'s, 'p: 's, 'e: 'p, C> NewAllowJavascriptExecutionScope<'s>
1167    for EscapableHandleScope<'p, 'e, C>
1168  {
1169    type NewScope = EscapableHandleScope<'p, 'e, C>;
1170  }
1171
1172  impl<'s, 'p: 's, P> NewAllowJavascriptExecutionScope<'s> for TryCatch<'p, P> {
1173    type NewScope = TryCatch<'s, P>;
1174  }
1175
1176  impl<'s, 'p: 's, P: Scope> NewAllowJavascriptExecutionScope<'s>
1177    for DisallowJavascriptExecutionScope<'p, P>
1178  {
1179    type NewScope = P;
1180  }
1181
1182  impl<'s, 'p: 's, P> NewAllowJavascriptExecutionScope<'s>
1183    for AllowJavascriptExecutionScope<'p, P>
1184  {
1185    type NewScope = AllowJavascriptExecutionScope<'s, P>;
1186  }
1187
1188  pub trait NewCallbackScope<'s>: Sized + getter::GetIsolate<'s> {
1189    type NewScope: Scope;
1190    const NEEDS_SCOPE: bool = false;
1191
1192    fn get_context(&self) -> Option<Local<'s, Context>> {
1193      None
1194    }
1195  }
1196
1197  impl<'s> NewCallbackScope<'s> for &'s mut Isolate {
1198    type NewScope = CallbackScope<'s, ()>;
1199  }
1200
1201  impl<'s> NewCallbackScope<'s> for &'s mut OwnedIsolate {
1202    type NewScope = CallbackScope<'s, ()>;
1203  }
1204
1205  impl<'s> NewCallbackScope<'s> for &'s FunctionCallbackInfo {
1206    type NewScope = CallbackScope<'s>;
1207  }
1208
1209  impl<'s, T> NewCallbackScope<'s> for &'s PropertyCallbackInfo<T> {
1210    type NewScope = CallbackScope<'s>;
1211  }
1212
1213  impl<'s> NewCallbackScope<'s> for &'s FastApiCallbackOptions<'s> {
1214    type NewScope = CallbackScope<'s>;
1215    const NEEDS_SCOPE: bool = true;
1216  }
1217
1218  impl<'s> NewCallbackScope<'s> for Local<'s, Context> {
1219    type NewScope = CallbackScope<'s>;
1220
1221    fn get_context(&self) -> Option<Local<'s, Context>> {
1222      Some(*self)
1223    }
1224  }
1225
1226  impl<'s> NewCallbackScope<'s> for Local<'s, Message> {
1227    type NewScope = CallbackScope<'s>;
1228  }
1229
1230  impl<'s, T: Into<Local<'s, Object>>> NewCallbackScope<'s> for T {
1231    type NewScope = CallbackScope<'s>;
1232  }
1233
1234  impl<'s> NewCallbackScope<'s> for &'s PromiseRejectMessage<'s> {
1235    type NewScope = CallbackScope<'s>;
1236  }
1237}
1238
1239/// The private `getter` module defines traits to look up the related `Isolate`
1240/// and `ScopeData` for many different types. The implementation of those traits
1241/// on the types that implement them are also all contained in this module.
1242mod getter {
1243  pub use super::*;
1244
1245  pub trait GetIsolate<'s> {
1246    unsafe fn get_isolate_mut(self) -> &'s mut Isolate;
1247  }
1248
1249  impl<'s> GetIsolate<'s> for &'s mut Isolate {
1250    unsafe fn get_isolate_mut(self) -> &'s mut Isolate {
1251      self
1252    }
1253  }
1254
1255  impl<'s> GetIsolate<'s> for &'s mut OwnedIsolate {
1256    unsafe fn get_isolate_mut(self) -> &'s mut Isolate {
1257      &mut *self
1258    }
1259  }
1260
1261  impl<'s> GetIsolate<'s> for &'s FunctionCallbackInfo {
1262    unsafe fn get_isolate_mut(self) -> &'s mut Isolate {
1263      unsafe { &mut *self.get_isolate_ptr() }
1264    }
1265  }
1266
1267  impl<'s, T> GetIsolate<'s> for &'s PropertyCallbackInfo<T> {
1268    unsafe fn get_isolate_mut(self) -> &'s mut Isolate {
1269      unsafe { &mut *self.get_isolate_ptr() }
1270    }
1271  }
1272
1273  impl<'s> GetIsolate<'s> for &'s FastApiCallbackOptions<'s> {
1274    unsafe fn get_isolate_mut(self) -> &'s mut Isolate {
1275      unsafe { &mut *self.isolate }
1276    }
1277  }
1278
1279  impl<'s> GetIsolate<'s> for Local<'s, Context> {
1280    unsafe fn get_isolate_mut(self) -> &'s mut Isolate {
1281      unsafe { &mut *raw::v8__Context__GetIsolate(&*self) }
1282    }
1283  }
1284
1285  impl<'s> GetIsolate<'s> for Local<'s, Message> {
1286    unsafe fn get_isolate_mut(self) -> &'s mut Isolate {
1287      unsafe { &mut *raw::v8__Message__GetIsolate(&*self) }
1288    }
1289  }
1290
1291  impl<'s, T: Into<Local<'s, Object>>> GetIsolate<'s> for T {
1292    unsafe fn get_isolate_mut(self) -> &'s mut Isolate {
1293      let object: Local<Object> = self.into();
1294      unsafe { &mut *raw::v8__Object__GetIsolate(&*object) }
1295    }
1296  }
1297
1298  impl<'s> GetIsolate<'s> for &'s PromiseRejectMessage<'s> {
1299    unsafe fn get_isolate_mut(self) -> &'s mut Isolate {
1300      let object: Local<Object> = self.get_promise().into();
1301      unsafe { &mut *raw::v8__Object__GetIsolate(&*object) }
1302    }
1303  }
1304
1305  pub trait GetScopeData {
1306    fn get_scope_data_mut(&mut self) -> &mut data::ScopeData;
1307  }
1308
1309  impl<T: Scope> GetScopeData for T {
1310    fn get_scope_data_mut(&mut self) -> &mut data::ScopeData {
1311      data::ScopeData::get_mut(self)
1312    }
1313  }
1314
1315  impl GetScopeData for Isolate {
1316    fn get_scope_data_mut(&mut self) -> &mut data::ScopeData {
1317      data::ScopeData::get_root_mut(self)
1318    }
1319  }
1320
1321  impl GetScopeData for OwnedIsolate {
1322    fn get_scope_data_mut(&mut self) -> &mut data::ScopeData {
1323      data::ScopeData::get_root_mut(self)
1324    }
1325  }
1326}
1327
1328/// All publicly exported `«Some»Scope` types are essentially wrapping a pointer
1329/// to a heap-allocated struct `ScopeData`. This module contains the definition
1330/// for `ScopeData` and its inner types, as well as related helper traits.
1331pub(crate) mod data {
1332  use super::*;
1333
1334  #[derive(Debug)]
1335  pub struct ScopeData {
1336    // The first four fields are always valid - even when the `Box<ScopeData>`
1337    // struct is free (does not contain data related to an actual scope).
1338    // The `previous` and `isolate` fields never change; the `next` field is
1339    // set to `None` initially when the struct is created, but it may later be
1340    // assigned a `Some(Box<ScopeData>)` value, after which this field never
1341    // changes again.
1342    isolate: NonNull<Isolate>,
1343    previous: Option<NonNull<ScopeData>>,
1344    next: Option<Box<ScopeData>>,
1345    // The 'status' field is also always valid (but does change).
1346    status: Cell<ScopeStatus>,
1347    // The following fields are only valid when this ScopeData object is in use
1348    // (eiter current or shadowed -- not free).
1349    context: Cell<Option<NonNull<Context>>>,
1350    escape_slot: Option<NonNull<Option<raw::EscapeSlot>>>,
1351    try_catch: Option<NonNull<raw::TryCatch>>,
1352    scope_type_specific_data: ScopeTypeSpecificData,
1353  }
1354
1355  impl ScopeData {
1356    /// Returns a mutable reference to the data associated with topmost scope
1357    /// on the scope stack. This function does not automatically exit zombie
1358    /// scopes, so it might return a zombie ScopeData reference.
1359    #[inline(always)]
1360    pub(crate) fn get_current_mut(isolate: &mut Isolate) -> &mut Self {
1361      let self_mut = isolate
1362        .get_current_scope_data()
1363        .map(NonNull::as_ptr)
1364        .map(|p| unsafe { &mut *p })
1365        .unwrap();
1366      match self_mut.status.get() {
1367        ScopeStatus::Current { .. } => self_mut,
1368        _ => unreachable!(),
1369      }
1370    }
1371
1372    /// Initializes the scope stack by creating a 'dummy' `ScopeData` at the
1373    /// very bottom. This makes it possible to store the freelist of reusable
1374    /// ScopeData objects even when no scope is entered.
1375    pub(crate) fn new_root(isolate: &mut Isolate) {
1376      let root = Box::leak(Self::boxed(isolate.into()));
1377      root.status = ScopeStatus::Current { zombie: false }.into();
1378      debug_assert!(isolate.get_current_scope_data().is_none());
1379      isolate.set_current_scope_data(Some(root.into()));
1380    }
1381
1382    /// Activates and returns the 'root' `ScopeData` object that is created when
1383    /// the isolate is initialized. In order to do so, any zombie scopes that
1384    /// remain on the scope stack are cleaned up.
1385    ///
1386    /// # Panics
1387    ///
1388    /// This function panics if the root can't be activated because there are
1389    /// still other scopes on the stack and they're not zombies.
1390    #[inline(always)]
1391    pub(crate) fn get_root_mut(isolate: &mut Isolate) -> &mut Self {
1392      let mut current_scope_data = Self::get_current_mut(isolate);
1393      loop {
1394        current_scope_data = match current_scope_data {
1395          root if root.previous.is_none() => break root,
1396          data => data.try_exit_scope(),
1397        };
1398      }
1399    }
1400
1401    /// Drops the scope stack and releases all `Box<ScopeData>` allocations.
1402    /// This function should be called only when an Isolate is being disposed.
1403    pub(crate) fn drop_root(isolate: &mut Isolate) {
1404      let root = Self::get_root_mut(isolate);
1405      unsafe {
1406        let _ = Box::from_raw(root);
1407      };
1408      isolate.set_current_scope_data(None);
1409    }
1410
1411    #[inline(always)]
1412    pub(super) fn new_context_scope_data<'s>(
1413      &'s mut self,
1414      context: Local<'s, Context>,
1415    ) -> &'s mut Self {
1416      self.new_scope_data_with(move |data| {
1417        data.scope_type_specific_data.init_with(|| {
1418          ScopeTypeSpecificData::ContextScope {
1419            _raw_context_scope: raw::ContextScope::new(context),
1420          }
1421        });
1422        data.context.set(Some(context.as_non_null()));
1423      })
1424    }
1425
1426    /// Implementation helper function, which creates the raw `HandleScope`, but
1427    /// defers (maybe) entering a context to the provided callback argument.
1428    /// This function gets called by `Self::new_handle_scope_data()` and
1429    /// `Self::new_handle_scope_data_with_context()`.
1430    #[inline(always)]
1431    fn new_handle_scope_data_with<F>(&mut self, init_context_fn: F) -> &mut Self
1432    where
1433      F: FnOnce(
1434        NonNull<Isolate>,
1435        &mut Cell<Option<NonNull<Context>>>,
1436        &mut Option<raw::ContextScope>,
1437      ),
1438    {
1439      self.new_scope_data_with(|data| {
1440        let isolate = data.isolate;
1441        data.scope_type_specific_data.init_with(|| {
1442          ScopeTypeSpecificData::HandleScope {
1443            allow_zombie: true,
1444            raw_handle_scope: unsafe { raw::HandleScope::uninit() },
1445            raw_context_scope: None,
1446          }
1447        });
1448        match &mut data.scope_type_specific_data {
1449          ScopeTypeSpecificData::HandleScope {
1450            raw_handle_scope,
1451            raw_context_scope,
1452            ..
1453          } => {
1454            unsafe { raw_handle_scope.init(isolate) };
1455            init_context_fn(isolate, &mut data.context, raw_context_scope);
1456          }
1457          _ => unreachable!(),
1458        };
1459      })
1460    }
1461
1462    #[inline(always)]
1463    pub(super) fn disable_zombie(&mut self) {
1464      if let ScopeTypeSpecificData::HandleScope { allow_zombie, .. } =
1465        &mut self.scope_type_specific_data
1466      {
1467        *allow_zombie = false;
1468      }
1469    }
1470
1471    #[inline(always)]
1472    pub(super) fn new_handle_scope_data(&mut self) -> &mut Self {
1473      self.new_handle_scope_data_with(|_, _, raw_context_scope| {
1474        debug_assert!(raw_context_scope.is_none());
1475      })
1476    }
1477
1478    #[inline(always)]
1479    pub(super) fn new_handle_scope_data_with_context(
1480      &mut self,
1481      context_ref: &Context,
1482    ) -> &mut Self {
1483      self.new_handle_scope_data_with(
1484        move |isolate, context_data, raw_context_scope| unsafe {
1485          let context_nn = NonNull::from(context_ref);
1486          // Copy the `Context` reference to a new local handle to enure that it
1487          // cannot get garbage collected until after this scope is dropped.
1488          let local_context_ptr =
1489            raw::v8__Local__New(isolate.as_ptr(), context_nn.cast().as_ptr())
1490              as *const Context;
1491          let local_context_nn =
1492            NonNull::new_unchecked(local_context_ptr as *mut _);
1493          let local_context = Local::from_non_null(local_context_nn);
1494          // Initialize the `raw::ContextScope`. This enters the context too.
1495          debug_assert!(raw_context_scope.is_none());
1496          ptr::write(
1497            raw_context_scope,
1498            Some(raw::ContextScope::new(local_context)),
1499          );
1500          // Also store the newly created `Local<Context>` in the `Cell` that
1501          // serves as a look-up cache for the current context.
1502          context_data.set(Some(local_context_nn));
1503        },
1504      )
1505    }
1506
1507    #[inline(always)]
1508    pub(super) fn new_escapable_handle_scope_data(&mut self) -> &mut Self {
1509      self.new_scope_data_with(|data| {
1510        // Note: the `raw_escape_slot` field must be initialized _before_ the
1511        // `raw_handle_scope` field, otherwise the escaped local handle ends up
1512        // inside the `EscapableHandleScope` that's being constructed here,
1513        // rather than escaping from it.
1514        let isolate = data.isolate;
1515        data.scope_type_specific_data.init_with(|| {
1516          ScopeTypeSpecificData::EscapableHandleScope {
1517            raw_handle_scope: unsafe { raw::HandleScope::uninit() },
1518            raw_escape_slot: Some(raw::EscapeSlot::new(isolate)),
1519          }
1520        });
1521        match &mut data.scope_type_specific_data {
1522          ScopeTypeSpecificData::EscapableHandleScope {
1523            raw_handle_scope,
1524            raw_escape_slot,
1525          } => {
1526            unsafe { raw_handle_scope.init(isolate) };
1527            data.escape_slot.replace(raw_escape_slot.into());
1528          }
1529          _ => unreachable!(),
1530        }
1531      })
1532    }
1533
1534    #[inline(always)]
1535    pub(super) fn new_try_catch_data(&mut self) -> &mut Self {
1536      self.new_scope_data_with(|data| {
1537        let isolate = data.isolate;
1538        data.scope_type_specific_data.init_with(|| {
1539          ScopeTypeSpecificData::TryCatch {
1540            raw_try_catch: unsafe { raw::TryCatch::uninit() },
1541          }
1542        });
1543        match &mut data.scope_type_specific_data {
1544          ScopeTypeSpecificData::TryCatch { raw_try_catch } => {
1545            unsafe { raw_try_catch.init(isolate) };
1546            data.try_catch.replace(raw_try_catch.into());
1547          }
1548          _ => unreachable!(),
1549        }
1550      })
1551    }
1552
1553    #[inline(always)]
1554    pub(super) fn new_disallow_javascript_execution_scope_data(
1555      &mut self,
1556      on_failure: OnFailure,
1557    ) -> &mut Self {
1558      self.new_scope_data_with(|data| {
1559        let isolate = data.isolate;
1560        data.scope_type_specific_data.init_with(|| {
1561          ScopeTypeSpecificData::DisallowJavascriptExecutionScope {
1562            raw_scope: unsafe {
1563              raw::DisallowJavascriptExecutionScope::uninit()
1564            },
1565          }
1566        });
1567        match &mut data.scope_type_specific_data {
1568          ScopeTypeSpecificData::DisallowJavascriptExecutionScope {
1569            raw_scope,
1570          } => unsafe { raw_scope.init(isolate, on_failure) },
1571          _ => unreachable!(),
1572        }
1573      })
1574    }
1575
1576    #[inline(always)]
1577    pub(super) fn new_allow_javascript_execution_scope_data(
1578      &mut self,
1579    ) -> &mut Self {
1580      self.new_scope_data_with(|data| {
1581        let isolate = data.isolate;
1582        data.scope_type_specific_data.init_with(|| {
1583          ScopeTypeSpecificData::AllowJavascriptExecutionScope {
1584            raw_scope: unsafe { raw::AllowJavascriptExecutionScope::uninit() },
1585          }
1586        });
1587        match &mut data.scope_type_specific_data {
1588          ScopeTypeSpecificData::AllowJavascriptExecutionScope {
1589            raw_scope,
1590          } => unsafe { raw_scope.init(isolate) },
1591          _ => unreachable!(),
1592        }
1593      })
1594    }
1595
1596    #[inline(always)]
1597    pub(super) fn new_callback_scope_data<'s>(
1598      &'s mut self,
1599      maybe_current_context: Option<Local<'s, Context>>,
1600    ) -> &'s mut Self {
1601      self.new_scope_data_with(|data| {
1602        debug_assert!(data.scope_type_specific_data.is_none());
1603        data
1604          .context
1605          .set(maybe_current_context.map(|cx| cx.as_non_null()));
1606      })
1607    }
1608
1609    #[inline(always)]
1610    fn new_scope_data_with(
1611      &mut self,
1612      init_fn: impl FnOnce(&mut Self),
1613    ) -> &mut Self {
1614      // Mark this scope (the parent of the newly created scope) as 'shadowed';
1615      self.status.set(match self.status.get() {
1616        ScopeStatus::Current { zombie } => ScopeStatus::Shadowed { zombie },
1617        _ => unreachable!(),
1618      });
1619      // Copy fields that that will be inherited by the new scope.
1620      let context = self.context.get().into();
1621      let escape_slot = self.escape_slot;
1622      // Initialize the `struct ScopeData` for the new scope.
1623      let new_scope_data = self.allocate_or_reuse_scope_data();
1624      // In debug builds, `zombie` is initially set to `true`, and the flag is
1625      // later cleared in the `as_scope()` method, to verify that we're
1626      // always creating exactly one scope from any `ScopeData` object.
1627      // For performance reasons this check is not performed in release builds.
1628      new_scope_data.status = Cell::new(ScopeStatus::Current {
1629        zombie: cfg!(debug_assertions),
1630      });
1631      // Store fields inherited from the parent scope.
1632      new_scope_data.context = context;
1633      new_scope_data.escape_slot = escape_slot;
1634      (init_fn)(new_scope_data);
1635      // Make the newly created scope the 'current' scope for this isolate.
1636      let new_scope_nn = unsafe { NonNull::new_unchecked(new_scope_data) };
1637      new_scope_data
1638        .get_isolate_mut()
1639        .set_current_scope_data(Some(new_scope_nn));
1640      new_scope_data
1641    }
1642
1643    /// Either returns an free `Box<ScopeData>` that is available for reuse,
1644    /// or allocates a new one on the heap.
1645    #[inline(always)]
1646    fn allocate_or_reuse_scope_data(&mut self) -> &mut Self {
1647      let self_nn = NonNull::new(self);
1648      match &mut self.next {
1649        Some(next_box) => {
1650          // Reuse a free `Box<ScopeData>` allocation.
1651          debug_assert_eq!(next_box.isolate, self.isolate);
1652          debug_assert_eq!(next_box.previous, self_nn);
1653          debug_assert_eq!(next_box.status.get(), ScopeStatus::Free);
1654          debug_assert!(next_box.scope_type_specific_data.is_none());
1655          next_box.as_mut()
1656        }
1657        next_field @ None => {
1658          // Allocate a new `Box<ScopeData>`.
1659          let mut next_box = Self::boxed(self.isolate);
1660          next_box.previous = self_nn;
1661          next_field.replace(next_box);
1662          next_field.as_mut().unwrap()
1663        }
1664      }
1665    }
1666
1667    #[inline(always)]
1668    pub(super) fn as_scope<S: Scope>(&mut self) -> S {
1669      assert_eq!(Layout::new::<&mut Self>(), Layout::new::<S>());
1670      // In debug builds, a new initialized `ScopeStatus` will have the `zombie`
1671      // flag set, so we have to reset it. In release builds, new `ScopeStatus`
1672      // objects come with the `zombie` flag cleared, so no update is necessary.
1673      if cfg!(debug_assertions) {
1674        assert_eq!(self.status.get(), ScopeStatus::Current { zombie: true });
1675        self.status.set(ScopeStatus::Current { zombie: false });
1676      }
1677      let self_nn = NonNull::from(self);
1678      unsafe { ptr::read(&self_nn as *const _ as *const S) }
1679    }
1680
1681    #[inline(always)]
1682    pub(super) fn get<S: Scope>(scope: &S) -> &Self {
1683      let self_mut = unsafe {
1684        (*(scope as *const S as *mut S as *mut NonNull<Self>)).as_mut()
1685      };
1686      self_mut.try_activate_scope();
1687      self_mut
1688    }
1689
1690    #[inline(always)]
1691    pub(super) fn get_mut<S: Scope>(scope: &mut S) -> &mut Self {
1692      let self_mut =
1693        unsafe { (*(scope as *mut S as *mut NonNull<Self>)).as_mut() };
1694      self_mut.try_activate_scope();
1695      self_mut
1696    }
1697
1698    #[inline(always)]
1699    fn try_activate_scope(mut self: &mut Self) -> &mut Self {
1700      self = match self.status.get() {
1701        ScopeStatus::Current { zombie: false } => self,
1702        ScopeStatus::Shadowed { zombie: false } => {
1703          self.next.as_mut().unwrap().try_exit_scope()
1704        }
1705        _ => unreachable!(),
1706      };
1707      debug_assert_eq!(
1708        self.get_isolate().get_current_scope_data(),
1709        NonNull::new(self as *mut _)
1710      );
1711      self
1712    }
1713
1714    #[inline(always)]
1715    fn try_exit_scope(mut self: &mut Self) -> &mut Self {
1716      loop {
1717        self = match self.status.get() {
1718          ScopeStatus::Shadowed { .. } => {
1719            self.next.as_mut().unwrap().try_exit_scope()
1720          }
1721          ScopeStatus::Current { zombie: true } => break self.exit_scope(),
1722          ScopeStatus::Current { zombie: false } => {
1723            panic!("active scope can't be dropped")
1724          }
1725          _ => unreachable!(),
1726        }
1727      }
1728    }
1729
1730    #[inline(always)]
1731    fn exit_scope(&mut self) -> &mut Self {
1732      // Clear out the scope type specific data field. None of the other fields
1733      // have a destructor, and there's no need to do any cleanup on them.
1734      if !matches!(self.scope_type_specific_data, ScopeTypeSpecificData::None) {
1735        self.scope_type_specific_data = Default::default();
1736      }
1737
1738      // Change the ScopeData's status field from 'Current' to 'Free', which
1739      // means that it is not associated with a scope and can be reused.
1740      self.status.set(ScopeStatus::Free);
1741
1742      // Point the Isolate's current scope data slot at our parent scope.
1743      let previous_nn = self.previous.unwrap();
1744      self
1745        .get_isolate_mut()
1746        .set_current_scope_data(Some(previous_nn));
1747
1748      // Update the parent scope's status field to reflect that it is now
1749      // 'Current' again an no longer 'Shadowed'.
1750      let previous_mut = unsafe { &mut *previous_nn.as_ptr() };
1751      previous_mut.status.set(match previous_mut.status.get() {
1752        ScopeStatus::Shadowed { zombie } => ScopeStatus::Current { zombie },
1753        _ => unreachable!(),
1754      });
1755
1756      previous_mut
1757    }
1758
1759    /// This function is called when any of the public scope objects (e.g
1760    /// `HandleScope`, `ContextScope`, etc.) are dropped.
1761    ///
1762    /// The Rust borrow checker allows values of type `HandleScope<'a>` and
1763    /// `EscapableHandleScope<'a, 'e>` to be dropped before their maximum
1764    /// lifetime ('a) is up. This creates a potential problem because any local
1765    /// handles that are created while these scopes are active are bound to
1766    /// that 'a lifetime. This means that we run the risk of creating local
1767    /// handles that outlive their creation scope.
1768    ///
1769    /// Therefore, we don't immediately exit the current scope at the very
1770    /// moment the user drops their Escapable/HandleScope handle.
1771    /// Instead, the current scope is marked as being a 'zombie': the scope
1772    /// itself is gone, but its data still on the stack. The zombie's data will
1773    /// be dropped when the user touches the parent scope; when that happens, it
1774    /// is certain that there are no accessible `Local<'a, T>` handles left,
1775    /// because the 'a lifetime ends there.
1776    ///
1777    /// Scope types that do no store local handles are exited immediately.
1778    #[inline(always)]
1779    pub(super) fn notify_scope_dropped(&mut self) {
1780      match &self.scope_type_specific_data {
1781        ScopeTypeSpecificData::HandleScope {
1782          allow_zombie: true, ..
1783        }
1784        | ScopeTypeSpecificData::EscapableHandleScope { .. } => {
1785          // Defer scope exit until the parent scope is touched.
1786          self.status.set(match self.status.get() {
1787            ScopeStatus::Current { zombie: false } => {
1788              ScopeStatus::Current { zombie: true }
1789            }
1790            _ => unreachable!(),
1791          });
1792        }
1793        _ => {
1794          // Regular, immediate exit.
1795          self.exit_scope();
1796        }
1797      }
1798    }
1799
1800    #[inline(always)]
1801    pub(crate) fn get_isolate(&self) -> &Isolate {
1802      unsafe { self.isolate.as_ref() }
1803    }
1804
1805    #[inline(always)]
1806    pub(crate) fn get_isolate_mut(&mut self) -> &mut Isolate {
1807      unsafe { self.isolate.as_mut() }
1808    }
1809
1810    #[inline(always)]
1811    pub(crate) fn get_isolate_ptr(&self) -> *mut Isolate {
1812      self.isolate.as_ptr()
1813    }
1814
1815    #[inline(always)]
1816    pub(crate) fn get_current_context(&self) -> *const Context {
1817      // To avoid creating a new Local every time `get_current_context() is
1818      // called, the current context is usually cached in the `context` field.
1819      // If the `context` field contains `None`, this might mean that this cache
1820      // field never got populated, so we'll do that here when necessary.
1821      let get_current_context_from_isolate = || unsafe {
1822        raw::v8__Isolate__GetCurrentContext(self.get_isolate_ptr())
1823      };
1824      match self.context.get().map(|nn| nn.as_ptr() as *const _) {
1825        Some(context) => {
1826          debug_assert!(unsafe {
1827            raw::v8__Context__EQ(context, get_current_context_from_isolate())
1828          });
1829          context
1830        }
1831        None => {
1832          let context = get_current_context_from_isolate();
1833          self.context.set(NonNull::new(context as *mut _));
1834          context
1835        }
1836      }
1837    }
1838
1839    #[inline(always)]
1840    pub(super) fn get_escape_slot_mut(
1841      &mut self,
1842    ) -> Option<&mut Option<raw::EscapeSlot>> {
1843      self
1844        .escape_slot
1845        .as_mut()
1846        .map(|escape_slot_nn| unsafe { escape_slot_nn.as_mut() })
1847    }
1848
1849    #[inline(always)]
1850    pub(super) fn get_try_catch(&self) -> &raw::TryCatch {
1851      self
1852        .try_catch
1853        .as_ref()
1854        .map(|try_catch_nn| unsafe { try_catch_nn.as_ref() })
1855        .unwrap()
1856    }
1857
1858    #[inline(always)]
1859    pub(super) fn get_try_catch_mut(&mut self) -> &mut raw::TryCatch {
1860      self
1861        .try_catch
1862        .as_mut()
1863        .map(|try_catch_nn| unsafe { try_catch_nn.as_mut() })
1864        .unwrap()
1865    }
1866
1867    /// Returns a new `Box<ScopeData>` with the `isolate` field set as specified
1868    /// by the first parameter, and the other fields initialized to their
1869    /// default values. This function exists solely because it turns out that
1870    /// Rust doesn't optimize `Box::new(Self{ .. })` very well (a.k.a. not at
1871    /// all) in this case, which is why `std::alloc::alloc()` is used directly.
1872    #[cold]
1873    fn boxed(isolate: NonNull<Isolate>) -> Box<Self> {
1874      unsafe {
1875        #[allow(clippy::cast_ptr_alignment)]
1876        let self_ptr = alloc(Layout::new::<Self>()) as *mut Self;
1877        ptr::write(
1878          self_ptr,
1879          Self {
1880            isolate,
1881            previous: Default::default(),
1882            next: Default::default(),
1883            status: Default::default(),
1884            context: Default::default(),
1885            escape_slot: Default::default(),
1886            try_catch: Default::default(),
1887            scope_type_specific_data: Default::default(),
1888          },
1889        );
1890        Box::from_raw(self_ptr)
1891      }
1892    }
1893  }
1894
1895  #[derive(Debug, Clone, Copy, Eq, PartialEq)]
1896  enum ScopeStatus {
1897    Free,
1898    Current { zombie: bool },
1899    Shadowed { zombie: bool },
1900  }
1901
1902  impl Default for ScopeStatus {
1903    fn default() -> Self {
1904      Self::Free
1905    }
1906  }
1907
1908  #[derive(Debug)]
1909  enum ScopeTypeSpecificData {
1910    None,
1911    ContextScope {
1912      _raw_context_scope: raw::ContextScope,
1913    },
1914    HandleScope {
1915      allow_zombie: bool,
1916      raw_handle_scope: raw::HandleScope,
1917      raw_context_scope: Option<raw::ContextScope>,
1918    },
1919    EscapableHandleScope {
1920      raw_handle_scope: raw::HandleScope,
1921      raw_escape_slot: Option<raw::EscapeSlot>,
1922    },
1923    TryCatch {
1924      raw_try_catch: raw::TryCatch,
1925    },
1926    DisallowJavascriptExecutionScope {
1927      raw_scope: raw::DisallowJavascriptExecutionScope,
1928    },
1929    AllowJavascriptExecutionScope {
1930      raw_scope: raw::AllowJavascriptExecutionScope,
1931    },
1932  }
1933
1934  impl Default for ScopeTypeSpecificData {
1935    fn default() -> Self {
1936      Self::None
1937    }
1938  }
1939
1940  impl Drop for ScopeTypeSpecificData {
1941    #[inline(always)]
1942    fn drop(&mut self) {
1943      // For `HandleScope`s that also enter a `Context`, drop order matters. The
1944      // context is stored in a `Local` handle, which is allocated in this
1945      // scope's own private `raw::HandleScope`. When that `raw::HandleScope`
1946      // is dropped first, we immediately lose the `Local<Context>` handle,
1947      // which we need in order to exit `ContextScope`.
1948      if let Self::HandleScope {
1949        raw_context_scope, ..
1950      } = self
1951      {
1952        *raw_context_scope = None;
1953      }
1954    }
1955  }
1956
1957  impl ScopeTypeSpecificData {
1958    pub fn is_none(&self) -> bool {
1959      matches!(self, Self::None)
1960    }
1961
1962    /// Replaces a `ScopeTypeSpecificData::None` value with the value returned
1963    /// from the specified closure. This function exists because initializing
1964    /// scopes is performance critical, and `ptr::write()` produces more
1965    /// efficient code than using a regular assign statement, which will try to
1966    /// drop the old value and move the new value into place, even after
1967    /// asserting `self.is_none()`.
1968    pub fn init_with(&mut self, init_fn: impl FnOnce() -> Self) {
1969      assert!(self.is_none());
1970      unsafe { ptr::write(self, (init_fn)()) }
1971    }
1972  }
1973}
1974
1975/// The `raw` module contains prototypes for all the `extern C` functions that
1976/// are used in this file, as well as definitions for the types they operate on.
1977mod raw {
1978  use super::*;
1979
1980  #[derive(Clone, Copy, Debug)]
1981  #[repr(transparent)]
1982  pub(super) struct Address(NonZeroUsize);
1983
1984  #[derive(Debug)]
1985  pub(super) struct ContextScope {
1986    entered_context: NonNull<Context>,
1987  }
1988
1989  impl ContextScope {
1990    pub fn new(context: Local<Context>) -> Self {
1991      unsafe { v8__Context__Enter(&*context) };
1992      Self {
1993        entered_context: context.as_non_null(),
1994      }
1995    }
1996  }
1997
1998  impl Drop for ContextScope {
1999    #[inline(always)]
2000    fn drop(&mut self) {
2001      unsafe { v8__Context__Exit(self.entered_context.as_ptr()) };
2002    }
2003  }
2004
2005  #[repr(C)]
2006  #[derive(Debug)]
2007  pub(super) struct HandleScope([MaybeUninit<usize>; 3]);
2008
2009  impl HandleScope {
2010    /// Creates an uninitialized `HandleScope`.
2011    ///
2012    /// This function is marked unsafe because the caller must ensure that the
2013    /// returned value isn't dropped before `init()` has been called.
2014    pub unsafe fn uninit() -> Self {
2015      Self(unsafe { MaybeUninit::uninit().assume_init() })
2016    }
2017
2018    /// This function is marked unsafe because `init()` must be called exactly
2019    /// once, no more and no less, after creating a `HandleScope` value with
2020    /// `HandleScope::uninit()`.
2021    pub unsafe fn init(&mut self, isolate: NonNull<Isolate>) {
2022      let buf = NonNull::from(self).cast();
2023      unsafe {
2024        v8__HandleScope__CONSTRUCT(buf.as_ptr(), isolate.as_ptr());
2025      }
2026    }
2027  }
2028
2029  impl Drop for HandleScope {
2030    #[inline(always)]
2031    fn drop(&mut self) {
2032      unsafe { v8__HandleScope__DESTRUCT(self) };
2033    }
2034  }
2035
2036  #[repr(transparent)]
2037  #[derive(Debug)]
2038  pub(super) struct EscapeSlot(NonNull<raw::Address>);
2039
2040  impl EscapeSlot {
2041    pub fn new(isolate: NonNull<Isolate>) -> Self {
2042      unsafe {
2043        let undefined = raw::v8__Undefined(isolate.as_ptr()) as *const _;
2044        let local = raw::v8__Local__New(isolate.as_ptr(), undefined);
2045        let slot_address_ptr = local as *const Address as *mut _;
2046        let slot_address_nn = NonNull::new_unchecked(slot_address_ptr);
2047        Self(slot_address_nn)
2048      }
2049    }
2050
2051    pub fn escape<'e, T>(self, value: Local<'_, T>) -> Local<'e, T>
2052    where
2053      for<'l> Local<'l, T>: Into<Local<'l, Data>>,
2054    {
2055      assert_eq!(Layout::new::<Self>(), Layout::new::<Local<T>>());
2056      unsafe {
2057        let undefined = Local::<Value>::from_non_null(self.0.cast());
2058        debug_assert!(undefined.is_undefined());
2059        let value_address = *(&*value as *const T as *const Address);
2060        ptr::write(self.0.as_ptr(), value_address);
2061        Local::from_non_null(self.0.cast())
2062      }
2063    }
2064  }
2065
2066  #[repr(C)]
2067  #[derive(Debug)]
2068  pub(super) struct TryCatch([MaybeUninit<usize>; 6]);
2069
2070  impl TryCatch {
2071    /// Creates an uninitialized `TryCatch`.
2072    ///
2073    /// This function is marked unsafe because the caller must ensure that the
2074    /// returned value isn't dropped before `init()` has been called.
2075    pub unsafe fn uninit() -> Self {
2076      Self(unsafe { MaybeUninit::uninit().assume_init() })
2077    }
2078
2079    /// This function is marked unsafe because `init()` must be called exactly
2080    /// once, no more and no less, after creating a `TryCatch` value with
2081    /// `TryCatch::uninit()`.
2082    pub unsafe fn init(&mut self, isolate: NonNull<Isolate>) {
2083      let buf = NonNull::from(self).cast();
2084      unsafe {
2085        v8__TryCatch__CONSTRUCT(buf.as_ptr(), isolate.as_ptr());
2086      }
2087    }
2088  }
2089
2090  impl Drop for TryCatch {
2091    #[inline(always)]
2092    fn drop(&mut self) {
2093      unsafe { v8__TryCatch__DESTRUCT(self) };
2094    }
2095  }
2096
2097  #[repr(C)]
2098  #[derive(Debug)]
2099  pub(super) struct DisallowJavascriptExecutionScope([MaybeUninit<usize>; 2]);
2100
2101  impl DisallowJavascriptExecutionScope {
2102    /// Creates an uninitialized `DisallowJavascriptExecutionScope`.
2103    ///
2104    /// This function is marked unsafe because the caller must ensure that the
2105    /// returned value isn't dropped before `init()` has been called.
2106    pub unsafe fn uninit() -> Self {
2107      Self(unsafe { MaybeUninit::uninit().assume_init() })
2108    }
2109
2110    /// This function is marked unsafe because `init()` must be called exactly
2111    /// once, no more and no less, after creating a
2112    /// `DisallowJavascriptExecutionScope` value with
2113    /// `DisallowJavascriptExecutionScope::uninit()`.
2114    pub unsafe fn init(
2115      &mut self,
2116      isolate: NonNull<Isolate>,
2117      on_failure: OnFailure,
2118    ) {
2119      let buf = NonNull::from(self).cast();
2120      unsafe {
2121        v8__DisallowJavascriptExecutionScope__CONSTRUCT(
2122          buf.as_ptr(),
2123          isolate.as_ptr(),
2124          on_failure,
2125        );
2126      }
2127    }
2128  }
2129
2130  impl Drop for DisallowJavascriptExecutionScope {
2131    #[inline(always)]
2132    fn drop(&mut self) {
2133      unsafe { v8__DisallowJavascriptExecutionScope__DESTRUCT(self) };
2134    }
2135  }
2136
2137  #[repr(C)]
2138  #[derive(Debug)]
2139  pub(super) struct AllowJavascriptExecutionScope([MaybeUninit<usize>; 2]);
2140
2141  impl AllowJavascriptExecutionScope {
2142    /// Creates an uninitialized `AllowJavascriptExecutionScope`.
2143    ///
2144    /// This function is marked unsafe because the caller must ensure that the
2145    /// returned value isn't dropped before `init()` has been called.
2146    pub unsafe fn uninit() -> Self {
2147      Self(unsafe { MaybeUninit::uninit().assume_init() })
2148    }
2149
2150    /// This function is marked unsafe because `init()` must be called exactly
2151    /// once, no more and no less, after creating an
2152    /// `AllowJavascriptExecutionScope` value with
2153    /// `AllowJavascriptExecutionScope::uninit()`.
2154    pub unsafe fn init(&mut self, isolate: NonNull<Isolate>) {
2155      unsafe {
2156        let buf = NonNull::from(self).cast();
2157        v8__AllowJavascriptExecutionScope__CONSTRUCT(
2158          buf.as_ptr(),
2159          isolate.as_ptr(),
2160        );
2161      }
2162    }
2163  }
2164
2165  impl Drop for AllowJavascriptExecutionScope {
2166    #[inline(always)]
2167    fn drop(&mut self) {
2168      unsafe { v8__AllowJavascriptExecutionScope__DESTRUCT(self) };
2169    }
2170  }
2171
2172  unsafe extern "C" {
2173    pub(super) fn v8__Isolate__GetCurrentContext(
2174      isolate: *mut Isolate,
2175    ) -> *const Context;
2176    pub(super) fn v8__Isolate__GetEnteredOrMicrotaskContext(
2177      isolate: *mut Isolate,
2178    ) -> *const Context;
2179    pub(super) fn v8__Isolate__ThrowException(
2180      isolate: *mut Isolate,
2181      exception: *const Value,
2182    ) -> *const Value;
2183    pub(super) fn v8__Isolate__GetDataFromSnapshotOnce(
2184      this: *mut Isolate,
2185      index: usize,
2186    ) -> *const Data;
2187    pub(super) fn v8__Isolate__GetCurrentHostDefinedOptions(
2188      this: *mut Isolate,
2189    ) -> *const Data;
2190
2191    pub(super) fn v8__Context__EQ(
2192      this: *const Context,
2193      other: *const Context,
2194    ) -> bool;
2195    pub(super) fn v8__Context__Enter(this: *const Context);
2196    pub(super) fn v8__Context__Exit(this: *const Context);
2197    pub(super) fn v8__Context__GetIsolate(this: *const Context)
2198    -> *mut Isolate;
2199    pub(super) fn v8__Context__GetDataFromSnapshotOnce(
2200      this: *const Context,
2201      index: usize,
2202    ) -> *const Data;
2203    pub(super) fn v8__Context__SetPromiseHooks(
2204      this: *const Context,
2205      init_hook: *const Function,
2206      before_hook: *const Function,
2207      after_hook: *const Function,
2208      resolve_hook: *const Function,
2209    );
2210    pub(super) fn v8__Context__SetContinuationPreservedEmbedderData(
2211      this: *mut Isolate,
2212      value: *const Value,
2213    );
2214    pub(super) fn v8__Context__GetContinuationPreservedEmbedderData(
2215      this: *mut Isolate,
2216    ) -> *const Value;
2217
2218    pub(super) fn v8__HandleScope__CONSTRUCT(
2219      buf: *mut MaybeUninit<HandleScope>,
2220      isolate: *mut Isolate,
2221    );
2222    pub(super) fn v8__HandleScope__DESTRUCT(this: *mut HandleScope);
2223
2224    pub(super) fn v8__Local__New(
2225      isolate: *mut Isolate,
2226      other: *const Data,
2227    ) -> *const Data;
2228    pub(super) fn v8__Undefined(isolate: *mut Isolate) -> *const Primitive;
2229
2230    pub(super) fn v8__TryCatch__CONSTRUCT(
2231      buf: *mut MaybeUninit<TryCatch>,
2232      isolate: *mut Isolate,
2233    );
2234    pub(super) fn v8__TryCatch__DESTRUCT(this: *mut TryCatch);
2235    pub(super) fn v8__TryCatch__HasCaught(this: *const TryCatch) -> bool;
2236    pub(super) fn v8__TryCatch__CanContinue(this: *const TryCatch) -> bool;
2237    pub(super) fn v8__TryCatch__HasTerminated(this: *const TryCatch) -> bool;
2238    pub(super) fn v8__TryCatch__IsVerbose(this: *const TryCatch) -> bool;
2239    pub(super) fn v8__TryCatch__SetVerbose(this: *mut TryCatch, value: bool);
2240    pub(super) fn v8__TryCatch__SetCaptureMessage(
2241      this: *mut TryCatch,
2242      value: bool,
2243    );
2244    pub(super) fn v8__TryCatch__Reset(this: *mut TryCatch);
2245    pub(super) fn v8__TryCatch__Exception(
2246      this: *const TryCatch,
2247    ) -> *const Value;
2248    pub(super) fn v8__TryCatch__StackTrace(
2249      this: *const TryCatch,
2250      context: *const Context,
2251    ) -> *const Value;
2252    pub(super) fn v8__TryCatch__Message(
2253      this: *const TryCatch,
2254    ) -> *const Message;
2255    pub(super) fn v8__TryCatch__ReThrow(this: *mut TryCatch) -> *const Value;
2256
2257    pub(super) fn v8__DisallowJavascriptExecutionScope__CONSTRUCT(
2258      buf: *mut MaybeUninit<DisallowJavascriptExecutionScope>,
2259      isolate: *mut Isolate,
2260      on_failure: OnFailure,
2261    );
2262    pub(super) fn v8__DisallowJavascriptExecutionScope__DESTRUCT(
2263      this: *mut DisallowJavascriptExecutionScope,
2264    );
2265
2266    pub(super) fn v8__AllowJavascriptExecutionScope__CONSTRUCT(
2267      buf: *mut MaybeUninit<AllowJavascriptExecutionScope>,
2268      isolate: *mut Isolate,
2269    );
2270    pub(super) fn v8__AllowJavascriptExecutionScope__DESTRUCT(
2271      this: *mut AllowJavascriptExecutionScope,
2272    );
2273
2274    pub(super) fn v8__Message__GetIsolate(this: *const Message)
2275    -> *mut Isolate;
2276    pub(super) fn v8__Object__GetIsolate(this: *const Object) -> *mut Isolate;
2277  }
2278}
2279
2280#[cfg(test)]
2281mod tests {
2282  use super::*;
2283  use crate::ContextOptions;
2284  use crate::Global;
2285  use std::any::type_name;
2286
2287  trait SameType {}
2288  impl<A> SameType for (A, A) {}
2289
2290  /// `AssertTypeOf` facilitates comparing types. The important difference with
2291  /// assigning a value to a variable with an explicitly stated type is that the
2292  /// latter allows coercions and dereferencing to change the type, whereas
2293  /// `AssertTypeOf` requires the compared types to match exactly.
2294  struct AssertTypeOf<'a, T>(#[allow(dead_code)] &'a T);
2295  impl<T> AssertTypeOf<'_, T> {
2296    pub fn is<A>(self)
2297    where
2298      (A, T): SameType,
2299    {
2300      assert_eq!(type_name::<A>(), type_name::<T>());
2301    }
2302  }
2303
2304  #[test]
2305  fn deref_types() {
2306    crate::initialize_v8();
2307    let isolate = &mut Isolate::new(Default::default());
2308    AssertTypeOf(isolate).is::<OwnedIsolate>();
2309    let l1_hs = &mut HandleScope::new(isolate);
2310    AssertTypeOf(l1_hs).is::<HandleScope<()>>();
2311    let context = Context::new(l1_hs, ContextOptions::default());
2312    {
2313      let l2_cxs = &mut ContextScope::new(l1_hs, context);
2314      AssertTypeOf(l2_cxs).is::<ContextScope<HandleScope>>();
2315      {
2316        let d = l2_cxs.deref_mut();
2317        AssertTypeOf(d).is::<HandleScope>();
2318        let d = d.deref_mut();
2319        AssertTypeOf(d).is::<HandleScope<()>>();
2320        let d = d.deref_mut();
2321        AssertTypeOf(d).is::<Isolate>();
2322      }
2323      {
2324        let l3_tc = &mut TryCatch::new(l2_cxs);
2325        AssertTypeOf(l3_tc).is::<TryCatch<HandleScope>>();
2326        let d = l3_tc.deref_mut();
2327        AssertTypeOf(d).is::<HandleScope>();
2328        let d = d.deref_mut();
2329        AssertTypeOf(d).is::<HandleScope<()>>();
2330        let d = d.deref_mut();
2331        AssertTypeOf(d).is::<Isolate>();
2332      }
2333      {
2334        let l3_djses = &mut DisallowJavascriptExecutionScope::new(
2335          l2_cxs,
2336          OnFailure::CrashOnFailure,
2337        );
2338        AssertTypeOf(l3_djses)
2339          .is::<DisallowJavascriptExecutionScope<HandleScope>>();
2340        let d = l3_djses.deref_mut();
2341        AssertTypeOf(d).is::<HandleScope>();
2342        let d = d.deref_mut();
2343        AssertTypeOf(d).is::<HandleScope<()>>();
2344        let d = d.deref_mut();
2345        AssertTypeOf(d).is::<Isolate>();
2346        {
2347          let l4_ajses = &mut AllowJavascriptExecutionScope::new(l3_djses);
2348          AssertTypeOf(l4_ajses).is::<HandleScope>();
2349          let d = l4_ajses.deref_mut();
2350          AssertTypeOf(d).is::<HandleScope<()>>();
2351          let d = d.deref_mut();
2352          AssertTypeOf(d).is::<Isolate>();
2353        }
2354      }
2355      {
2356        let l3_ehs = &mut EscapableHandleScope::new(l2_cxs);
2357        AssertTypeOf(l3_ehs).is::<EscapableHandleScope>();
2358        {
2359          let l4_cxs = &mut ContextScope::new(l3_ehs, context);
2360          AssertTypeOf(l4_cxs).is::<ContextScope<EscapableHandleScope>>();
2361          let d = l4_cxs.deref_mut();
2362          AssertTypeOf(d).is::<EscapableHandleScope>();
2363          let d = d.deref_mut();
2364          AssertTypeOf(d).is::<HandleScope>();
2365          let d = d.deref_mut();
2366          AssertTypeOf(d).is::<HandleScope<()>>();
2367          let d = d.deref_mut();
2368          AssertTypeOf(d).is::<Isolate>();
2369        }
2370        {
2371          let l4_tc = &mut TryCatch::new(l3_ehs);
2372          AssertTypeOf(l4_tc).is::<TryCatch<EscapableHandleScope>>();
2373          let d = l4_tc.deref_mut();
2374          AssertTypeOf(d).is::<EscapableHandleScope>();
2375          let d = d.deref_mut();
2376          AssertTypeOf(d).is::<HandleScope>();
2377          let d = d.deref_mut();
2378          AssertTypeOf(d).is::<HandleScope<()>>();
2379          let d = d.deref_mut();
2380          AssertTypeOf(d).is::<Isolate>();
2381        }
2382        {
2383          let l4_djses = &mut DisallowJavascriptExecutionScope::new(
2384            l3_ehs,
2385            OnFailure::CrashOnFailure,
2386          );
2387          AssertTypeOf(l4_djses)
2388            .is::<DisallowJavascriptExecutionScope<EscapableHandleScope>>();
2389          let d = l4_djses.deref_mut();
2390          AssertTypeOf(d).is::<EscapableHandleScope>();
2391          let d = d.deref_mut();
2392          AssertTypeOf(d).is::<HandleScope>();
2393          let d = d.deref_mut();
2394          AssertTypeOf(d).is::<HandleScope<()>>();
2395          let d = d.deref_mut();
2396          AssertTypeOf(d).is::<Isolate>();
2397          {
2398            let l5_ajses = &mut AllowJavascriptExecutionScope::new(l4_djses);
2399            AssertTypeOf(l5_ajses).is::<EscapableHandleScope>();
2400            let d = l5_ajses.deref_mut();
2401            AssertTypeOf(d).is::<HandleScope>();
2402            let d = d.deref_mut();
2403            AssertTypeOf(d).is::<HandleScope<()>>();
2404            let d = d.deref_mut();
2405            AssertTypeOf(d).is::<Isolate>();
2406          }
2407        }
2408      }
2409    }
2410    {
2411      let l2_tc = &mut TryCatch::new(l1_hs);
2412      AssertTypeOf(l2_tc).is::<TryCatch<HandleScope<()>>>();
2413      let d = l2_tc.deref_mut();
2414      AssertTypeOf(d).is::<HandleScope<()>>();
2415      let d = d.deref_mut();
2416      AssertTypeOf(d).is::<Isolate>();
2417      {
2418        let l3_djses = &mut DisallowJavascriptExecutionScope::new(
2419          l2_tc,
2420          OnFailure::CrashOnFailure,
2421        );
2422        AssertTypeOf(l3_djses)
2423          .is::<DisallowJavascriptExecutionScope<TryCatch<HandleScope<()>>>>();
2424        let d = l3_djses.deref_mut();
2425        AssertTypeOf(d).is::<TryCatch<HandleScope<()>>>();
2426        let d = d.deref_mut();
2427        AssertTypeOf(d).is::<HandleScope<()>>();
2428        let d = d.deref_mut();
2429        AssertTypeOf(d).is::<Isolate>();
2430        {
2431          let l4_ajses = &mut AllowJavascriptExecutionScope::new(l3_djses);
2432          AssertTypeOf(l4_ajses).is::<TryCatch<HandleScope<()>>>();
2433          let d = l4_ajses.deref_mut();
2434          AssertTypeOf(d).is::<HandleScope<()>>();
2435          let d = d.deref_mut();
2436          AssertTypeOf(d).is::<Isolate>();
2437        }
2438      }
2439    }
2440    {
2441      let l2_ehs = &mut EscapableHandleScope::new(l1_hs);
2442      AssertTypeOf(l2_ehs).is::<EscapableHandleScope<()>>();
2443      let l3_tc = &mut TryCatch::new(l2_ehs);
2444      AssertTypeOf(l3_tc).is::<TryCatch<EscapableHandleScope<()>>>();
2445      let d = l3_tc.deref_mut();
2446      AssertTypeOf(d).is::<EscapableHandleScope<()>>();
2447      let d = d.deref_mut();
2448      AssertTypeOf(d).is::<HandleScope<()>>();
2449      let d = d.deref_mut();
2450      AssertTypeOf(d).is::<Isolate>();
2451    }
2452    {
2453      // `CallbackScope` is meant to be used inside V8 API callback functions
2454      // only. It assumes that a `HandleScope` already exists on the stack, and
2455      // that a context has been entered. Push a `ContextScope` onto the stack
2456      // to also meet the second expectation.
2457      let _ = ContextScope::new(l1_hs, context);
2458      let l2_cbs = &mut unsafe { CallbackScope::new(context) };
2459      AssertTypeOf(l2_cbs).is::<CallbackScope>();
2460      let d = l2_cbs.deref_mut();
2461      AssertTypeOf(d).is::<HandleScope>();
2462      let d = d.deref_mut();
2463      AssertTypeOf(d).is::<HandleScope<()>>();
2464      let d = d.deref_mut();
2465      AssertTypeOf(d).is::<Isolate>();
2466    }
2467    {
2468      let isolate: &mut Isolate = l1_hs.as_mut();
2469      let l2_cbs = &mut unsafe { CallbackScope::new(isolate) };
2470      AssertTypeOf(l2_cbs).is::<CallbackScope<()>>();
2471      let d = l2_cbs.deref_mut();
2472      AssertTypeOf(d).is::<HandleScope<()>>();
2473      let d = d.deref_mut();
2474      AssertTypeOf(d).is::<Isolate>();
2475    }
2476  }
2477
2478  #[test]
2479  fn new_scope_types() {
2480    crate::initialize_v8();
2481    let isolate = &mut Isolate::new(Default::default());
2482    AssertTypeOf(isolate).is::<OwnedIsolate>();
2483    let global_context: Global<Context>;
2484    {
2485      let l1_hs = &mut HandleScope::new(isolate);
2486      AssertTypeOf(l1_hs).is::<HandleScope<()>>();
2487      let context = Context::new(l1_hs, Default::default());
2488      global_context = Global::new(l1_hs, context);
2489      AssertTypeOf(&HandleScope::new(l1_hs)).is::<HandleScope<()>>();
2490      {
2491        let l2_cxs = &mut ContextScope::new(l1_hs, context);
2492        AssertTypeOf(l2_cxs).is::<ContextScope<HandleScope>>();
2493        AssertTypeOf(&ContextScope::new(l2_cxs, context))
2494          .is::<ContextScope<HandleScope>>();
2495        AssertTypeOf(&HandleScope::new(l2_cxs)).is::<HandleScope>();
2496        AssertTypeOf(&EscapableHandleScope::new(l2_cxs))
2497          .is::<EscapableHandleScope>();
2498        AssertTypeOf(&TryCatch::new(l2_cxs)).is::<TryCatch<HandleScope>>();
2499      }
2500      {
2501        let l2_ehs = &mut EscapableHandleScope::new(l1_hs);
2502        AssertTypeOf(l2_ehs).is::<EscapableHandleScope<()>>();
2503        AssertTypeOf(&HandleScope::new(l2_ehs))
2504          .is::<EscapableHandleScope<()>>();
2505        AssertTypeOf(&EscapableHandleScope::new(l2_ehs))
2506          .is::<EscapableHandleScope<()>>();
2507        {
2508          let l3_cxs = &mut ContextScope::new(l2_ehs, context);
2509          AssertTypeOf(l3_cxs).is::<ContextScope<EscapableHandleScope>>();
2510          AssertTypeOf(&ContextScope::new(l3_cxs, context))
2511            .is::<ContextScope<EscapableHandleScope>>();
2512          AssertTypeOf(&HandleScope::new(l3_cxs)).is::<EscapableHandleScope>();
2513          AssertTypeOf(&EscapableHandleScope::new(l3_cxs))
2514            .is::<EscapableHandleScope>();
2515          {
2516            let l4_tc = &mut TryCatch::new(l3_cxs);
2517            AssertTypeOf(l4_tc).is::<TryCatch<EscapableHandleScope>>();
2518            AssertTypeOf(&ContextScope::new(l4_tc, context))
2519              .is::<ContextScope<EscapableHandleScope>>();
2520            AssertTypeOf(&HandleScope::new(l4_tc)).is::<EscapableHandleScope>();
2521            AssertTypeOf(&EscapableHandleScope::new(l4_tc))
2522              .is::<EscapableHandleScope>();
2523            AssertTypeOf(&TryCatch::new(l4_tc))
2524              .is::<TryCatch<EscapableHandleScope>>();
2525          }
2526        }
2527        {
2528          let l3_tc = &mut TryCatch::new(l2_ehs);
2529          AssertTypeOf(l3_tc).is::<TryCatch<EscapableHandleScope<()>>>();
2530          AssertTypeOf(&ContextScope::new(l3_tc, context))
2531            .is::<ContextScope<EscapableHandleScope>>();
2532          AssertTypeOf(&HandleScope::new(l3_tc))
2533            .is::<EscapableHandleScope<()>>();
2534          AssertTypeOf(&EscapableHandleScope::new(l3_tc))
2535            .is::<EscapableHandleScope<()>>();
2536          AssertTypeOf(&TryCatch::new(l3_tc))
2537            .is::<TryCatch<EscapableHandleScope<()>>>();
2538        }
2539      }
2540      {
2541        let l2_tc = &mut TryCatch::new(l1_hs);
2542        AssertTypeOf(l2_tc).is::<TryCatch<HandleScope<()>>>();
2543        AssertTypeOf(&ContextScope::new(l2_tc, context))
2544          .is::<ContextScope<HandleScope>>();
2545        AssertTypeOf(&HandleScope::new(l2_tc)).is::<HandleScope<()>>();
2546        AssertTypeOf(&EscapableHandleScope::new(l2_tc))
2547          .is::<EscapableHandleScope<()>>();
2548        AssertTypeOf(&TryCatch::new(l2_tc)).is::<TryCatch<HandleScope<()>>>();
2549      }
2550      {
2551        let l2_cbs = &mut unsafe { CallbackScope::new(context) };
2552        AssertTypeOf(l2_cbs).is::<CallbackScope>();
2553        AssertTypeOf(&ContextScope::new(l2_cbs, context))
2554          .is::<ContextScope<HandleScope>>();
2555        {
2556          let l3_hs = &mut HandleScope::new(l2_cbs);
2557          AssertTypeOf(l3_hs).is::<HandleScope>();
2558          AssertTypeOf(&ContextScope::new(l3_hs, context))
2559            .is::<ContextScope<HandleScope>>();
2560          AssertTypeOf(&HandleScope::new(l3_hs)).is::<HandleScope>();
2561          AssertTypeOf(&EscapableHandleScope::new(l3_hs))
2562            .is::<EscapableHandleScope>();
2563          AssertTypeOf(&TryCatch::new(l3_hs)).is::<TryCatch<HandleScope>>();
2564        }
2565        {
2566          let l3_ehs = &mut EscapableHandleScope::new(l2_cbs);
2567          AssertTypeOf(l3_ehs).is::<EscapableHandleScope>();
2568          AssertTypeOf(&ContextScope::new(l3_ehs, context))
2569            .is::<ContextScope<EscapableHandleScope>>();
2570          AssertTypeOf(&HandleScope::new(l3_ehs)).is::<EscapableHandleScope>();
2571          AssertTypeOf(&EscapableHandleScope::new(l3_ehs))
2572            .is::<EscapableHandleScope>();
2573          AssertTypeOf(&TryCatch::new(l3_ehs))
2574            .is::<TryCatch<EscapableHandleScope>>();
2575        }
2576        {
2577          let l3_tc = &mut TryCatch::new(l2_cbs);
2578          AssertTypeOf(l3_tc).is::<TryCatch<HandleScope>>();
2579          AssertTypeOf(&ContextScope::new(l3_tc, context))
2580            .is::<ContextScope<HandleScope>>();
2581          AssertTypeOf(&HandleScope::new(l3_tc)).is::<HandleScope>();
2582          AssertTypeOf(&EscapableHandleScope::new(l3_tc))
2583            .is::<EscapableHandleScope>();
2584          AssertTypeOf(&TryCatch::new(l3_tc)).is::<TryCatch<HandleScope>>();
2585        }
2586      }
2587    }
2588    {
2589      let l1_cbs = &mut unsafe { CallbackScope::new(&mut *isolate) };
2590      AssertTypeOf(l1_cbs).is::<CallbackScope<()>>();
2591      let context = Context::new(l1_cbs, Default::default());
2592      AssertTypeOf(&ContextScope::new(l1_cbs, context))
2593        .is::<ContextScope<HandleScope>>();
2594      AssertTypeOf(&HandleScope::new(l1_cbs)).is::<HandleScope<()>>();
2595      AssertTypeOf(&EscapableHandleScope::new(l1_cbs))
2596        .is::<EscapableHandleScope<()>>();
2597      AssertTypeOf(&TryCatch::new(l1_cbs)).is::<TryCatch<HandleScope<()>>>();
2598    }
2599    {
2600      AssertTypeOf(&HandleScope::with_context(isolate, &global_context))
2601        .is::<HandleScope>();
2602      AssertTypeOf(&HandleScope::with_context(isolate, global_context))
2603        .is::<HandleScope>();
2604    }
2605  }
2606}