1use 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 self::wrappers::{
21 StackGCVectorStringAtIndex, StackGCVectorStringLength, StackGCVectorValueAtIndex,
22 StackGCVectorValueLength,
23};
24use crate::consts::{JSCLASS_GLOBAL_SLOT_COUNT, JSCLASS_RESERVED_SLOTS_MASK};
25use crate::consts::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
26use crate::conversions::jsstr_to_string;
27use crate::default_heapsize;
28pub use crate::gc::*;
29use crate::glue::AppendToRootedObjectVector;
30use crate::glue::{CreateRootedIdVector, CreateRootedObjectVector};
31use crate::glue::{
32 DeleteCompileOptions, DeleteRootedObjectVector, DescribeScriptedCaller, DestroyRootedIdVector,
33};
34use crate::glue::{DeleteJSAutoStructuredCloneBuffer, NewJSAutoStructuredCloneBuffer};
35use crate::glue::{
36 GetIdVectorAddress, GetObjectVectorAddress, NewCompileOptions, SliceRootedIdVector,
37};
38use crate::jsapi;
39use crate::jsapi::glue::{DeleteRealmOptions, JS_Init, JS_NewRealmOptions};
40use crate::jsapi::js;
41use crate::jsapi::js::frontend::InitialStencilAndDelazifications;
42use crate::jsapi::mozilla::Utf8Unit;
43use crate::jsapi::shadow::BaseShape;
44use crate::jsapi::HandleObjectVector as RawHandleObjectVector;
45use crate::jsapi::HandleValue as RawHandleValue;
46use crate::jsapi::JS_AddExtraGCRootsTracer;
47use crate::jsapi::MutableHandleIdVector as RawMutableHandleIdVector;
48use crate::jsapi::{already_AddRefed, jsid};
49use crate::jsapi::{BuildStackString, CaptureCurrentStack, StackFormat};
50use crate::jsapi::{Evaluate2, HandleValueArray, StencilRelease};
51use crate::jsapi::{InitSelfHostedCode, IsWindowSlow};
52use crate::jsapi::{
53 JSAutoRealm, JS_SetGCParameter, JS_SetNativeStackQuota, JS_WrapObject, JS_WrapValue,
54};
55use crate::jsapi::{JSAutoStructuredCloneBuffer, JSStructuredCloneCallbacks, StructuredCloneScope};
56use crate::jsapi::{JSClass, JSClassOps, JSContext, Realm, JSCLASS_RESERVED_SLOTS_SHIFT};
57use crate::jsapi::{JSErrorReport, JSFunctionSpec, JSGCParamKey};
58use crate::jsapi::{JSObject, JSPropertySpec, JSRuntime};
59use crate::jsapi::{JSString, Object, PersistentRootedIdVector};
60use crate::jsapi::{JS_DefineFunctions, JS_DefineProperties, JS_DestroyContext, JS_ShutDown};
61use crate::jsapi::{JS_EnumerateStandardClasses, JS_GetRuntime, JS_GlobalObjectTraceHook};
62use crate::jsapi::{JS_MayResolveStandardClass, JS_NewContext, JS_ResolveStandardClass};
63use crate::jsapi::{JS_RequestInterruptCallback, JS_RequestInterruptCallbackCanWait};
64use crate::jsapi::{JS_StackCapture_AllFrames, JS_StackCapture_MaxFrames};
65use crate::jsapi::{PersistentRootedObjectVector, ReadOnlyCompileOptions, RootingContext};
66use crate::jsapi::{SetWarningReporter, SourceText, ToBooleanSlow};
67use crate::jsapi::{ToInt32Slow, ToInt64Slow, ToNumberSlow, ToStringSlow, ToUint16Slow};
68use crate::jsapi::{ToUint32Slow, ToUint64Slow, ToWindowProxyIfWindowSlow};
69use crate::jsval::{JSVal, ObjectValue};
70use crate::panic::maybe_resume_unwind;
71use log::{debug, warn};
72use mozjs_sys::jsapi::JS::SavedFrameResult;
73pub use mozjs_sys::jsgc::{GCMethods, IntoHandle, IntoMutableHandle};
74pub use mozjs_sys::trace::Traceable as Trace;
75
76use crate::rooted;
77
78const STACK_QUOTA: usize = 128 * 8 * 1024;
82
83const SYSTEM_CODE_BUFFER: usize = 10 * 1024;
109
110const TRUSTED_SCRIPT_BUFFER: usize = 8 * 12800;
112
113trait ToResult {
114 fn to_result(self) -> Result<(), ()>;
115}
116
117impl ToResult for bool {
118 fn to_result(self) -> Result<(), ()> {
119 if self {
120 Ok(())
121 } else {
122 Err(())
123 }
124 }
125}
126
127pub struct RealmOptions(*mut jsapi::RealmOptions);
131
132impl Deref for RealmOptions {
133 type Target = jsapi::RealmOptions;
134 fn deref(&self) -> &Self::Target {
135 unsafe { &*self.0 }
136 }
137}
138
139impl DerefMut for RealmOptions {
140 fn deref_mut(&mut self) -> &mut Self::Target {
141 unsafe { &mut *self.0 }
142 }
143}
144
145impl Default for RealmOptions {
146 fn default() -> RealmOptions {
147 RealmOptions(unsafe { JS_NewRealmOptions() })
148 }
149}
150
151impl Drop for RealmOptions {
152 fn drop(&mut self) {
153 unsafe { DeleteRealmOptions(self.0) }
154 }
155}
156
157thread_local!(static CONTEXT: Cell<Option<NonNull<JSContext>>> = Cell::new(None));
158
159#[derive(PartialEq)]
160enum EngineState {
161 Uninitialized,
162 InitFailed,
163 Initialized,
164 ShutDown,
165}
166
167static ENGINE_STATE: Mutex<EngineState> = Mutex::new(EngineState::Uninitialized);
168
169#[derive(Debug)]
170pub enum JSEngineError {
171 AlreadyInitialized,
172 AlreadyShutDown,
173 InitFailed,
174}
175
176pub struct JSEngine {
180 outstanding_handles: Arc<AtomicU32>,
182 marker: PhantomData<*mut ()>,
184}
185
186pub struct JSEngineHandle(Arc<AtomicU32>);
187
188impl Clone for JSEngineHandle {
189 fn clone(&self) -> JSEngineHandle {
190 self.0.fetch_add(1, Ordering::SeqCst);
191 JSEngineHandle(self.0.clone())
192 }
193}
194
195impl Drop for JSEngineHandle {
196 fn drop(&mut self) {
197 self.0.fetch_sub(1, Ordering::SeqCst);
198 }
199}
200
201impl JSEngine {
202 pub fn init() -> Result<JSEngine, JSEngineError> {
204 let mut state = ENGINE_STATE.lock().unwrap();
205 match *state {
206 EngineState::Initialized => return Err(JSEngineError::AlreadyInitialized),
207 EngineState::InitFailed => return Err(JSEngineError::InitFailed),
208 EngineState::ShutDown => return Err(JSEngineError::AlreadyShutDown),
209 EngineState::Uninitialized => (),
210 }
211 if unsafe { !JS_Init() } {
212 *state = EngineState::InitFailed;
213 Err(JSEngineError::InitFailed)
214 } else {
215 *state = EngineState::Initialized;
216 Ok(JSEngine {
217 outstanding_handles: Arc::new(AtomicU32::new(0)),
218 marker: PhantomData,
219 })
220 }
221 }
222
223 pub fn can_shutdown(&self) -> bool {
224 self.outstanding_handles.load(Ordering::SeqCst) == 0
225 }
226
227 pub fn handle(&self) -> JSEngineHandle {
229 self.outstanding_handles.fetch_add(1, Ordering::SeqCst);
230 JSEngineHandle(self.outstanding_handles.clone())
231 }
232}
233
234impl Drop for JSEngine {
237 fn drop(&mut self) {
238 let mut state = ENGINE_STATE.lock().unwrap();
239 if *state == EngineState::Initialized {
240 assert_eq!(
241 self.outstanding_handles.load(Ordering::SeqCst),
242 0,
243 "There are outstanding JS engine handles"
244 );
245 *state = EngineState::ShutDown;
246 unsafe {
247 JS_ShutDown();
248 }
249 }
250 }
251}
252
253pub fn transform_str_to_source_text(source: &str) -> SourceText<Utf8Unit> {
254 SourceText {
255 units_: source.as_ptr() as *const _,
256 length_: source.len() as u32,
257 ownsUnits_: false,
258 _phantom_0: PhantomData,
259 }
260}
261
262pub fn transform_u16_to_source_text(source: &[u16]) -> SourceText<u16> {
263 SourceText {
264 units_: source.as_ptr() as *const _,
265 length_: source.len() as u32,
266 ownsUnits_: false,
267 _phantom_0: PhantomData,
268 }
269}
270
271pub struct ParentRuntime {
275 parent: *mut JSRuntime,
277 engine: JSEngineHandle,
279 children_of_parent: Arc<()>,
281}
282unsafe impl Send for ParentRuntime {}
283
284pub struct Runtime {
286 cx: crate::context::JSContext,
288 engine: JSEngineHandle,
290 _parent_child_count: Option<Arc<()>>,
295 outstanding_children: Arc<()>,
301 thread_safe_handle: Arc<RwLock<Option<NonNull<JSContext>>>>,
305}
306
307impl Runtime {
308 pub fn get() -> Option<NonNull<JSContext>> {
312 CONTEXT.with(|context| context.get())
313 }
314
315 pub fn thread_safe_js_context(&self) -> ThreadSafeJSContext {
317 ThreadSafeJSContext(self.thread_safe_handle.clone())
320 }
321
322 pub fn new(engine: JSEngineHandle) -> Runtime {
324 unsafe { Self::create(engine, None) }
325 }
326
327 pub fn prepare_for_new_child(&self) -> ParentRuntime {
333 ParentRuntime {
334 parent: self.rt(),
335 engine: self.engine.clone(),
336 children_of_parent: self.outstanding_children.clone(),
337 }
338 }
339
340 pub unsafe fn create_with_parent(parent: ParentRuntime) -> Runtime {
348 Self::create(parent.engine.clone(), Some(parent))
349 }
350
351 unsafe fn create(engine: JSEngineHandle, parent: Option<ParentRuntime>) -> Runtime {
352 let parent_runtime = parent.as_ref().map_or(ptr::null_mut(), |r| r.parent);
353 let js_context = NonNull::new(JS_NewContext(
354 default_heapsize + (ChunkSize as u32),
355 parent_runtime,
356 ))
357 .unwrap();
358
359 JS_SetGCParameter(js_context.as_ptr(), JSGCParamKey::JSGC_MAX_BYTES, u32::MAX);
365
366 JS_AddExtraGCRootsTracer(js_context.as_ptr(), Some(trace_traceables), ptr::null_mut());
367
368 JS_SetNativeStackQuota(
369 js_context.as_ptr(),
370 STACK_QUOTA,
371 STACK_QUOTA - SYSTEM_CODE_BUFFER,
372 STACK_QUOTA - SYSTEM_CODE_BUFFER - TRUSTED_SCRIPT_BUFFER,
373 );
374
375 CONTEXT.with(|context| {
376 assert!(context.get().is_none());
377 context.set(Some(js_context));
378 });
379
380 #[cfg(target_pointer_width = "64")]
381 let cache = crate::jsapi::__BindgenOpaqueArray::<u64, 2>::default();
382 #[cfg(target_pointer_width = "32")]
383 let cache = crate::jsapi::__BindgenOpaqueArray::<u32, 2>::default();
384
385 InitSelfHostedCode(js_context.as_ptr(), cache, None);
386
387 SetWarningReporter(js_context.as_ptr(), Some(report_warning));
388
389 Runtime {
390 engine,
391 _parent_child_count: parent.map(|p| p.children_of_parent),
392 cx: crate::context::JSContext::from_ptr(js_context),
393 outstanding_children: Arc::new(()),
394 thread_safe_handle: Arc::new(RwLock::new(Some(js_context))),
395 }
396 }
397
398 pub fn rt(&self) -> *mut JSRuntime {
400 unsafe { JS_GetRuntime(self.cx.raw_cx_no_gc()) }
402 }
403
404 pub fn cx<'rt>(&'rt mut self) -> &'rt mut crate::context::JSContext {
406 &mut self.cx
407 }
408
409 pub fn cx_no_gc<'rt>(&'rt self) -> &'rt crate::context::JSContext {
411 &self.cx
412 }
413
414 pub fn evaluate_script(
415 &mut self,
416 glob: HandleObject,
417 script: &str,
418 rval: MutableHandleValue,
419 options: CompileOptionsWrapper,
420 ) -> Result<(), ()> {
421 evaluate_script(self.cx(), glob, script, rval, options)
422 }
423
424 pub fn new_compile_options(&self, filename: &str, line: u32) -> CompileOptionsWrapper {
425 unsafe { CompileOptionsWrapper::new(self.cx_no_gc().raw_cx_no_gc(), filename, line) }
427 }
428}
429
430pub fn evaluate_script(
431 cx: &mut crate::context::JSContext,
432 glob: HandleObject,
433 script: &str,
434 rval: MutableHandleValue,
435 options: CompileOptionsWrapper,
436) -> Result<(), ()> {
437 debug!(
438 "Evaluating script from {} with content {}",
439 options.filename(),
440 script
441 );
442
443 let _ac = JSAutoRealm::new(unsafe { cx.raw_cx() }, glob.get());
444
445 unsafe {
446 let mut source = transform_str_to_source_text(&script);
447 if !Evaluate2(cx.raw_cx(), options.ptr, &mut source, rval.into()) {
448 debug!("...err!");
449 maybe_resume_unwind();
450 Err(())
451 } else {
452 debug!("...ok!");
455 Ok(())
456 }
457 }
458}
459
460impl Drop for Runtime {
461 fn drop(&mut self) {
462 self.thread_safe_handle.write().unwrap().take();
463 assert!(
464 Arc::get_mut(&mut self.outstanding_children).is_some(),
465 "This runtime still has live children."
466 );
467 unsafe {
468 JS_DestroyContext(self.cx.raw_cx());
469
470 CONTEXT.with(|context| {
471 assert!(context.take().is_some());
472 });
473 }
474 }
475}
476
477#[derive(Clone)]
481pub struct ThreadSafeJSContext(Arc<RwLock<Option<NonNull<JSContext>>>>);
482
483unsafe impl Send for ThreadSafeJSContext {}
484unsafe impl Sync for ThreadSafeJSContext {}
485
486impl ThreadSafeJSContext {
487 pub fn request_interrupt_callback(&self) {
491 if let Some(cx) = self.0.read().unwrap().as_ref() {
492 unsafe {
493 JS_RequestInterruptCallback(cx.as_ptr());
494 }
495 }
496 }
497
498 pub fn request_interrupt_callback_can_wait(&self) {
502 if let Some(cx) = self.0.read().unwrap().as_ref() {
503 unsafe {
504 JS_RequestInterruptCallbackCanWait(cx.as_ptr());
505 }
506 }
507 }
508}
509
510const ChunkShift: usize = 20;
511const ChunkSize: usize = 1 << ChunkShift;
512
513#[cfg(target_pointer_width = "32")]
514const ChunkLocationOffset: usize = ChunkSize - 2 * 4 - 8;
515
516pub struct RootedObjectVectorWrapper {
520 pub ptr: *mut PersistentRootedObjectVector,
521}
522
523impl RootedObjectVectorWrapper {
524 pub fn new(cx: *mut JSContext) -> RootedObjectVectorWrapper {
525 RootedObjectVectorWrapper {
526 ptr: unsafe { CreateRootedObjectVector(cx) },
527 }
528 }
529
530 pub fn append(&self, obj: *mut JSObject) -> bool {
531 unsafe { AppendToRootedObjectVector(self.ptr, obj) }
532 }
533
534 pub fn handle(&self) -> RawHandleObjectVector {
535 RawHandleObjectVector {
536 ptr: unsafe { GetObjectVectorAddress(self.ptr) },
537 }
538 }
539}
540
541impl Drop for RootedObjectVectorWrapper {
542 fn drop(&mut self) {
543 unsafe { DeleteRootedObjectVector(self.ptr) }
544 }
545}
546
547pub struct CompileOptionsWrapper {
548 pub ptr: *mut ReadOnlyCompileOptions,
549 filename: CString,
550}
551
552impl CompileOptionsWrapper {
553 pub unsafe fn new(cx: *mut JSContext, filename: &str, line: u32) -> Self {
557 let filename = CString::new(filename.as_bytes()).unwrap();
558 let ptr = NewCompileOptions(cx, filename.as_ptr(), line);
559 assert!(!ptr.is_null());
560 Self { ptr, filename }
561 }
562
563 pub fn filename(&self) -> &str {
564 self.filename.to_str().expect("Guaranteed by new")
565 }
566
567 pub fn set_introduction_type(&mut self, introduction_type: &'static CStr) {
568 unsafe {
569 (*self.ptr)._base.introductionType = introduction_type.as_ptr();
570 }
571 }
572}
573
574impl Drop for CompileOptionsWrapper {
575 fn drop(&mut self) {
576 unsafe { DeleteCompileOptions(self.ptr) }
577 }
578}
579
580pub struct JSAutoStructuredCloneBufferWrapper {
581 ptr: NonNull<JSAutoStructuredCloneBuffer>,
582}
583
584impl JSAutoStructuredCloneBufferWrapper {
585 pub unsafe fn new(
586 scope: StructuredCloneScope,
587 callbacks: *const JSStructuredCloneCallbacks,
588 ) -> Self {
589 let raw_ptr = NewJSAutoStructuredCloneBuffer(scope, callbacks);
590 Self {
591 ptr: NonNull::new(raw_ptr).unwrap(),
592 }
593 }
594
595 pub fn as_raw_ptr(&self) -> *mut JSAutoStructuredCloneBuffer {
596 self.ptr.as_ptr()
597 }
598}
599
600impl Drop for JSAutoStructuredCloneBufferWrapper {
601 fn drop(&mut self) {
602 unsafe {
603 DeleteJSAutoStructuredCloneBuffer(self.ptr.as_ptr());
604 }
605 }
606}
607
608pub struct Stencil {
609 inner: already_AddRefed<InitialStencilAndDelazifications>,
610}
611
612impl Drop for Stencil {
616 fn drop(&mut self) {
617 if self.is_null() {
618 return;
619 }
620 unsafe {
621 StencilRelease(self.inner.mRawPtr);
622 }
623 }
624}
625
626impl Deref for Stencil {
627 type Target = *mut InitialStencilAndDelazifications;
628
629 fn deref(&self) -> &Self::Target {
630 &self.inner.mRawPtr
631 }
632}
633
634impl Stencil {
635 pub fn is_null(&self) -> bool {
636 self.inner.mRawPtr.is_null()
637 }
638}
639
640#[inline]
644pub unsafe fn ToBoolean(v: HandleValue) -> bool {
645 let val = *v.ptr;
646
647 if val.is_boolean() {
648 return val.to_boolean();
649 }
650
651 if val.is_int32() {
652 return val.to_int32() != 0;
653 }
654
655 if val.is_null_or_undefined() {
656 return false;
657 }
658
659 if val.is_double() {
660 let d = val.to_double();
661 return !d.is_nan() && d != 0f64;
662 }
663
664 if val.is_symbol() {
665 return true;
666 }
667
668 ToBooleanSlow(v.into())
669}
670
671#[inline]
672pub unsafe fn ToNumber(cx: *mut JSContext, v: HandleValue) -> Result<f64, ()> {
673 let val = *v.ptr;
674 if val.is_number() {
675 return Ok(val.to_number());
676 }
677
678 let mut out = Default::default();
679 if ToNumberSlow(cx, v.into_handle(), &mut out) {
680 Ok(out)
681 } else {
682 Err(())
683 }
684}
685
686#[inline]
687unsafe fn convert_from_int32<T: Default + Copy>(
688 cx: *mut JSContext,
689 v: HandleValue,
690 conv_fn: unsafe extern "C" fn(*mut JSContext, RawHandleValue, *mut T) -> bool,
691) -> Result<T, ()> {
692 let val = *v.ptr;
693 if val.is_int32() {
694 let intval: i64 = val.to_int32() as i64;
695 let intval = *(&intval as *const i64 as *const T);
697 return Ok(intval);
698 }
699
700 let mut out = Default::default();
701 if conv_fn(cx, v.into(), &mut out) {
702 Ok(out)
703 } else {
704 Err(())
705 }
706}
707
708#[inline]
709pub unsafe fn ToInt32(cx: *mut JSContext, v: HandleValue) -> Result<i32, ()> {
710 convert_from_int32::<i32>(cx, v, ToInt32Slow)
711}
712
713#[inline]
714pub unsafe fn ToUint32(cx: *mut JSContext, v: HandleValue) -> Result<u32, ()> {
715 convert_from_int32::<u32>(cx, v, ToUint32Slow)
716}
717
718#[inline]
719pub unsafe fn ToUint16(cx: *mut JSContext, v: HandleValue) -> Result<u16, ()> {
720 convert_from_int32::<u16>(cx, v, ToUint16Slow)
721}
722
723#[inline]
724pub unsafe fn ToInt64(cx: *mut JSContext, v: HandleValue) -> Result<i64, ()> {
725 convert_from_int32::<i64>(cx, v, ToInt64Slow)
726}
727
728#[inline]
729pub unsafe fn ToUint64(cx: *mut JSContext, v: HandleValue) -> Result<u64, ()> {
730 convert_from_int32::<u64>(cx, v, ToUint64Slow)
731}
732
733#[inline]
734pub unsafe fn ToString(cx: *mut JSContext, v: HandleValue) -> *mut JSString {
735 let val = *v.ptr;
736 if val.is_string() {
737 return val.to_string();
738 }
739
740 ToStringSlow(cx, v.into())
741}
742
743pub unsafe fn ToWindowProxyIfWindow(obj: *mut JSObject) -> *mut JSObject {
744 if is_window(obj) {
745 ToWindowProxyIfWindowSlow(obj)
746 } else {
747 obj
748 }
749}
750
751pub unsafe extern "C" fn report_warning(_cx: *mut JSContext, report: *mut JSErrorReport) {
752 fn latin1_to_string(bytes: &[u8]) -> String {
753 bytes
754 .iter()
755 .map(|c| char::from_u32(*c as u32).unwrap())
756 .collect()
757 }
758
759 let fnptr = (*report)._base.filename.data_;
760 let fname = if !fnptr.is_null() {
761 let c_str = CStr::from_ptr(fnptr);
762 latin1_to_string(c_str.to_bytes())
763 } else {
764 "none".to_string()
765 };
766
767 let lineno = (*report)._base.lineno;
768 let column = (*report)._base.column._base;
769
770 let msg_ptr = (*report)._base.message_.data_ as *const u8;
771 let msg_len = (0usize..)
772 .find(|&i| *msg_ptr.offset(i as isize) == 0)
773 .unwrap();
774 let msg_slice = slice::from_raw_parts(msg_ptr, msg_len);
775 let msg = str::from_utf8_unchecked(msg_slice);
776
777 warn!("Warning at {}:{}:{}: {}\n", fname, lineno, column, msg);
778}
779
780pub struct IdVector(*mut PersistentRootedIdVector);
781
782impl IdVector {
783 pub unsafe fn new(cx: *mut JSContext) -> IdVector {
784 let vector = CreateRootedIdVector(cx);
785 assert!(!vector.is_null());
786 IdVector(vector)
787 }
788
789 pub fn handle_mut(&mut self) -> RawMutableHandleIdVector {
790 RawMutableHandleIdVector {
791 ptr: unsafe { GetIdVectorAddress(self.0) },
792 }
793 }
794}
795
796impl Drop for IdVector {
797 fn drop(&mut self) {
798 unsafe { DestroyRootedIdVector(self.0) }
799 }
800}
801
802impl Deref for IdVector {
803 type Target = [jsid];
804
805 fn deref(&self) -> &[jsid] {
806 unsafe {
807 let mut length = 0;
808 let pointer = SliceRootedIdVector(self.0, &mut length);
809 slice::from_raw_parts(pointer, length)
810 }
811 }
812}
813
814pub unsafe fn define_methods(
830 cx: *mut JSContext,
831 obj: HandleObject,
832 methods: &'static [JSFunctionSpec],
833) -> Result<(), ()> {
834 assert!({
835 match methods.last() {
836 Some(&JSFunctionSpec {
837 name,
838 call,
839 nargs,
840 flags,
841 selfHostedName,
842 }) => {
843 name.string_.is_null()
844 && call.is_zeroed()
845 && nargs == 0
846 && flags == 0
847 && selfHostedName.is_null()
848 }
849 None => false,
850 }
851 });
852
853 JS_DefineFunctions(cx, obj.into(), methods.as_ptr()).to_result()
854}
855
856pub unsafe fn define_properties(
872 cx: *mut JSContext,
873 obj: HandleObject,
874 properties: &'static [JSPropertySpec],
875) -> Result<(), ()> {
876 assert!({
877 match properties.last() {
878 Some(spec) => spec.is_zeroed(),
879 None => false,
880 }
881 });
882
883 JS_DefineProperties(cx, obj.into(), properties.as_ptr()).to_result()
884}
885
886static SIMPLE_GLOBAL_CLASS_OPS: JSClassOps = JSClassOps {
887 addProperty: None,
888 delProperty: None,
889 enumerate: Some(JS_EnumerateStandardClasses),
890 newEnumerate: None,
891 resolve: Some(JS_ResolveStandardClass),
892 mayResolve: Some(JS_MayResolveStandardClass),
893 finalize: None,
894 call: None,
895 construct: None,
896 trace: Some(JS_GlobalObjectTraceHook),
897};
898
899pub static SIMPLE_GLOBAL_CLASS: JSClass = JSClass {
901 name: c"Global".as_ptr(),
902 flags: JSCLASS_IS_GLOBAL
903 | ((JSCLASS_GLOBAL_SLOT_COUNT & JSCLASS_RESERVED_SLOTS_MASK)
904 << JSCLASS_RESERVED_SLOTS_SHIFT),
905 cOps: &SIMPLE_GLOBAL_CLASS_OPS as *const JSClassOps,
906 spec: ptr::null(),
907 ext: ptr::null(),
908 oOps: ptr::null(),
909};
910
911#[inline]
912unsafe fn get_object_group(obj: *mut JSObject) -> *mut BaseShape {
913 assert!(!obj.is_null());
914 let obj = obj as *mut Object;
915 (*(*obj).shape).base
916}
917
918#[inline]
919pub unsafe fn get_object_class(obj: *mut JSObject) -> *const JSClass {
920 (*get_object_group(obj)).clasp as *const _
921}
922
923#[inline]
924pub unsafe fn get_object_realm(obj: *mut JSObject) -> *mut Realm {
925 (*get_object_group(obj)).realm
926}
927
928#[inline]
929pub unsafe fn get_context_realm(cx: *mut JSContext) -> *mut Realm {
930 let cx = cx as *mut RootingContext;
931 (*cx).realm_
932}
933
934#[inline]
935pub fn is_dom_class(class: &JSClass) -> bool {
936 class.flags & JSCLASS_IS_DOMJSCLASS != 0
937}
938
939#[inline]
940pub unsafe fn is_dom_object(obj: *mut JSObject) -> bool {
941 is_dom_class(&*get_object_class(obj))
942}
943
944#[inline]
945pub unsafe fn is_window(obj: *mut JSObject) -> bool {
946 (*get_object_class(obj)).flags & JSCLASS_IS_GLOBAL != 0 && IsWindowSlow(obj)
947}
948
949#[inline]
950pub unsafe fn try_to_outerize(mut rval: MutableHandleValue) {
951 let obj = rval.to_object();
952 if is_window(obj) {
953 let obj = ToWindowProxyIfWindowSlow(obj);
954 assert!(!obj.is_null());
955 rval.set(ObjectValue(&mut *obj));
956 }
957}
958
959#[inline]
960pub unsafe fn try_to_outerize_object(mut rval: MutableHandleObject) {
961 if is_window(*rval) {
962 let obj = ToWindowProxyIfWindowSlow(*rval);
963 assert!(!obj.is_null());
964 rval.set(obj);
965 }
966}
967
968#[inline]
969pub unsafe fn maybe_wrap_object(cx: *mut JSContext, mut obj: MutableHandleObject) {
970 if get_object_realm(*obj) != get_context_realm(cx) {
971 assert!(JS_WrapObject(cx, obj.reborrow().into()));
972 }
973 try_to_outerize_object(obj);
974}
975
976#[inline]
977pub unsafe fn maybe_wrap_object_value(cx: *mut JSContext, rval: MutableHandleValue) {
978 assert!(rval.is_object());
979 let obj = rval.to_object();
980 if get_object_realm(obj) != get_context_realm(cx) {
981 assert!(JS_WrapValue(cx, rval.into()));
982 } else if is_dom_object(obj) {
983 try_to_outerize(rval);
984 }
985}
986
987#[inline]
988pub unsafe fn maybe_wrap_object_or_null_value(cx: *mut JSContext, rval: MutableHandleValue) {
989 assert!(rval.is_object_or_null());
990 if !rval.is_null() {
991 maybe_wrap_object_value(cx, rval);
992 }
993}
994
995#[inline]
996pub unsafe fn maybe_wrap_value(cx: *mut JSContext, rval: MutableHandleValue) {
997 if rval.is_string() {
998 assert!(JS_WrapValue(cx, rval.into()));
999 } else if rval.is_object() {
1000 maybe_wrap_object_value(cx, rval);
1001 }
1002}
1003
1004#[macro_export]
1006macro_rules! new_jsjitinfo_bitfield_1 {
1007 (
1008 $type_: expr,
1009 $aliasSet_: expr,
1010 $returnType_: expr,
1011 $isInfallible: expr,
1012 $isMovable: expr,
1013 $isEliminatable: expr,
1014 $isAlwaysInSlot: expr,
1015 $isLazilyCachedInSlot: expr,
1016 $isTypedMethod: expr,
1017 $slotIndex: expr,
1018 ) => {
1019 0 | (($type_ as u32) << 0u32)
1020 | (($aliasSet_ as u32) << 4u32)
1021 | (($returnType_ as u32) << 8u32)
1022 | (($isInfallible as u32) << 16u32)
1023 | (($isMovable as u32) << 17u32)
1024 | (($isEliminatable as u32) << 18u32)
1025 | (($isAlwaysInSlot as u32) << 19u32)
1026 | (($isLazilyCachedInSlot as u32) << 20u32)
1027 | (($isTypedMethod as u32) << 21u32)
1028 | (($slotIndex as u32) << 22u32)
1029 };
1030}
1031
1032#[derive(Debug, Default)]
1033pub struct ScriptedCaller {
1034 pub filename: String,
1035 pub line: u32,
1036 pub col: u32,
1037}
1038
1039pub unsafe fn describe_scripted_caller(cx: *mut JSContext) -> Result<ScriptedCaller, ()> {
1040 let mut buf = [0; 1024];
1041 let mut line = 0;
1042 let mut col = 0;
1043 if !DescribeScriptedCaller(cx, buf.as_mut_ptr(), buf.len(), &mut line, &mut col) {
1044 return Err(());
1045 }
1046 let filename = CStr::from_ptr((&buf) as *const _ as *const _);
1047 Ok(ScriptedCaller {
1048 filename: String::from_utf8_lossy(filename.to_bytes()).into_owned(),
1049 line,
1050 col,
1051 })
1052}
1053
1054pub struct CapturedJSStack<'a> {
1055 cx: *mut JSContext,
1056 stack: RootedGuard<'a, *mut JSObject>,
1057}
1058
1059impl<'a> CapturedJSStack<'a> {
1060 pub unsafe fn new(
1061 cx: *mut JSContext,
1062 mut guard: RootedGuard<'a, *mut JSObject>,
1063 max_frame_count: Option<u32>,
1064 ) -> Option<Self> {
1065 let ref mut stack_capture = MaybeUninit::uninit();
1066 match max_frame_count {
1067 None => JS_StackCapture_AllFrames(stack_capture.as_mut_ptr()),
1068 Some(count) => JS_StackCapture_MaxFrames(count, stack_capture.as_mut_ptr()),
1069 };
1070 let ref mut stack_capture = stack_capture.assume_init();
1071
1072 if !CaptureCurrentStack(
1073 cx,
1074 guard.handle_mut().raw(),
1075 stack_capture,
1076 HandleObject::null().into(),
1077 ) {
1078 None
1079 } else {
1080 Some(CapturedJSStack { cx, stack: guard })
1081 }
1082 }
1083
1084 pub fn as_string(&self, indent: Option<usize>, format: StackFormat) -> Option<String> {
1085 unsafe {
1086 let stack_handle = self.stack.handle();
1087 rooted!(in(self.cx) let mut js_string = ptr::null_mut::<JSString>());
1088 let mut string_handle = js_string.handle_mut();
1089
1090 if !BuildStackString(
1091 self.cx,
1092 ptr::null_mut(),
1093 stack_handle.into(),
1094 string_handle.raw(),
1095 indent.unwrap_or(0),
1096 format,
1097 ) {
1098 return None;
1099 }
1100
1101 Some(jsstr_to_string(self.cx, NonNull::new(string_handle.get())?))
1102 }
1103 }
1104
1105 pub fn for_each_stack_frame<F>(&self, mut f: F)
1107 where
1108 F: FnMut(Handle<*mut JSObject>),
1109 {
1110 rooted!(in(self.cx) let mut current_element = self.stack.clone());
1111 rooted!(in(self.cx) let mut next_element = ptr::null_mut::<JSObject>());
1112
1113 loop {
1114 f(current_element.handle());
1115
1116 unsafe {
1117 let result = jsapi::GetSavedFrameParent(
1118 self.cx,
1119 ptr::null_mut(),
1120 current_element.handle().into_handle(),
1121 next_element.handle_mut().into_handle_mut(),
1122 jsapi::SavedFrameSelfHosted::Include,
1123 );
1124
1125 if result != SavedFrameResult::Ok || next_element.is_null() {
1126 return;
1127 }
1128 }
1129 current_element.set(next_element.get());
1130 }
1131 }
1132}
1133
1134#[macro_export]
1135macro_rules! capture_stack {
1136 (&in($cx:expr) $($t:tt)*) => {
1137 capture_stack!(in(unsafe {$cx.raw_cx_no_gc()}) $($t)*);
1138 };
1139 (in($cx:expr) let $name:ident = with max depth($max_frame_count:expr)) => {
1140 rooted!(in($cx) let mut __obj = ::std::ptr::null_mut());
1141 let $name = $crate::rust::CapturedJSStack::new($cx, __obj, Some($max_frame_count));
1142 };
1143 (in($cx:expr) let $name:ident ) => {
1144 rooted!(in($cx) let mut __obj = ::std::ptr::null_mut());
1145 let $name = $crate::rust::CapturedJSStack::new($cx, __obj, None);
1146 }
1147}
1148
1149pub struct EnvironmentChain {
1150 chain: *mut crate::jsapi::JS::EnvironmentChain,
1151}
1152
1153impl EnvironmentChain {
1154 pub fn new(
1155 cx: *mut JSContext,
1156 support_unscopeables: crate::jsapi::JS::SupportUnscopables,
1157 ) -> Self {
1158 unsafe {
1159 Self {
1160 chain: crate::jsapi::glue::NewEnvironmentChain(cx, support_unscopeables),
1161 }
1162 }
1163 }
1164
1165 pub fn append(&self, obj: *mut JSObject) {
1166 unsafe {
1167 assert!(crate::jsapi::glue::AppendToEnvironmentChain(
1168 self.chain, obj
1169 ));
1170 }
1171 }
1172
1173 pub fn get(&self) -> *mut crate::jsapi::JS::EnvironmentChain {
1174 self.chain
1175 }
1176}
1177
1178impl Drop for EnvironmentChain {
1179 fn drop(&mut self) {
1180 unsafe {
1181 crate::jsapi::glue::DeleteEnvironmentChain(self.chain);
1182 }
1183 }
1184}
1185
1186impl<'a> Handle<'a, StackGCVector<JSVal, js::TempAllocPolicy>> {
1187 pub fn at(&'a self, index: u32) -> Option<Handle<'a, JSVal>> {
1188 if index >= self.len() {
1189 return None;
1190 }
1191 let handle =
1192 unsafe { Handle::from_marked_location(StackGCVectorValueAtIndex(*self, index)) };
1193 Some(handle)
1194 }
1195
1196 pub fn len(&self) -> u32 {
1197 unsafe { StackGCVectorValueLength(*self) }
1198 }
1199}
1200
1201impl<'a> Handle<'a, StackGCVector<*mut JSString, js::TempAllocPolicy>> {
1202 pub fn at(&'a self, index: u32) -> Option<Handle<'a, *mut JSString>> {
1203 if index >= self.len() {
1204 return None;
1205 }
1206 let handle =
1207 unsafe { Handle::from_marked_location(StackGCVectorStringAtIndex(*self, index)) };
1208 Some(handle)
1209 }
1210
1211 pub fn len(&self) -> u32 {
1212 unsafe { StackGCVectorStringLength(*self) }
1213 }
1214}
1215
1216pub mod wrappers {
1218 macro_rules! wrap {
1219 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: *const Handle<$gentype:ty>, $($rest:tt)*) => {
1224 wrap!(@inner $saved <> ($($acc,)* if $arg.is_null() { std::ptr::null() } else { &(*$arg).into() },) <> $($rest)*);
1225 };
1226 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: Handle<$gentype:ty>, $($rest:tt)*) => {
1227 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1228 };
1229 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandle<$gentype:ty>, $($rest:tt)*) => {
1230 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1231 };
1232 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: Handle, $($rest:tt)*) => {
1233 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1234 };
1235 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandle, $($rest:tt)*) => {
1236 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1237 };
1238 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleFunction , $($rest:tt)*) => {
1239 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1240 };
1241 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleId , $($rest:tt)*) => {
1242 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1243 };
1244 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleObject , $($rest:tt)*) => {
1245 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1246 };
1247 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleScript , $($rest:tt)*) => {
1248 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1249 };
1250 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleString , $($rest:tt)*) => {
1251 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1252 };
1253 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleSymbol , $($rest:tt)*) => {
1254 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1255 };
1256 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleValue , $($rest:tt)*) => {
1257 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1258 };
1259 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleFunction , $($rest:tt)*) => {
1260 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1261 };
1262 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleId , $($rest:tt)*) => {
1263 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1264 };
1265 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleObject , $($rest:tt)*) => {
1266 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1267 };
1268 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleScript , $($rest:tt)*) => {
1269 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1270 };
1271 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleString , $($rest:tt)*) => {
1272 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1273 };
1274 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleSymbol , $($rest:tt)*) => {
1275 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1276 };
1277 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleValue , $($rest:tt)*) => {
1278 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1279 };
1280 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: $type:ty, $($rest:tt)*) => {
1281 wrap!(@inner $saved <> ($($acc,)* $arg,) <> $($rest)*);
1282 };
1283 (@inner ($module:tt: $func_name:ident ($($args:tt)*) -> $outtype:ty) <> ($($argexprs:expr,)*) <> ) => {
1284 #[inline]
1285 pub unsafe fn $func_name($($args)*) -> $outtype {
1286 $module::$func_name($($argexprs),*)
1287 }
1288 };
1289 ($module:tt: pub fn $func_name:ident($($args:tt)*) -> $outtype:ty) => {
1290 wrap!(@inner ($module: $func_name ($($args)*) -> $outtype) <> () <> $($args)* ,);
1291 };
1292 ($module:tt: pub fn $func_name:ident($($args:tt)*)) => {
1293 wrap!($module: pub fn $func_name($($args)*) -> ());
1294 }
1295 }
1296
1297 use super::*;
1298 use crate::glue;
1299 use crate::glue::EncodedStringCallback;
1300 use crate::jsapi;
1301 use crate::jsapi::js::TempAllocPolicy;
1302 use crate::jsapi::jsid;
1303 use crate::jsapi::mozilla::Utf8Unit;
1304 use crate::jsapi::BigInt;
1305 use crate::jsapi::CallArgs;
1306 use crate::jsapi::CloneDataPolicy;
1307 use crate::jsapi::ColumnNumberOneOrigin;
1308 use crate::jsapi::CompartmentTransplantCallback;
1309 use crate::jsapi::EnvironmentChain;
1310 use crate::jsapi::JSONParseHandler;
1311 use crate::jsapi::Latin1Char;
1312 use crate::jsapi::PropertyKey;
1313 use crate::jsapi::TaggedColumnNumberOneOrigin;
1314 use crate::jsapi::ESClass;
1316 use crate::jsapi::ExceptionStackBehavior;
1317 use crate::jsapi::ForOfIterator;
1318 use crate::jsapi::ForOfIterator_NonIterableBehavior;
1319 use crate::jsapi::HandleObjectVector;
1320 use crate::jsapi::InstantiateOptions;
1321 use crate::jsapi::JSClass;
1322 use crate::jsapi::JSErrorReport;
1323 use crate::jsapi::JSExnType;
1324 use crate::jsapi::JSFunctionSpecWithHelp;
1325 use crate::jsapi::JSJitInfo;
1326 use crate::jsapi::JSONWriteCallback;
1327 use crate::jsapi::JSPrincipals;
1328 use crate::jsapi::JSPropertySpec;
1329 use crate::jsapi::JSPropertySpec_Name;
1330 use crate::jsapi::JSProtoKey;
1331 use crate::jsapi::JSScript;
1332 use crate::jsapi::JSStructuredCloneData;
1333 use crate::jsapi::JSType;
1334 use crate::jsapi::ModuleErrorBehaviour;
1335 use crate::jsapi::ModuleType;
1336 use crate::jsapi::MutableHandleIdVector;
1337 use crate::jsapi::PromiseState;
1338 use crate::jsapi::PromiseUserInputEventHandlingState;
1339 use crate::jsapi::ReadOnlyCompileOptions;
1340 use crate::jsapi::Realm;
1341 use crate::jsapi::RefPtr;
1342 use crate::jsapi::RegExpFlags;
1343 use crate::jsapi::ScriptEnvironmentPreparer_Closure;
1344 use crate::jsapi::SourceText;
1345 use crate::jsapi::StackCapture;
1346 use crate::jsapi::Stencil;
1347 use crate::jsapi::StructuredCloneScope;
1348 use crate::jsapi::Symbol;
1349 use crate::jsapi::SymbolCode;
1350 use crate::jsapi::TranscodeBuffer;
1351 use crate::jsapi::TwoByteChars;
1352 use crate::jsapi::UniqueChars;
1353 use crate::jsapi::Value;
1354 use crate::jsapi::WasmModule;
1355 use crate::jsapi::{ElementAdder, IsArrayAnswer, PropertyDescriptor};
1356 use crate::jsapi::{JSContext, JSFunction, JSNative, JSObject, JSString};
1357 use crate::jsapi::{
1358 JSStructuredCloneCallbacks, JSStructuredCloneReader, JSStructuredCloneWriter,
1359 };
1360 use crate::jsapi::{MallocSizeOf, ObjectOpResult, ObjectPrivateVisitor, TabSizes};
1361 use crate::jsapi::{SavedFrameResult, SavedFrameSelfHosted};
1362 include!("jsapi_wrappers.in.rs");
1363 include!("glue_wrappers.in.rs");
1364}
1365
1366pub mod wrappers2 {
1368 macro_rules! wrap {
1369 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: *const Handle<$gentype:ty>, $($rest:tt)*) => {
1374 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: *const Handle<$gentype>) <> ($($arg_expr_acc,)* if $arg.is_null() { ::std::ptr::null() } else { &(*$arg).into() },) <> $($rest)*);
1375 };
1376 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: Handle<$gentype:ty>, $($rest:tt)*) => {
1377 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: Handle<$gentype>) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1378 };
1379 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandle<$gentype:ty>, $($rest:tt)*) => {
1380 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandle<$gentype>) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1381 };
1382 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: Handle, $($rest:tt)*) => {
1383 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: Handle) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1384 };
1385 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandle, $($rest:tt)*) => {
1386 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandle) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1387 };
1388 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleFunction , $($rest:tt)*) => {
1389 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleFunction) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1390 };
1391 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleId , $($rest:tt)*) => {
1392 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleId) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1393 };
1394 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleObject , $($rest:tt)*) => {
1395 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleObject) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1396 };
1397 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleScript , $($rest:tt)*) => {
1398 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleScript) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1399 };
1400 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleString , $($rest:tt)*) => {
1401 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleString) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1402 };
1403 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleSymbol , $($rest:tt)*) => {
1404 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleSymbol) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1405 };
1406 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleValue , $($rest:tt)*) => {
1407 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleValue) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1408 };
1409 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleFunction , $($rest:tt)*) => {
1410 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleFunction) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1411 };
1412 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleId , $($rest:tt)*) => {
1413 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleId) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1414 };
1415 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleObject , $($rest:tt)*) => {
1416 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleObject) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1417 };
1418 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleScript , $($rest:tt)*) => {
1419 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleScript) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1420 };
1421 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleString , $($rest:tt)*) => {
1422 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleString) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1423 };
1424 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleSymbol , $($rest:tt)*) => {
1425 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleSymbol) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1426 };
1427 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleValue , $($rest:tt)*) => {
1428 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleValue) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1429 };
1430 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: &mut JSContext , $($rest:tt)*) => {
1431 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: &mut JSContext) <> ($($arg_expr_acc,)* $arg.raw_cx(),) <> $($rest)*);
1432 };
1433 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: &JSContext , $($rest:tt)*) => {
1434 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: &JSContext) <> ($($arg_expr_acc,)* $arg.raw_cx_no_gc(),) <> $($rest)*);
1435 };
1436 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: *const AutoRequireNoGC , $($rest:tt)*) => {
1438 wrap!(@inner $saved <> ($($arg_sig_acc)*) <> ($($arg_expr_acc,)* ::std::ptr::null(),) <> $($rest)*);
1439 };
1440 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: $type:ty, $($rest:tt)*) => {
1441 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: $type) <> ($($arg_expr_acc,)* $arg,) <> $($rest)*);
1442 };
1443 (@inner ($module:tt: $func_name:ident -> $outtype:ty) <> (, $($args:tt)*) <> ($($argexprs:expr,)*) <> ) => {
1444 #[inline]
1445 pub unsafe fn $func_name($($args)*) -> $outtype {
1446 $module::$func_name($($argexprs),*)
1447 }
1448 };
1449 ($module:tt: pub fn $func_name:ident($($args:tt)*) -> $outtype:ty) => {
1450 wrap!(@inner ($module: $func_name -> $outtype) <> () <> () <> $($args)* ,);
1451 };
1452 ($module:tt: pub fn $func_name:ident($($args:tt)*)) => {
1453 wrap!($module: pub fn $func_name($($args)*) -> ());
1454 }
1455 }
1456
1457 use super::*;
1458 use super::{
1459 Handle, HandleFunction, HandleId, HandleObject, HandleScript, HandleString, HandleValue,
1460 HandleValueArray, MutableHandle, MutableHandleId, MutableHandleObject, MutableHandleString,
1461 MutableHandleValue, StackGCVector,
1462 };
1463 use crate::context::JSContext;
1464 use crate::glue;
1465 use crate::glue::*;
1466 use crate::jsapi;
1467 use crate::jsapi::js::TempAllocPolicy;
1468 use crate::jsapi::mozilla::Utf8Unit;
1469 use crate::jsapi::mozilla::*;
1470 use crate::jsapi::BigInt;
1471 use crate::jsapi::CallArgs;
1472 use crate::jsapi::CloneDataPolicy;
1473 use crate::jsapi::ColumnNumberOneOrigin;
1474 use crate::jsapi::CompartmentTransplantCallback;
1475 use crate::jsapi::ESClass;
1476 use crate::jsapi::EnvironmentChain;
1477 use crate::jsapi::ExceptionStackBehavior;
1478 use crate::jsapi::ForOfIterator;
1479 use crate::jsapi::ForOfIterator_NonIterableBehavior;
1480 use crate::jsapi::HandleObjectVector;
1481 use crate::jsapi::InstantiateOptions;
1482 use crate::jsapi::JSClass;
1483 use crate::jsapi::JSErrorReport;
1484 use crate::jsapi::JSExnType;
1485 use crate::jsapi::JSFunctionSpecWithHelp;
1486 use crate::jsapi::JSJitInfo;
1487 use crate::jsapi::JSONParseHandler;
1488 use crate::jsapi::JSONWriteCallback;
1489 use crate::jsapi::JSPrincipals;
1490 use crate::jsapi::JSPropertySpec;
1491 use crate::jsapi::JSPropertySpec_Name;
1492 use crate::jsapi::JSProtoKey;
1493 use crate::jsapi::JSScript;
1494 use crate::jsapi::JSStructuredCloneData;
1495 use crate::jsapi::JSType;
1496 use crate::jsapi::Latin1Char;
1497 use crate::jsapi::ModuleErrorBehaviour;
1498 use crate::jsapi::ModuleType;
1499 use crate::jsapi::MutableHandleIdVector;
1500 use crate::jsapi::PromiseState;
1501 use crate::jsapi::PromiseUserInputEventHandlingState;
1502 use crate::jsapi::PropertyKey;
1503 use crate::jsapi::ReadOnlyCompileOptions;
1504 use crate::jsapi::Realm;
1505 use crate::jsapi::RealmOptions;
1506 use crate::jsapi::RefPtr;
1507 use crate::jsapi::RegExpFlags;
1508 use crate::jsapi::ScriptEnvironmentPreparer_Closure;
1509 use crate::jsapi::SourceText;
1510 use crate::jsapi::StackCapture;
1511 use crate::jsapi::Stencil;
1512 use crate::jsapi::StructuredCloneScope;
1513 use crate::jsapi::Symbol;
1514 use crate::jsapi::SymbolCode;
1515 use crate::jsapi::TaggedColumnNumberOneOrigin;
1516 use crate::jsapi::TranscodeBuffer;
1517 use crate::jsapi::TwoByteChars;
1518 use crate::jsapi::UniqueChars;
1519 use crate::jsapi::Value;
1520 use crate::jsapi::WasmModule;
1521 use crate::jsapi::*;
1522 use crate::jsapi::{ElementAdder, IsArrayAnswer, PropertyDescriptor};
1523 use crate::jsapi::{JSFunction, JSNative, JSObject, JSString};
1524 use crate::jsapi::{
1525 JSStructuredCloneCallbacks, JSStructuredCloneReader, JSStructuredCloneWriter,
1526 };
1527 use crate::jsapi::{MallocSizeOf, ObjectOpResult, ObjectPrivateVisitor, TabSizes};
1528 use crate::jsapi::{SavedFrameResult, SavedFrameSelfHosted};
1529 include!("jsapi2_wrappers.in.rs");
1530 include!("glue2_wrappers.in.rs");
1531}