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