mozjs/
rust.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5//! Rust wrappers around the raw JS apis
6
7use std::cell::Cell;
8use std::char;
9use std::default::Default;
10use std::ffi::{CStr, CString};
11use std::marker::PhantomData;
12use std::mem::MaybeUninit;
13use std::ops::{Deref, DerefMut};
14use std::ptr::{self, NonNull};
15use std::slice;
16use std::str;
17use std::sync::atomic::{AtomicU32, Ordering};
18use std::sync::{Arc, Mutex, RwLock};
19
20use crate::consts::{JSCLASS_GLOBAL_SLOT_COUNT, JSCLASS_RESERVED_SLOTS_MASK};
21use crate::consts::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
22use crate::conversions::jsstr_to_string;
23use crate::default_heapsize;
24pub use crate::gc::*;
25use crate::glue::AppendToRootedObjectVector;
26use crate::glue::{CreateRootedIdVector, CreateRootedObjectVector};
27use crate::glue::{
28    DeleteCompileOptions, DeleteRootedObjectVector, DescribeScriptedCaller, DestroyRootedIdVector,
29};
30use crate::glue::{DeleteJSAutoStructuredCloneBuffer, NewJSAutoStructuredCloneBuffer};
31use crate::glue::{
32    GetIdVectorAddress, GetObjectVectorAddress, NewCompileOptions, SliceRootedIdVector,
33};
34use crate::jsapi;
35use crate::jsapi::glue::{DeleteRealmOptions, JS_Init, JS_NewRealmOptions};
36use crate::jsapi::js::frontend::InitialStencilAndDelazifications;
37use crate::jsapi::mozilla::Utf8Unit;
38use crate::jsapi::shadow::BaseShape;
39use crate::jsapi::HandleObjectVector as RawHandleObjectVector;
40use crate::jsapi::HandleValue as RawHandleValue;
41use crate::jsapi::JS_AddExtraGCRootsTracer;
42use crate::jsapi::MutableHandleIdVector as RawMutableHandleIdVector;
43use crate::jsapi::{already_AddRefed, jsid};
44use crate::jsapi::{BuildStackString, CaptureCurrentStack, StackFormat};
45use crate::jsapi::{Evaluate2, HandleValueArray, StencilRelease};
46use crate::jsapi::{InitSelfHostedCode, IsWindowSlow};
47use crate::jsapi::{
48    JSAutoRealm, JS_SetGCParameter, JS_SetNativeStackQuota, JS_WrapObject, JS_WrapValue,
49};
50use crate::jsapi::{JSAutoStructuredCloneBuffer, JSStructuredCloneCallbacks, StructuredCloneScope};
51use crate::jsapi::{JSClass, JSClassOps, JSContext, Realm, JSCLASS_RESERVED_SLOTS_SHIFT};
52use crate::jsapi::{JSErrorReport, JSFunctionSpec, JSGCParamKey};
53use crate::jsapi::{JSObject, JSPropertySpec, JSRuntime};
54use crate::jsapi::{JSString, Object, PersistentRootedIdVector};
55use crate::jsapi::{JS_DefineFunctions, JS_DefineProperties, JS_DestroyContext, JS_ShutDown};
56use crate::jsapi::{JS_EnumerateStandardClasses, JS_GetRuntime, JS_GlobalObjectTraceHook};
57use crate::jsapi::{JS_MayResolveStandardClass, JS_NewContext, JS_ResolveStandardClass};
58use crate::jsapi::{JS_RequestInterruptCallback, JS_RequestInterruptCallbackCanWait};
59use crate::jsapi::{JS_StackCapture_AllFrames, JS_StackCapture_MaxFrames};
60use crate::jsapi::{PersistentRootedObjectVector, ReadOnlyCompileOptions, RootingContext};
61use crate::jsapi::{SetWarningReporter, SourceText, ToBooleanSlow};
62use crate::jsapi::{ToInt32Slow, ToInt64Slow, ToNumberSlow, ToStringSlow, ToUint16Slow};
63use crate::jsapi::{ToUint32Slow, ToUint64Slow, ToWindowProxyIfWindowSlow};
64use crate::jsval::ObjectValue;
65use crate::panic::maybe_resume_unwind;
66use log::{debug, warn};
67use mozjs_sys::jsapi::JS::SavedFrameResult;
68pub use mozjs_sys::jsgc::{GCMethods, IntoHandle, IntoMutableHandle};
69pub use mozjs_sys::trace::Traceable as Trace;
70
71use crate::rooted;
72
73// From Gecko:
74// Our "default" stack is what we use in configurations where we don't have a compelling reason to
75// do things differently. This is effectively 1MB on 64-bit platforms.
76const STACK_QUOTA: usize = 128 * 8 * 1024;
77
78// From Gecko:
79// The JS engine permits us to set different stack limits for system code,
80// trusted script, and untrusted script. We have tests that ensure that
81// we can always execute 10 "heavy" (eval+with) stack frames deeper in
82// privileged code. Our stack sizes vary greatly in different configurations,
83// so satisfying those tests requires some care. Manual measurements of the
84// number of heavy stack frames achievable gives us the following rough data,
85// ordered by the effective categories in which they are grouped in the
86// JS_SetNativeStackQuota call (which predates this analysis).
87//
88// (NB: These numbers may have drifted recently - see bug 938429)
89// OSX 64-bit Debug: 7MB stack, 636 stack frames => ~11.3k per stack frame
90// OSX64 Opt: 7MB stack, 2440 stack frames => ~3k per stack frame
91//
92// Linux 32-bit Debug: 2MB stack, 426 stack frames => ~4.8k per stack frame
93// Linux 64-bit Debug: 4MB stack, 455 stack frames => ~9.0k per stack frame
94//
95// Windows (Opt+Debug): 900K stack, 235 stack frames => ~3.4k per stack frame
96//
97// Linux 32-bit Opt: 1MB stack, 272 stack frames => ~3.8k per stack frame
98// Linux 64-bit Opt: 2MB stack, 316 stack frames => ~6.5k per stack frame
99//
100// We tune the trusted/untrusted quotas for each configuration to achieve our
101// invariants while attempting to minimize overhead. In contrast, our buffer
102// between system code and trusted script is a very unscientific 10k.
103const SYSTEM_CODE_BUFFER: usize = 10 * 1024;
104
105// Gecko's value on 64-bit.
106const TRUSTED_SCRIPT_BUFFER: usize = 8 * 12800;
107
108trait ToResult {
109    fn to_result(self) -> Result<(), ()>;
110}
111
112impl ToResult for bool {
113    fn to_result(self) -> Result<(), ()> {
114        if self {
115            Ok(())
116        } else {
117            Err(())
118        }
119    }
120}
121
122// ___________________________________________________________________________
123// friendly Rustic API to runtimes
124
125pub struct RealmOptions(*mut jsapi::RealmOptions);
126
127impl Deref for RealmOptions {
128    type Target = jsapi::RealmOptions;
129    fn deref(&self) -> &Self::Target {
130        unsafe { &*self.0 }
131    }
132}
133
134impl DerefMut for RealmOptions {
135    fn deref_mut(&mut self) -> &mut Self::Target {
136        unsafe { &mut *self.0 }
137    }
138}
139
140impl Default for RealmOptions {
141    fn default() -> RealmOptions {
142        RealmOptions(unsafe { JS_NewRealmOptions() })
143    }
144}
145
146impl Drop for RealmOptions {
147    fn drop(&mut self) {
148        unsafe { DeleteRealmOptions(self.0) }
149    }
150}
151
152thread_local!(static CONTEXT: Cell<*mut JSContext> = Cell::new(ptr::null_mut()));
153
154#[derive(PartialEq)]
155enum EngineState {
156    Uninitialized,
157    InitFailed,
158    Initialized,
159    ShutDown,
160}
161
162static ENGINE_STATE: Mutex<EngineState> = Mutex::new(EngineState::Uninitialized);
163
164#[derive(Debug)]
165pub enum JSEngineError {
166    AlreadyInitialized,
167    AlreadyShutDown,
168    InitFailed,
169}
170
171/// A handle that must be kept alive in order to create new Runtimes.
172/// When this handle is dropped, the engine is shut down and cannot
173/// be reinitialized.
174pub struct JSEngine {
175    /// The count of alive handles derived from this initialized instance.
176    outstanding_handles: Arc<AtomicU32>,
177    // Ensure this type cannot be sent between threads.
178    marker: PhantomData<*mut ()>,
179}
180
181pub struct JSEngineHandle(Arc<AtomicU32>);
182
183impl Clone for JSEngineHandle {
184    fn clone(&self) -> JSEngineHandle {
185        self.0.fetch_add(1, Ordering::SeqCst);
186        JSEngineHandle(self.0.clone())
187    }
188}
189
190impl Drop for JSEngineHandle {
191    fn drop(&mut self) {
192        self.0.fetch_sub(1, Ordering::SeqCst);
193    }
194}
195
196impl JSEngine {
197    /// Initialize the JS engine to prepare for creating new JS runtimes.
198    pub fn init() -> Result<JSEngine, JSEngineError> {
199        let mut state = ENGINE_STATE.lock().unwrap();
200        match *state {
201            EngineState::Initialized => return Err(JSEngineError::AlreadyInitialized),
202            EngineState::InitFailed => return Err(JSEngineError::InitFailed),
203            EngineState::ShutDown => return Err(JSEngineError::AlreadyShutDown),
204            EngineState::Uninitialized => (),
205        }
206        if unsafe { !JS_Init() } {
207            *state = EngineState::InitFailed;
208            Err(JSEngineError::InitFailed)
209        } else {
210            *state = EngineState::Initialized;
211            Ok(JSEngine {
212                outstanding_handles: Arc::new(AtomicU32::new(0)),
213                marker: PhantomData,
214            })
215        }
216    }
217
218    pub fn can_shutdown(&self) -> bool {
219        self.outstanding_handles.load(Ordering::SeqCst) == 0
220    }
221
222    /// Create a handle to this engine.
223    pub fn handle(&self) -> JSEngineHandle {
224        self.outstanding_handles.fetch_add(1, Ordering::SeqCst);
225        JSEngineHandle(self.outstanding_handles.clone())
226    }
227}
228
229/// Shut down the JS engine, invalidating any existing runtimes and preventing
230/// any new ones from being created.
231impl Drop for JSEngine {
232    fn drop(&mut self) {
233        let mut state = ENGINE_STATE.lock().unwrap();
234        if *state == EngineState::Initialized {
235            assert_eq!(
236                self.outstanding_handles.load(Ordering::SeqCst),
237                0,
238                "There are outstanding JS engine handles"
239            );
240            *state = EngineState::ShutDown;
241            unsafe {
242                JS_ShutDown();
243            }
244        }
245    }
246}
247
248pub fn transform_str_to_source_text(source: &str) -> SourceText<Utf8Unit> {
249    SourceText {
250        units_: source.as_ptr() as *const _,
251        length_: source.len() as u32,
252        ownsUnits_: false,
253        _phantom_0: PhantomData,
254    }
255}
256
257pub fn transform_u16_to_source_text(source: &[u16]) -> SourceText<u16> {
258    SourceText {
259        units_: source.as_ptr() as *const _,
260        length_: source.len() as u32,
261        ownsUnits_: false,
262        _phantom_0: PhantomData,
263    }
264}
265
266/// A handle to a Runtime that will be used to create a new runtime in another
267/// thread. This handle and the new runtime must be destroyed before the original
268/// runtime can be dropped.
269pub struct ParentRuntime {
270    /// Raw pointer to the underlying SpiderMonkey runtime.
271    parent: *mut JSRuntime,
272    /// Handle to ensure the JS engine remains running while this handle exists.
273    engine: JSEngineHandle,
274    /// The number of children of the runtime that created this ParentRuntime value.
275    children_of_parent: Arc<()>,
276}
277unsafe impl Send for ParentRuntime {}
278
279/// A wrapper for the `JSContext` structure in SpiderMonkey.
280pub struct Runtime {
281    /// Raw pointer to the underlying SpiderMonkey context.
282    cx: *mut JSContext,
283    /// The engine that this runtime is associated with.
284    engine: JSEngineHandle,
285    /// If this Runtime was created with a parent, this member exists to ensure
286    /// that that parent's count of outstanding children (see [outstanding_children])
287    /// remains accurate and will be automatically decreased when this Runtime value
288    /// is dropped.
289    _parent_child_count: Option<Arc<()>>,
290    /// The strong references to this value represent the number of child runtimes
291    /// that have been created using this Runtime as a parent. Since Runtime values
292    /// must be associated with a particular thread, we cannot simply use Arc<Runtime>
293    /// to represent the resulting ownership graph and risk destroying a Runtime on
294    /// the wrong thread.
295    outstanding_children: Arc<()>,
296    /// An `Option` that holds the same pointer as `cx`.
297    /// This is shared with all [`ThreadSafeJSContext`]s, so
298    /// they can detect when it's destroyed on the main thread.
299    thread_safe_handle: Arc<RwLock<Option<*mut JSContext>>>,
300}
301
302impl Runtime {
303    /// Get the `JSContext` for this thread.
304    pub fn get() -> Option<NonNull<JSContext>> {
305        let cx = CONTEXT.with(|context| context.get());
306        NonNull::new(cx)
307    }
308
309    /// Create a [`ThreadSafeJSContext`] that can detect when this `Runtime` is destroyed.
310    pub fn thread_safe_js_context(&self) -> ThreadSafeJSContext {
311        ThreadSafeJSContext(self.thread_safe_handle.clone())
312    }
313
314    /// Creates a new `JSContext`.
315    pub fn new(engine: JSEngineHandle) -> Runtime {
316        unsafe { Self::create(engine, None) }
317    }
318
319    /// Signal that a new child runtime will be created in the future, and ensure
320    /// that this runtime will not allow itself to be destroyed before the new
321    /// child runtime. Returns a handle that can be passed to `create_with_parent`
322    /// in order to create a new runtime on another thread that is associated with
323    /// this runtime.
324    pub fn prepare_for_new_child(&self) -> ParentRuntime {
325        ParentRuntime {
326            parent: self.rt(),
327            engine: self.engine.clone(),
328            children_of_parent: self.outstanding_children.clone(),
329        }
330    }
331
332    /// Creates a new `JSContext` with a parent runtime. If the parent does not outlive
333    /// the new runtime, its destructor will assert.
334    ///
335    /// Unsafety:
336    /// If panicking does not abort the program, any threads with child runtimes will
337    /// continue executing after the thread with the parent runtime panics, but they
338    /// will be in an invalid and undefined state.
339    pub unsafe fn create_with_parent(parent: ParentRuntime) -> Runtime {
340        Self::create(parent.engine.clone(), Some(parent))
341    }
342
343    unsafe fn create(engine: JSEngineHandle, parent: Option<ParentRuntime>) -> Runtime {
344        let parent_runtime = parent.as_ref().map_or(ptr::null_mut(), |r| r.parent);
345        let js_context = JS_NewContext(default_heapsize + (ChunkSize as u32), parent_runtime);
346        assert!(!js_context.is_null());
347
348        // Unconstrain the runtime's threshold on nominal heap size, to avoid
349        // triggering GC too often if operating continuously near an arbitrary
350        // finite threshold. This leaves the maximum-JS_malloc-bytes threshold
351        // still in effect to cause periodical, and we hope hygienic,
352        // last-ditch GCs from within the GC's allocator.
353        JS_SetGCParameter(js_context, JSGCParamKey::JSGC_MAX_BYTES, u32::MAX);
354
355        JS_AddExtraGCRootsTracer(js_context, Some(trace_traceables), ptr::null_mut());
356
357        JS_SetNativeStackQuota(
358            js_context,
359            STACK_QUOTA,
360            STACK_QUOTA - SYSTEM_CODE_BUFFER,
361            STACK_QUOTA - SYSTEM_CODE_BUFFER - TRUSTED_SCRIPT_BUFFER,
362        );
363
364        CONTEXT.with(|context| {
365            assert!(context.get().is_null());
366            context.set(js_context);
367        });
368
369        #[cfg(target_pointer_width = "64")]
370        let cache = crate::jsapi::__BindgenOpaqueArray::<u64, 2>::default();
371        #[cfg(target_pointer_width = "32")]
372        let cache = crate::jsapi::__BindgenOpaqueArray::<u32, 2>::default();
373
374        InitSelfHostedCode(js_context, cache, None);
375
376        SetWarningReporter(js_context, Some(report_warning));
377
378        Runtime {
379            engine,
380            _parent_child_count: parent.map(|p| p.children_of_parent),
381            cx: js_context,
382            outstanding_children: Arc::new(()),
383            thread_safe_handle: Arc::new(RwLock::new(Some(js_context))),
384        }
385    }
386
387    /// Returns the `JSRuntime` object.
388    pub fn rt(&self) -> *mut JSRuntime {
389        unsafe { JS_GetRuntime(self.cx) }
390    }
391
392    /// Returns the `JSContext` object.
393    pub fn cx(&self) -> *mut JSContext {
394        self.cx
395    }
396
397    pub fn evaluate_script(
398        &self,
399        glob: HandleObject,
400        script: &str,
401        rval: MutableHandleValue,
402        options: CompileOptionsWrapper,
403    ) -> Result<(), ()> {
404        debug!(
405            "Evaluating script from {} with content {}",
406            options.filename(),
407            script
408        );
409
410        let _ac = JSAutoRealm::new(self.cx(), glob.get());
411
412        unsafe {
413            let mut source = transform_str_to_source_text(&script);
414            if !Evaluate2(self.cx(), options.ptr, &mut source, rval.into()) {
415                debug!("...err!");
416                maybe_resume_unwind();
417                Err(())
418            } else {
419                // we could return the script result but then we'd have
420                // to root it and so forth and, really, who cares?
421                debug!("...ok!");
422                Ok(())
423            }
424        }
425    }
426
427    pub fn new_compile_options(&self, filename: &str, line: u32) -> CompileOptionsWrapper {
428        // SAFETY: `cx` argument points to a non-null, valid JSContext
429        unsafe { CompileOptionsWrapper::new(self.cx(), filename, line) }
430    }
431}
432
433impl Drop for Runtime {
434    fn drop(&mut self) {
435        self.thread_safe_handle.write().unwrap().take();
436        assert!(
437            Arc::get_mut(&mut self.outstanding_children).is_some(),
438            "This runtime still has live children."
439        );
440        unsafe {
441            JS_DestroyContext(self.cx);
442
443            CONTEXT.with(|context| {
444                assert_eq!(context.get(), self.cx);
445                context.set(ptr::null_mut());
446            });
447        }
448    }
449}
450
451/// A version of the [`JSContext`] that can be used from other threads and is thus
452/// `Send` and `Sync`. This should only ever expose operations that are marked as
453/// thread-safe by the SpiderMonkey API, ie ones that only atomic fields in JSContext.
454#[derive(Clone)]
455pub struct ThreadSafeJSContext(Arc<RwLock<Option<*mut JSContext>>>);
456
457unsafe impl Send for ThreadSafeJSContext {}
458unsafe impl Sync for ThreadSafeJSContext {}
459
460impl ThreadSafeJSContext {
461    /// Call `JS_RequestInterruptCallback` from the SpiderMonkey API.
462    /// This is thread-safe according to
463    /// <https://searchfox.org/mozilla-central/rev/7a85a111b5f42cdc07f438e36f9597c4c6dc1d48/js/public/Interrupt.h#19>
464    pub fn request_interrupt_callback(&self) {
465        if let Some(&cx) = self.0.read().unwrap().as_ref() {
466            unsafe {
467                JS_RequestInterruptCallback(cx);
468            }
469        }
470    }
471
472    /// Call `JS_RequestInterruptCallbackCanWait` from the SpiderMonkey API.
473    /// This is thread-safe according to
474    /// <https://searchfox.org/mozilla-central/rev/7a85a111b5f42cdc07f438e36f9597c4c6dc1d48/js/public/Interrupt.h#19>
475    pub fn request_interrupt_callback_can_wait(&self) {
476        if let Some(&cx) = self.0.read().unwrap().as_ref() {
477            unsafe {
478                JS_RequestInterruptCallbackCanWait(cx);
479            }
480        }
481    }
482}
483
484const ChunkShift: usize = 20;
485const ChunkSize: usize = 1 << ChunkShift;
486
487#[cfg(target_pointer_width = "32")]
488const ChunkLocationOffset: usize = ChunkSize - 2 * 4 - 8;
489
490// ___________________________________________________________________________
491// Wrappers around things in jsglue.cpp
492
493pub struct RootedObjectVectorWrapper {
494    pub ptr: *mut PersistentRootedObjectVector,
495}
496
497impl RootedObjectVectorWrapper {
498    pub fn new(cx: *mut JSContext) -> RootedObjectVectorWrapper {
499        RootedObjectVectorWrapper {
500            ptr: unsafe { CreateRootedObjectVector(cx) },
501        }
502    }
503
504    pub fn append(&self, obj: *mut JSObject) -> bool {
505        unsafe { AppendToRootedObjectVector(self.ptr, obj) }
506    }
507
508    pub fn handle(&self) -> RawHandleObjectVector {
509        RawHandleObjectVector {
510            ptr: unsafe { GetObjectVectorAddress(self.ptr) },
511        }
512    }
513}
514
515impl Drop for RootedObjectVectorWrapper {
516    fn drop(&mut self) {
517        unsafe { DeleteRootedObjectVector(self.ptr) }
518    }
519}
520
521pub struct CompileOptionsWrapper {
522    pub ptr: *mut ReadOnlyCompileOptions,
523    filename: CString,
524}
525
526impl CompileOptionsWrapper {
527    /// # Safety
528    /// `cx` must point to a non-null, valid [`JSContext`].
529    /// To create an instance from safe code, use [`Runtime::new_compile_options`].
530    pub unsafe fn new(cx: *mut JSContext, filename: &str, line: u32) -> Self {
531        let filename = CString::new(filename.as_bytes()).unwrap();
532        let ptr = NewCompileOptions(cx, filename.as_ptr(), line);
533        assert!(!ptr.is_null());
534        Self { ptr, filename }
535    }
536
537    pub fn filename(&self) -> &str {
538        self.filename.to_str().expect("Guaranteed by new")
539    }
540
541    pub fn set_introduction_type(&mut self, introduction_type: &'static CStr) {
542        unsafe {
543            (*self.ptr)._base.introductionType = introduction_type.as_ptr();
544        }
545    }
546}
547
548impl Drop for CompileOptionsWrapper {
549    fn drop(&mut self) {
550        unsafe { DeleteCompileOptions(self.ptr) }
551    }
552}
553
554pub struct JSAutoStructuredCloneBufferWrapper {
555    ptr: NonNull<JSAutoStructuredCloneBuffer>,
556}
557
558impl JSAutoStructuredCloneBufferWrapper {
559    pub unsafe fn new(
560        scope: StructuredCloneScope,
561        callbacks: *const JSStructuredCloneCallbacks,
562    ) -> Self {
563        let raw_ptr = NewJSAutoStructuredCloneBuffer(scope, callbacks);
564        Self {
565            ptr: NonNull::new(raw_ptr).unwrap(),
566        }
567    }
568
569    pub fn as_raw_ptr(&self) -> *mut JSAutoStructuredCloneBuffer {
570        self.ptr.as_ptr()
571    }
572}
573
574impl Drop for JSAutoStructuredCloneBufferWrapper {
575    fn drop(&mut self) {
576        unsafe {
577            DeleteJSAutoStructuredCloneBuffer(self.ptr.as_ptr());
578        }
579    }
580}
581
582pub struct Stencil {
583    inner: already_AddRefed<InitialStencilAndDelazifications>,
584}
585
586/*unsafe impl Send for Stencil {}
587unsafe impl Sync for Stencil {}*/
588
589impl Drop for Stencil {
590    fn drop(&mut self) {
591        if self.is_null() {
592            return;
593        }
594        unsafe {
595            StencilRelease(self.inner.mRawPtr);
596        }
597    }
598}
599
600impl Deref for Stencil {
601    type Target = *mut InitialStencilAndDelazifications;
602
603    fn deref(&self) -> &Self::Target {
604        &self.inner.mRawPtr
605    }
606}
607
608impl Stencil {
609    pub fn is_null(&self) -> bool {
610        self.inner.mRawPtr.is_null()
611    }
612}
613
614// ___________________________________________________________________________
615// Fast inline converters
616
617#[inline]
618pub unsafe fn ToBoolean(v: HandleValue) -> bool {
619    let val = *v.ptr;
620
621    if val.is_boolean() {
622        return val.to_boolean();
623    }
624
625    if val.is_int32() {
626        return val.to_int32() != 0;
627    }
628
629    if val.is_null_or_undefined() {
630        return false;
631    }
632
633    if val.is_double() {
634        let d = val.to_double();
635        return !d.is_nan() && d != 0f64;
636    }
637
638    if val.is_symbol() {
639        return true;
640    }
641
642    ToBooleanSlow(v.into())
643}
644
645#[inline]
646pub unsafe fn ToNumber(cx: *mut JSContext, v: HandleValue) -> Result<f64, ()> {
647    let val = *v.ptr;
648    if val.is_number() {
649        return Ok(val.to_number());
650    }
651
652    let mut out = Default::default();
653    if ToNumberSlow(cx, v.into_handle(), &mut out) {
654        Ok(out)
655    } else {
656        Err(())
657    }
658}
659
660#[inline]
661unsafe fn convert_from_int32<T: Default + Copy>(
662    cx: *mut JSContext,
663    v: HandleValue,
664    conv_fn: unsafe extern "C" fn(*mut JSContext, RawHandleValue, *mut T) -> bool,
665) -> Result<T, ()> {
666    let val = *v.ptr;
667    if val.is_int32() {
668        let intval: i64 = val.to_int32() as i64;
669        // TODO: do something better here that works on big endian
670        let intval = *(&intval as *const i64 as *const T);
671        return Ok(intval);
672    }
673
674    let mut out = Default::default();
675    if conv_fn(cx, v.into(), &mut out) {
676        Ok(out)
677    } else {
678        Err(())
679    }
680}
681
682#[inline]
683pub unsafe fn ToInt32(cx: *mut JSContext, v: HandleValue) -> Result<i32, ()> {
684    convert_from_int32::<i32>(cx, v, ToInt32Slow)
685}
686
687#[inline]
688pub unsafe fn ToUint32(cx: *mut JSContext, v: HandleValue) -> Result<u32, ()> {
689    convert_from_int32::<u32>(cx, v, ToUint32Slow)
690}
691
692#[inline]
693pub unsafe fn ToUint16(cx: *mut JSContext, v: HandleValue) -> Result<u16, ()> {
694    convert_from_int32::<u16>(cx, v, ToUint16Slow)
695}
696
697#[inline]
698pub unsafe fn ToInt64(cx: *mut JSContext, v: HandleValue) -> Result<i64, ()> {
699    convert_from_int32::<i64>(cx, v, ToInt64Slow)
700}
701
702#[inline]
703pub unsafe fn ToUint64(cx: *mut JSContext, v: HandleValue) -> Result<u64, ()> {
704    convert_from_int32::<u64>(cx, v, ToUint64Slow)
705}
706
707#[inline]
708pub unsafe fn ToString(cx: *mut JSContext, v: HandleValue) -> *mut JSString {
709    let val = *v.ptr;
710    if val.is_string() {
711        return val.to_string();
712    }
713
714    ToStringSlow(cx, v.into())
715}
716
717pub unsafe fn ToWindowProxyIfWindow(obj: *mut JSObject) -> *mut JSObject {
718    if is_window(obj) {
719        ToWindowProxyIfWindowSlow(obj)
720    } else {
721        obj
722    }
723}
724
725pub unsafe extern "C" fn report_warning(_cx: *mut JSContext, report: *mut JSErrorReport) {
726    fn latin1_to_string(bytes: &[u8]) -> String {
727        bytes
728            .iter()
729            .map(|c| char::from_u32(*c as u32).unwrap())
730            .collect()
731    }
732
733    let fnptr = (*report)._base.filename.data_;
734    let fname = if !fnptr.is_null() {
735        let c_str = CStr::from_ptr(fnptr);
736        latin1_to_string(c_str.to_bytes())
737    } else {
738        "none".to_string()
739    };
740
741    let lineno = (*report)._base.lineno;
742    let column = (*report)._base.column._base;
743
744    let msg_ptr = (*report)._base.message_.data_ as *const u8;
745    let msg_len = (0usize..)
746        .find(|&i| *msg_ptr.offset(i as isize) == 0)
747        .unwrap();
748    let msg_slice = slice::from_raw_parts(msg_ptr, msg_len);
749    let msg = str::from_utf8_unchecked(msg_slice);
750
751    warn!("Warning at {}:{}:{}: {}\n", fname, lineno, column, msg);
752}
753
754pub struct IdVector(*mut PersistentRootedIdVector);
755
756impl IdVector {
757    pub unsafe fn new(cx: *mut JSContext) -> IdVector {
758        let vector = CreateRootedIdVector(cx);
759        assert!(!vector.is_null());
760        IdVector(vector)
761    }
762
763    pub fn handle_mut(&mut self) -> RawMutableHandleIdVector {
764        RawMutableHandleIdVector {
765            ptr: unsafe { GetIdVectorAddress(self.0) },
766        }
767    }
768}
769
770impl Drop for IdVector {
771    fn drop(&mut self) {
772        unsafe { DestroyRootedIdVector(self.0) }
773    }
774}
775
776impl Deref for IdVector {
777    type Target = [jsid];
778
779    fn deref(&self) -> &[jsid] {
780        unsafe {
781            let mut length = 0;
782            let pointer = SliceRootedIdVector(self.0, &mut length);
783            slice::from_raw_parts(pointer, length)
784        }
785    }
786}
787
788/// Defines methods on `obj`. The last entry of `methods` must contain zeroed
789/// memory.
790///
791/// # Failures
792///
793/// Returns `Err` on JSAPI failure.
794///
795/// # Panics
796///
797/// Panics if the last entry of `methods` does not contain zeroed memory.
798///
799/// # Safety
800///
801/// - `cx` must be valid.
802/// - This function calls into unaudited C++ code.
803pub unsafe fn define_methods(
804    cx: *mut JSContext,
805    obj: HandleObject,
806    methods: &'static [JSFunctionSpec],
807) -> Result<(), ()> {
808    assert!({
809        match methods.last() {
810            Some(&JSFunctionSpec {
811                name,
812                call,
813                nargs,
814                flags,
815                selfHostedName,
816            }) => {
817                name.string_.is_null()
818                    && call.is_zeroed()
819                    && nargs == 0
820                    && flags == 0
821                    && selfHostedName.is_null()
822            }
823            None => false,
824        }
825    });
826
827    JS_DefineFunctions(cx, obj.into(), methods.as_ptr()).to_result()
828}
829
830/// Defines attributes on `obj`. The last entry of `properties` must contain
831/// zeroed memory.
832///
833/// # Failures
834///
835/// Returns `Err` on JSAPI failure.
836///
837/// # Panics
838///
839/// Panics if the last entry of `properties` does not contain zeroed memory.
840///
841/// # Safety
842///
843/// - `cx` must be valid.
844/// - This function calls into unaudited C++ code.
845pub unsafe fn define_properties(
846    cx: *mut JSContext,
847    obj: HandleObject,
848    properties: &'static [JSPropertySpec],
849) -> Result<(), ()> {
850    assert!({
851        match properties.last() {
852            Some(spec) => spec.is_zeroed(),
853            None => false,
854        }
855    });
856
857    JS_DefineProperties(cx, obj.into(), properties.as_ptr()).to_result()
858}
859
860static SIMPLE_GLOBAL_CLASS_OPS: JSClassOps = JSClassOps {
861    addProperty: None,
862    delProperty: None,
863    enumerate: Some(JS_EnumerateStandardClasses),
864    newEnumerate: None,
865    resolve: Some(JS_ResolveStandardClass),
866    mayResolve: Some(JS_MayResolveStandardClass),
867    finalize: None,
868    call: None,
869    construct: None,
870    trace: Some(JS_GlobalObjectTraceHook),
871};
872
873/// This is a simple `JSClass` for global objects, primarily intended for tests.
874pub static SIMPLE_GLOBAL_CLASS: JSClass = JSClass {
875    name: c"Global".as_ptr(),
876    flags: JSCLASS_IS_GLOBAL
877        | ((JSCLASS_GLOBAL_SLOT_COUNT & JSCLASS_RESERVED_SLOTS_MASK)
878            << JSCLASS_RESERVED_SLOTS_SHIFT),
879    cOps: &SIMPLE_GLOBAL_CLASS_OPS as *const JSClassOps,
880    spec: ptr::null(),
881    ext: ptr::null(),
882    oOps: ptr::null(),
883};
884
885#[inline]
886unsafe fn get_object_group(obj: *mut JSObject) -> *mut BaseShape {
887    assert!(!obj.is_null());
888    let obj = obj as *mut Object;
889    (*(*obj).shape).base
890}
891
892#[inline]
893pub unsafe fn get_object_class(obj: *mut JSObject) -> *const JSClass {
894    (*get_object_group(obj)).clasp as *const _
895}
896
897#[inline]
898pub unsafe fn get_object_realm(obj: *mut JSObject) -> *mut Realm {
899    (*get_object_group(obj)).realm
900}
901
902#[inline]
903pub unsafe fn get_context_realm(cx: *mut JSContext) -> *mut Realm {
904    let cx = cx as *mut RootingContext;
905    (*cx).realm_
906}
907
908#[inline]
909pub fn is_dom_class(class: &JSClass) -> bool {
910    class.flags & JSCLASS_IS_DOMJSCLASS != 0
911}
912
913#[inline]
914pub unsafe fn is_dom_object(obj: *mut JSObject) -> bool {
915    is_dom_class(&*get_object_class(obj))
916}
917
918#[inline]
919pub unsafe fn is_window(obj: *mut JSObject) -> bool {
920    (*get_object_class(obj)).flags & JSCLASS_IS_GLOBAL != 0 && IsWindowSlow(obj)
921}
922
923#[inline]
924pub unsafe fn try_to_outerize(mut rval: MutableHandleValue) {
925    let obj = rval.to_object();
926    if is_window(obj) {
927        let obj = ToWindowProxyIfWindowSlow(obj);
928        assert!(!obj.is_null());
929        rval.set(ObjectValue(&mut *obj));
930    }
931}
932
933#[inline]
934pub unsafe fn try_to_outerize_object(mut rval: MutableHandleObject) {
935    if is_window(*rval) {
936        let obj = ToWindowProxyIfWindowSlow(*rval);
937        assert!(!obj.is_null());
938        rval.set(obj);
939    }
940}
941
942#[inline]
943pub unsafe fn maybe_wrap_object(cx: *mut JSContext, mut obj: MutableHandleObject) {
944    if get_object_realm(*obj) != get_context_realm(cx) {
945        assert!(JS_WrapObject(cx, obj.reborrow().into()));
946    }
947    try_to_outerize_object(obj);
948}
949
950#[inline]
951pub unsafe fn maybe_wrap_object_value(cx: *mut JSContext, rval: MutableHandleValue) {
952    assert!(rval.is_object());
953    let obj = rval.to_object();
954    if get_object_realm(obj) != get_context_realm(cx) {
955        assert!(JS_WrapValue(cx, rval.into()));
956    } else if is_dom_object(obj) {
957        try_to_outerize(rval);
958    }
959}
960
961#[inline]
962pub unsafe fn maybe_wrap_object_or_null_value(cx: *mut JSContext, rval: MutableHandleValue) {
963    assert!(rval.is_object_or_null());
964    if !rval.is_null() {
965        maybe_wrap_object_value(cx, rval);
966    }
967}
968
969#[inline]
970pub unsafe fn maybe_wrap_value(cx: *mut JSContext, rval: MutableHandleValue) {
971    if rval.is_string() {
972        assert!(JS_WrapValue(cx, rval.into()));
973    } else if rval.is_object() {
974        maybe_wrap_object_value(cx, rval);
975    }
976}
977
978/// Like `JSJitInfo::new_bitfield_1`, but usable in `const` contexts.
979#[macro_export]
980macro_rules! new_jsjitinfo_bitfield_1 {
981    (
982        $type_: expr,
983        $aliasSet_: expr,
984        $returnType_: expr,
985        $isInfallible: expr,
986        $isMovable: expr,
987        $isEliminatable: expr,
988        $isAlwaysInSlot: expr,
989        $isLazilyCachedInSlot: expr,
990        $isTypedMethod: expr,
991        $slotIndex: expr,
992    ) => {
993        0 | (($type_ as u32) << 0u32)
994            | (($aliasSet_ as u32) << 4u32)
995            | (($returnType_ as u32) << 8u32)
996            | (($isInfallible as u32) << 16u32)
997            | (($isMovable as u32) << 17u32)
998            | (($isEliminatable as u32) << 18u32)
999            | (($isAlwaysInSlot as u32) << 19u32)
1000            | (($isLazilyCachedInSlot as u32) << 20u32)
1001            | (($isTypedMethod as u32) << 21u32)
1002            | (($slotIndex as u32) << 22u32)
1003    };
1004}
1005
1006#[derive(Debug, Default)]
1007pub struct ScriptedCaller {
1008    pub filename: String,
1009    pub line: u32,
1010    pub col: u32,
1011}
1012
1013pub unsafe fn describe_scripted_caller(cx: *mut JSContext) -> Result<ScriptedCaller, ()> {
1014    let mut buf = [0; 1024];
1015    let mut line = 0;
1016    let mut col = 0;
1017    if !DescribeScriptedCaller(cx, buf.as_mut_ptr(), buf.len(), &mut line, &mut col) {
1018        return Err(());
1019    }
1020    let filename = CStr::from_ptr((&buf) as *const _ as *const _);
1021    Ok(ScriptedCaller {
1022        filename: String::from_utf8_lossy(filename.to_bytes()).into_owned(),
1023        line,
1024        col,
1025    })
1026}
1027
1028pub struct CapturedJSStack<'a> {
1029    cx: *mut JSContext,
1030    stack: RootedGuard<'a, *mut JSObject>,
1031}
1032
1033impl<'a> CapturedJSStack<'a> {
1034    pub unsafe fn new(
1035        cx: *mut JSContext,
1036        mut guard: RootedGuard<'a, *mut JSObject>,
1037        max_frame_count: Option<u32>,
1038    ) -> Option<Self> {
1039        let ref mut stack_capture = MaybeUninit::uninit();
1040        match max_frame_count {
1041            None => JS_StackCapture_AllFrames(stack_capture.as_mut_ptr()),
1042            Some(count) => JS_StackCapture_MaxFrames(count, stack_capture.as_mut_ptr()),
1043        };
1044        let ref mut stack_capture = stack_capture.assume_init();
1045
1046        if !CaptureCurrentStack(
1047            cx,
1048            guard.handle_mut().raw(),
1049            stack_capture,
1050            HandleObject::null().into(),
1051        ) {
1052            None
1053        } else {
1054            Some(CapturedJSStack { cx, stack: guard })
1055        }
1056    }
1057
1058    pub fn as_string(&self, indent: Option<usize>, format: StackFormat) -> Option<String> {
1059        unsafe {
1060            let stack_handle = self.stack.handle();
1061            rooted!(in(self.cx) let mut js_string = ptr::null_mut::<JSString>());
1062            let mut string_handle = js_string.handle_mut();
1063
1064            if !BuildStackString(
1065                self.cx,
1066                ptr::null_mut(),
1067                stack_handle.into(),
1068                string_handle.raw(),
1069                indent.unwrap_or(0),
1070                format,
1071            ) {
1072                return None;
1073            }
1074
1075            Some(jsstr_to_string(self.cx, NonNull::new(string_handle.get())?))
1076        }
1077    }
1078
1079    /// Executes the provided closure for each frame on the js stack
1080    pub fn for_each_stack_frame<F>(&self, mut f: F)
1081    where
1082        F: FnMut(Handle<*mut JSObject>),
1083    {
1084        rooted!(in(self.cx) let mut current_element = self.stack.clone());
1085        rooted!(in(self.cx) let mut next_element = ptr::null_mut::<JSObject>());
1086
1087        loop {
1088            f(current_element.handle());
1089
1090            unsafe {
1091                let result = jsapi::GetSavedFrameParent(
1092                    self.cx,
1093                    ptr::null_mut(),
1094                    current_element.handle().into_handle(),
1095                    next_element.handle_mut().into_handle_mut(),
1096                    jsapi::SavedFrameSelfHosted::Include,
1097                );
1098
1099                if result != SavedFrameResult::Ok || next_element.is_null() {
1100                    return;
1101                }
1102            }
1103            current_element.set(next_element.get());
1104        }
1105    }
1106}
1107
1108#[macro_export]
1109macro_rules! capture_stack {
1110    (in($cx:expr) let $name:ident = with max depth($max_frame_count:expr)) => {
1111        rooted!(in($cx) let mut __obj = ::std::ptr::null_mut());
1112        let $name = $crate::rust::CapturedJSStack::new($cx, __obj, Some($max_frame_count));
1113    };
1114    (in($cx:expr) let $name:ident ) => {
1115        rooted!(in($cx) let mut __obj = ::std::ptr::null_mut());
1116        let $name = $crate::rust::CapturedJSStack::new($cx, __obj, None);
1117    }
1118}
1119
1120pub struct EnvironmentChain {
1121    chain: *mut crate::jsapi::JS::EnvironmentChain,
1122}
1123
1124impl EnvironmentChain {
1125    pub fn new(
1126        cx: *mut JSContext,
1127        support_unscopeables: crate::jsapi::JS::SupportUnscopables,
1128    ) -> Self {
1129        unsafe {
1130            Self {
1131                chain: crate::jsapi::glue::NewEnvironmentChain(cx, support_unscopeables),
1132            }
1133        }
1134    }
1135
1136    pub fn append(&self, obj: *mut JSObject) {
1137        unsafe {
1138            assert!(crate::jsapi::glue::AppendToEnvironmentChain(
1139                self.chain, obj
1140            ));
1141        }
1142    }
1143
1144    pub fn get(&self) -> *mut crate::jsapi::JS::EnvironmentChain {
1145        self.chain
1146    }
1147}
1148
1149impl Drop for EnvironmentChain {
1150    fn drop(&mut self) {
1151        unsafe {
1152            crate::jsapi::glue::DeleteEnvironmentChain(self.chain);
1153        }
1154    }
1155}
1156
1157/// Wrappers for JSAPI methods that accept lifetimed Handle and MutableHandle arguments
1158pub mod wrappers {
1159    macro_rules! wrap {
1160        // The invocation of @inner has the following form:
1161        // @inner (input args) <> (accumulator) <> unparsed tokens
1162        // when `unparsed tokens == \eps`, accumulator contains the final result
1163
1164        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: *const Handle<$gentype:ty>, $($rest:tt)*) => {
1165            wrap!(@inner $saved <> ($($acc,)* if $arg.is_null() { std::ptr::null() } else { &(*$arg).into() },) <> $($rest)*);
1166        };
1167        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: Handle<$gentype:ty>, $($rest:tt)*) => {
1168            wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1169        };
1170        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandle<$gentype:ty>, $($rest:tt)*) => {
1171            wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1172        };
1173        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: Handle, $($rest:tt)*) => {
1174            wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1175        };
1176        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandle, $($rest:tt)*) => {
1177            wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1178        };
1179        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleFunction , $($rest:tt)*) => {
1180            wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1181        };
1182        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleId , $($rest:tt)*) => {
1183            wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1184        };
1185        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleObject , $($rest:tt)*) => {
1186            wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1187        };
1188        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleScript , $($rest:tt)*) => {
1189            wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1190        };
1191        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleString , $($rest:tt)*) => {
1192            wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1193        };
1194        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleSymbol , $($rest:tt)*) => {
1195            wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1196        };
1197        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleValue , $($rest:tt)*) => {
1198            wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1199        };
1200        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleFunction , $($rest:tt)*) => {
1201            wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1202        };
1203        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleId , $($rest:tt)*) => {
1204            wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1205        };
1206        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleObject , $($rest:tt)*) => {
1207            wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1208        };
1209        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleScript , $($rest:tt)*) => {
1210            wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1211        };
1212        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleString , $($rest:tt)*) => {
1213            wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1214        };
1215        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleSymbol , $($rest:tt)*) => {
1216            wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1217        };
1218        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleValue , $($rest:tt)*) => {
1219            wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1220        };
1221        (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: $type:ty, $($rest:tt)*) => {
1222            wrap!(@inner $saved <> ($($acc,)* $arg,) <> $($rest)*);
1223        };
1224        (@inner ($module:tt: $func_name:ident ($($args:tt)*) -> $outtype:ty) <> ($($argexprs:expr,)*) <> ) => {
1225            #[inline]
1226            pub unsafe fn $func_name($($args)*) -> $outtype {
1227                $module::$func_name($($argexprs),*)
1228            }
1229        };
1230        ($module:tt: pub fn $func_name:ident($($args:tt)*) -> $outtype:ty) => {
1231            wrap!(@inner ($module: $func_name ($($args)*) -> $outtype) <> () <> $($args)* ,);
1232        };
1233        ($module:tt: pub fn $func_name:ident($($args:tt)*)) => {
1234            wrap!($module: pub fn $func_name($($args)*) -> ());
1235        }
1236    }
1237
1238    use super::*;
1239    use crate::glue;
1240    use crate::glue::EncodedStringCallback;
1241    use crate::jsapi;
1242    use crate::jsapi::jsid;
1243    use crate::jsapi::mozilla::Utf8Unit;
1244    use crate::jsapi::BigInt;
1245    use crate::jsapi::CallArgs;
1246    use crate::jsapi::CloneDataPolicy;
1247    use crate::jsapi::ColumnNumberOneOrigin;
1248    use crate::jsapi::CompartmentTransplantCallback;
1249    use crate::jsapi::EnvironmentChain;
1250    use crate::jsapi::JSONParseHandler;
1251    use crate::jsapi::Latin1Char;
1252    use crate::jsapi::PropertyKey;
1253    use crate::jsapi::TaggedColumnNumberOneOrigin;
1254    //use jsapi::DynamicImportStatus;
1255    use crate::jsapi::ESClass;
1256    use crate::jsapi::ExceptionStackBehavior;
1257    use crate::jsapi::ForOfIterator;
1258    use crate::jsapi::ForOfIterator_NonIterableBehavior;
1259    use crate::jsapi::HandleObjectVector;
1260    use crate::jsapi::InstantiateOptions;
1261    use crate::jsapi::JSClass;
1262    use crate::jsapi::JSErrorReport;
1263    use crate::jsapi::JSExnType;
1264    use crate::jsapi::JSFunctionSpecWithHelp;
1265    use crate::jsapi::JSJitInfo;
1266    use crate::jsapi::JSONWriteCallback;
1267    use crate::jsapi::JSPrincipals;
1268    use crate::jsapi::JSPropertySpec;
1269    use crate::jsapi::JSPropertySpec_Name;
1270    use crate::jsapi::JSProtoKey;
1271    use crate::jsapi::JSScript;
1272    use crate::jsapi::JSStructuredCloneData;
1273    use crate::jsapi::JSType;
1274    use crate::jsapi::ModuleErrorBehaviour;
1275    use crate::jsapi::ModuleType;
1276    use crate::jsapi::MutableHandleIdVector;
1277    use crate::jsapi::PromiseState;
1278    use crate::jsapi::PromiseUserInputEventHandlingState;
1279    use crate::jsapi::ReadOnlyCompileOptions;
1280    use crate::jsapi::Realm;
1281    use crate::jsapi::RefPtr;
1282    use crate::jsapi::RegExpFlags;
1283    use crate::jsapi::ScriptEnvironmentPreparer_Closure;
1284    use crate::jsapi::SourceText;
1285    use crate::jsapi::StackCapture;
1286    use crate::jsapi::Stencil;
1287    use crate::jsapi::StructuredCloneScope;
1288    use crate::jsapi::Symbol;
1289    use crate::jsapi::SymbolCode;
1290    use crate::jsapi::TranscodeBuffer;
1291    use crate::jsapi::TwoByteChars;
1292    use crate::jsapi::UniqueChars;
1293    use crate::jsapi::Value;
1294    use crate::jsapi::WasmModule;
1295    use crate::jsapi::{ElementAdder, IsArrayAnswer, PropertyDescriptor};
1296    use crate::jsapi::{JSContext, JSFunction, JSNative, JSObject, JSString};
1297    use crate::jsapi::{
1298        JSStructuredCloneCallbacks, JSStructuredCloneReader, JSStructuredCloneWriter,
1299    };
1300    use crate::jsapi::{MallocSizeOf, ObjectOpResult, ObjectPrivateVisitor, TabSizes};
1301    use crate::jsapi::{SavedFrameResult, SavedFrameSelfHosted};
1302    include!("jsapi_wrappers.in.rs");
1303    include!("glue_wrappers.in.rs");
1304}