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