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::OwningCompileOptions_for_fc;
34use crate::glue::{DeleteCompileOptions, DeleteRootedObjectVector, DestroyRootedIdVector};
35use crate::glue::{DeleteJSAutoStructuredCloneBuffer, NewJSAutoStructuredCloneBuffer};
36use crate::glue::{GetIdVectorAddress, GetObjectVectorAddress, SliceRootedIdVector};
37use crate::jsapi;
38use crate::jsapi::glue::{DeleteRealmOptions, JS_Init, JS_NewRealmOptions};
39use crate::jsapi::js;
40use crate::jsapi::js::frontend::InitialStencilAndDelazifications;
41use crate::jsapi::mozilla::Utf8Unit;
42use crate::jsapi::shadow::BaseShape;
43use crate::jsapi::HandleObjectVector as RawHandleObjectVector;
44use crate::jsapi::InstantiateOptions;
45use crate::jsapi::JS_AddExtraGCRootsTracer;
46use crate::jsapi::MutableHandleIdVector as RawMutableHandleIdVector;
47use crate::jsapi::StackFormat;
48use crate::jsapi::{already_AddRefed, jsid};
49use crate::jsapi::{BorrowedErrorReport, Rooted};
50use crate::jsapi::{DeleteOwningCompileOptions, OwningCompileOptions};
51use crate::jsapi::{HandleValueArray, StencilRelease};
52use crate::jsapi::{InitSelfHostedCode, IsWindowSlow};
53use crate::jsapi::{JSAutoStructuredCloneBuffer, JSStructuredCloneCallbacks, StructuredCloneScope};
54use crate::jsapi::{JSClass, JSClassOps, JSContext, Realm, JSCLASS_RESERVED_SLOTS_SHIFT};
55use crate::jsapi::{JSErrorReport, JSFunctionSpec, JSGCParamKey};
56use crate::jsapi::{JSObject, JSPropertySpec, JSRuntime};
57use crate::jsapi::{JSString, Object, PersistentRootedIdVector};
58use crate::jsapi::{JS_DestroyContext, JS_ShutDown};
59use crate::jsapi::{JS_EnumerateStandardClasses, JS_GlobalObjectTraceHook};
60use crate::jsapi::{JS_MayResolveStandardClass, JS_NewContext, JS_ResolveStandardClass};
61use crate::jsapi::{JS_RequestInterruptCallback, JS_RequestInterruptCallbackCanWait};
62use crate::jsapi::{JS_SetGCParameter, JS_SetNativeStackQuota};
63use crate::jsapi::{JS_StackCapture_AllFrames, JS_StackCapture_MaxFrames};
64use crate::jsapi::{PersistentRootedObjectVector, ReadOnlyCompileOptions, RootingContext};
65use crate::jsapi::{RootedObject, RootedValue, ToWindowProxyIfWindowSlow};
66use crate::jsapi::{SetWarningReporter, SourceText, ToBooleanSlow};
67use crate::jsval::{JSVal, ObjectValue, UndefinedValue};
68use crate::offthread::FrontendContext;
69use crate::panic::maybe_resume_unwind;
70use crate::realm::AutoRealm;
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 { wrappers2::JS_GetRuntime(self.cx_no_gc()) }
401 }
402
403 pub fn cx<'rt>(&'rt mut self) -> &'rt mut crate::context::JSContext {
405 &mut self.cx
406 }
407
408 pub fn cx_no_gc<'rt>(&'rt self) -> &'rt crate::context::JSContext {
410 &self.cx
411 }
412}
413
414pub fn evaluate_script(
415 cx: &mut crate::context::JSContext,
416 glob: HandleObject,
417 script: &str,
418 rval: MutableHandleValue,
419 options: CompileOptionsWrapper,
420) -> Result<(), ()> {
421 debug!(
422 "Evaluating script from {} with content {}",
423 options.filename(),
424 script
425 );
426
427 let mut realm = AutoRealm::new_from_handle(cx, glob);
428
429 unsafe {
430 let mut source = transform_str_to_source_text(&script);
431 if !wrappers2::Evaluate2(&mut realm, options.ptr, &mut source, rval.into()) {
432 debug!("...err!");
433 maybe_resume_unwind();
434 Err(())
435 } else {
436 debug!("...ok!");
439 Ok(())
440 }
441 }
442}
443
444impl Drop for Runtime {
445 fn drop(&mut self) {
446 self.thread_safe_handle.write().unwrap().take();
447 assert!(
448 Arc::get_mut(&mut self.outstanding_children).is_some(),
449 "This runtime still has live children."
450 );
451 unsafe {
452 JS_DestroyContext(self.cx.raw_cx());
453
454 CONTEXT.with(|context| {
455 assert!(context.take().is_some());
456 });
457 }
458 }
459}
460
461#[derive(Clone)]
465pub struct ThreadSafeJSContext(Arc<RwLock<Option<NonNull<JSContext>>>>);
466
467unsafe impl Send for ThreadSafeJSContext {}
468unsafe impl Sync for ThreadSafeJSContext {}
469
470impl ThreadSafeJSContext {
471 pub fn request_interrupt_callback(&self) {
475 if let Some(cx) = self.0.read().unwrap().as_ref() {
476 unsafe {
477 JS_RequestInterruptCallback(cx.as_ptr());
478 }
479 }
480 }
481
482 pub fn request_interrupt_callback_can_wait(&self) {
486 if let Some(cx) = self.0.read().unwrap().as_ref() {
487 unsafe {
488 JS_RequestInterruptCallbackCanWait(cx.as_ptr());
489 }
490 }
491 }
492}
493
494const ChunkShift: usize = 20;
495const ChunkSize: usize = 1 << ChunkShift;
496
497#[cfg(target_pointer_width = "32")]
498const ChunkLocationOffset: usize = ChunkSize - 2 * 4 - 8;
499
500pub struct RootedObjectVectorWrapper {
504 pub ptr: *mut PersistentRootedObjectVector,
505}
506
507impl RootedObjectVectorWrapper {
508 pub fn new(cx: &mut crate::context::JSContext) -> RootedObjectVectorWrapper {
509 RootedObjectVectorWrapper {
510 ptr: unsafe { CreateRootedObjectVector(cx) },
511 }
512 }
513
514 pub fn append(&self, obj: *mut JSObject) -> bool {
515 unsafe { AppendToRootedObjectVector(self.ptr, obj) }
516 }
517
518 pub fn handle(&self) -> RawHandleObjectVector {
519 RawHandleObjectVector {
520 ptr: unsafe { GetObjectVectorAddress(self.ptr) },
521 }
522 }
523}
524
525impl Drop for RootedObjectVectorWrapper {
526 fn drop(&mut self) {
527 unsafe { DeleteRootedObjectVector(self.ptr) }
528 }
529}
530
531pub struct OwningCompileOptionsWrapper {
532 pub ptr: *mut OwningCompileOptions,
533}
534
535impl OwningCompileOptionsWrapper {
536 pub fn new_for_fc(fc: &FrontendContext, options: *const ReadOnlyCompileOptions) -> Self {
537 Self {
538 ptr: unsafe { OwningCompileOptions_for_fc(**fc, options) },
539 }
540 }
541
542 pub fn read_only(&self) -> &ReadOnlyCompileOptions {
543 unsafe { &(*self.ptr)._base }
544 }
545}
546
547unsafe impl Send for OwningCompileOptionsWrapper {}
548
549impl Drop for OwningCompileOptionsWrapper {
550 fn drop(&mut self) {
551 unsafe { DeleteOwningCompileOptions(self.ptr) }
552 }
553}
554
555impl From<&OwningCompileOptionsWrapper> for InstantiateOptions {
556 fn from(value: &OwningCompileOptionsWrapper) -> Self {
557 let options = value.read_only();
558 InstantiateOptions {
559 skipFilenameValidation: options._base.skipFilenameValidation_,
560 hideScriptFromDebugger: options._base.hideScriptFromDebugger_,
561 deferDebugMetadata: options._base.deferDebugMetadata_,
562 eagerDelazificationStrategy_: options._base.eagerDelazificationStrategy_,
563 eagerBaselineStrategy_: options._base.eagerBaselineStrategy_,
564 }
565 }
566}
567
568pub struct CompileOptionsWrapper {
569 pub ptr: *mut ReadOnlyCompileOptions,
570 filename: CString,
571}
572
573impl CompileOptionsWrapper {
574 pub fn new(cx: &crate::context::JSContext, filename: CString, line: u32) -> Self {
575 let ptr = unsafe { wrappers2::NewCompileOptions(cx, filename.as_ptr(), line) };
576 assert!(!ptr.is_null());
577 Self { ptr, filename }
578 }
579
580 pub fn filename(&self) -> &str {
581 self.filename.to_str().expect("Guaranteed by new")
582 }
583
584 pub fn set_introduction_type(&mut self, introduction_type: &'static CStr) {
585 unsafe {
586 (*self.ptr)._base.introductionType = introduction_type.as_ptr();
587 }
588 }
589
590 pub fn set_muted_errors(&mut self, muted_errors: bool) {
591 unsafe {
592 (*self.ptr)._base.mutedErrors_ = muted_errors;
593 }
594 }
595
596 pub fn set_is_run_once(&mut self, is_run_once: bool) {
597 unsafe {
598 (*self.ptr).isRunOnce = is_run_once;
599 }
600 }
601
602 pub fn set_no_script_rval(&mut self, no_script_rval: bool) {
603 unsafe {
604 (*self.ptr).noScriptRval = no_script_rval;
605 }
606 }
607}
608
609impl Drop for CompileOptionsWrapper {
610 fn drop(&mut self) {
611 unsafe { DeleteCompileOptions(self.ptr) }
612 }
613}
614
615pub struct JSAutoStructuredCloneBufferWrapper {
616 ptr: NonNull<JSAutoStructuredCloneBuffer>,
617}
618
619impl JSAutoStructuredCloneBufferWrapper {
620 pub unsafe fn new(
621 scope: StructuredCloneScope,
622 callbacks: *const JSStructuredCloneCallbacks,
623 ) -> Self {
624 let raw_ptr = NewJSAutoStructuredCloneBuffer(scope, callbacks);
625 Self {
626 ptr: NonNull::new(raw_ptr).unwrap(),
627 }
628 }
629
630 pub fn as_raw_ptr(&self) -> *mut JSAutoStructuredCloneBuffer {
631 self.ptr.as_ptr()
632 }
633}
634
635impl Drop for JSAutoStructuredCloneBufferWrapper {
636 fn drop(&mut self) {
637 unsafe {
638 DeleteJSAutoStructuredCloneBuffer(self.ptr.as_ptr());
639 }
640 }
641}
642
643pub struct Stencil {
644 inner: already_AddRefed<InitialStencilAndDelazifications>,
645}
646
647unsafe impl Send for Stencil {}
648
649impl Drop for Stencil {
650 fn drop(&mut self) {
651 if self.is_null() {
652 return;
653 }
654 unsafe {
655 StencilRelease(self.inner.mRawPtr);
656 }
657 }
658}
659
660impl Deref for Stencil {
661 type Target = *mut InitialStencilAndDelazifications;
662
663 fn deref(&self) -> &Self::Target {
664 &self.inner.mRawPtr
665 }
666}
667
668impl Stencil {
669 pub fn is_null(&self) -> bool {
670 self.inner.mRawPtr.is_null()
671 }
672
673 pub unsafe fn from_raw(inner: already_AddRefed<InitialStencilAndDelazifications>) -> Self {
674 Self { inner }
675 }
676}
677
678#[inline]
682pub unsafe fn ToBoolean(v: HandleValue) -> bool {
683 let val = *v.ptr.as_ptr();
684
685 if val.is_boolean() {
686 return val.to_boolean();
687 }
688
689 if val.is_int32() {
690 return val.to_int32() != 0;
691 }
692
693 if val.is_null_or_undefined() {
694 return false;
695 }
696
697 if val.is_double() {
698 let d = val.to_double();
699 return !d.is_nan() && d != 0f64;
700 }
701
702 if val.is_symbol() {
703 return true;
704 }
705
706 ToBooleanSlow(v.into())
707}
708
709#[inline]
710pub unsafe fn ToNumber(cx: &mut crate::context::JSContext, v: HandleValue) -> Result<f64, ()> {
711 let val = *v.ptr.as_ptr();
712 if val.is_number() {
713 return Ok(val.to_number());
714 }
715
716 let mut out = Default::default();
717 if ToNumberSlow(cx, v, &mut out) {
718 Ok(out)
719 } else {
720 Err(())
721 }
722}
723
724#[inline]
725unsafe fn convert_from_int32<T: Default + Copy>(
726 cx: &mut crate::context::JSContext,
727 v: HandleValue,
728 conv_fn: unsafe fn(&mut crate::context::JSContext, HandleValue, *mut T) -> bool,
729) -> Result<T, ()> {
730 let val = *v.ptr.as_ptr();
731 if val.is_int32() {
732 let intval: i64 = val.to_int32() as i64;
733 let intval = *(&intval as *const i64 as *const T);
735 return Ok(intval);
736 }
737
738 let mut out = Default::default();
739 if conv_fn(cx, v, &mut out) {
740 Ok(out)
741 } else {
742 Err(())
743 }
744}
745
746#[inline]
747pub unsafe fn ToInt32(cx: &mut crate::context::JSContext, v: HandleValue) -> Result<i32, ()> {
748 convert_from_int32::<i32>(cx, v, ToInt32Slow)
749}
750
751#[inline]
752pub unsafe fn ToUint32(cx: &mut crate::context::JSContext, v: HandleValue) -> Result<u32, ()> {
753 convert_from_int32::<u32>(cx, v, ToUint32Slow)
754}
755
756#[inline]
757pub unsafe fn ToUint16(cx: &mut crate::context::JSContext, v: HandleValue) -> Result<u16, ()> {
758 convert_from_int32::<u16>(cx, v, ToUint16Slow)
759}
760
761#[inline]
762pub unsafe fn ToInt64(cx: &mut crate::context::JSContext, v: HandleValue) -> Result<i64, ()> {
763 convert_from_int32::<i64>(cx, v, ToInt64Slow)
764}
765
766#[inline]
767pub unsafe fn ToUint64(cx: &mut crate::context::JSContext, v: HandleValue) -> Result<u64, ()> {
768 convert_from_int32::<u64>(cx, v, ToUint64Slow)
769}
770
771#[inline]
772pub unsafe fn ToString(cx: &mut crate::context::JSContext, v: HandleValue) -> *mut JSString {
773 let val = *v.ptr.as_ptr();
774 if val.is_string() {
775 return val.to_string();
776 }
777
778 ToStringSlow(cx, v.into())
779}
780
781pub unsafe fn ToWindowProxyIfWindow(obj: *mut JSObject) -> *mut JSObject {
782 if is_window(obj) {
783 ToWindowProxyIfWindowSlow(obj)
784 } else {
785 obj
786 }
787}
788
789pub unsafe extern "C" fn report_warning(_cx: *mut JSContext, report: *mut JSErrorReport) {
790 fn latin1_to_string(bytes: &[u8]) -> String {
791 bytes
792 .iter()
793 .map(|c| char::from_u32(*c as u32).unwrap())
794 .collect()
795 }
796
797 let fnptr = (*report)._base.filename.data_;
798 let fname = if !fnptr.is_null() {
799 let c_str = CStr::from_ptr(fnptr);
800 latin1_to_string(c_str.to_bytes())
801 } else {
802 "none".to_string()
803 };
804
805 let lineno = (*report)._base.lineno;
806 let column = (*report)._base.column._base;
807
808 let msg_ptr = (*report)._base.message_.data_ as *const u8;
809 let msg_len = (0usize..)
810 .find(|&i| *msg_ptr.offset(i as isize) == 0)
811 .unwrap();
812 let msg_slice = slice::from_raw_parts(msg_ptr, msg_len);
813 let msg = str::from_utf8_unchecked(msg_slice);
814
815 warn!("Warning at {}:{}:{}: {}\n", fname, lineno, column, msg);
816}
817
818pub struct IdVector(*mut PersistentRootedIdVector);
819
820impl IdVector {
821 pub fn new(cx: &mut crate::context::JSContext) -> IdVector {
822 let vector = unsafe { CreateRootedIdVector(cx) };
823 assert!(!vector.is_null());
824 IdVector(vector)
825 }
826
827 pub fn handle_mut(&mut self) -> RawMutableHandleIdVector {
828 RawMutableHandleIdVector {
829 ptr: unsafe { GetIdVectorAddress(self.0) },
830 }
831 }
832}
833
834impl Drop for IdVector {
835 fn drop(&mut self) {
836 unsafe { DestroyRootedIdVector(self.0) }
837 }
838}
839
840impl Deref for IdVector {
841 type Target = [jsid];
842
843 fn deref(&self) -> &[jsid] {
844 unsafe {
845 let mut length = 0;
846 let pointer = SliceRootedIdVector(self.0, &mut length);
847 slice::from_raw_parts(pointer, length)
848 }
849 }
850}
851
852pub unsafe fn define_methods(
867 cx: &mut crate::context::JSContext,
868 obj: HandleObject,
869 methods: &'static [JSFunctionSpec],
870) -> Result<(), ()> {
871 assert!({
872 match methods.last() {
873 Some(&JSFunctionSpec {
874 name,
875 call,
876 nargs,
877 flags,
878 selfHostedName,
879 }) => {
880 name.string_.is_null()
881 && call.is_zeroed()
882 && nargs == 0
883 && flags == 0
884 && selfHostedName.is_null()
885 }
886 None => false,
887 }
888 });
889
890 JS_DefineFunctions(cx, obj, methods.as_ptr()).to_result()
891}
892
893pub unsafe fn define_properties(
908 cx: &mut crate::context::JSContext,
909 obj: HandleObject,
910 properties: &'static [JSPropertySpec],
911) -> Result<(), ()> {
912 assert!({
913 match properties.last() {
914 Some(spec) => spec.is_zeroed(),
915 None => false,
916 }
917 });
918
919 JS_DefineProperties(cx, obj, properties.as_ptr()).to_result()
920}
921
922static SIMPLE_GLOBAL_CLASS_OPS: JSClassOps = JSClassOps {
923 addProperty: None,
924 delProperty: None,
925 enumerate: Some(JS_EnumerateStandardClasses),
926 newEnumerate: None,
927 resolve: Some(JS_ResolveStandardClass),
928 mayResolve: Some(JS_MayResolveStandardClass),
929 finalize: None,
930 call: None,
931 construct: None,
932 trace: Some(JS_GlobalObjectTraceHook),
933};
934
935pub static SIMPLE_GLOBAL_CLASS: JSClass = JSClass {
937 name: c"Global".as_ptr(),
938 flags: JSCLASS_IS_GLOBAL
939 | ((JSCLASS_GLOBAL_SLOT_COUNT & JSCLASS_RESERVED_SLOTS_MASK)
940 << JSCLASS_RESERVED_SLOTS_SHIFT),
941 cOps: &SIMPLE_GLOBAL_CLASS_OPS as *const JSClassOps,
942 spec: ptr::null(),
943 ext: ptr::null(),
944 oOps: ptr::null(),
945};
946
947#[inline]
948unsafe fn get_object_group(obj: *mut JSObject) -> *mut BaseShape {
949 assert!(!obj.is_null());
950 let obj = obj as *mut Object;
951 (*(*obj).shape).base
952}
953
954#[inline]
955pub unsafe fn get_object_class(obj: *mut JSObject) -> *const JSClass {
956 (*get_object_group(obj)).clasp as *const _
957}
958
959#[inline]
960pub unsafe fn get_object_realm(obj: *mut JSObject) -> *mut Realm {
961 (*get_object_group(obj)).realm
962}
963
964#[inline]
965pub unsafe fn get_context_realm(cx: *mut JSContext) -> *mut Realm {
966 let cx = cx as *mut RootingContext;
967 (*cx).realm_
968}
969
970#[inline]
971pub fn is_dom_class(class: &JSClass) -> bool {
972 class.flags & JSCLASS_IS_DOMJSCLASS != 0
973}
974
975#[inline]
976pub unsafe fn is_dom_object(obj: *mut JSObject) -> bool {
977 is_dom_class(&*get_object_class(obj))
978}
979
980#[inline]
981pub unsafe fn is_window(obj: *mut JSObject) -> bool {
982 (*get_object_class(obj)).flags & JSCLASS_IS_GLOBAL != 0 && IsWindowSlow(obj)
983}
984
985#[inline]
986pub unsafe fn try_to_outerize(mut rval: MutableHandleValue) {
987 let obj = rval.to_object();
988 if is_window(obj) {
989 let obj = ToWindowProxyIfWindowSlow(obj);
990 assert!(!obj.is_null());
991 rval.set(ObjectValue(&mut *obj));
992 }
993}
994
995#[inline]
996pub unsafe fn try_to_outerize_object(mut rval: MutableHandleObject) {
997 if is_window(*rval) {
998 let obj = ToWindowProxyIfWindowSlow(*rval);
999 assert!(!obj.is_null());
1000 rval.set(obj);
1001 }
1002}
1003
1004#[inline]
1005pub unsafe fn maybe_wrap_object(cx: &mut crate::context::JSContext, mut obj: MutableHandleObject) {
1006 if get_object_realm(*obj) != get_context_realm(cx.raw_cx()) {
1007 assert!(JS_WrapObject(cx, obj.reborrow()));
1008 }
1009 try_to_outerize_object(obj);
1010}
1011
1012#[inline]
1013pub unsafe fn maybe_wrap_object_value(
1014 cx: &mut crate::context::JSContext,
1015 rval: MutableHandleValue,
1016) {
1017 assert!(rval.is_object());
1018 let obj = rval.to_object();
1019 if get_object_realm(obj) != get_context_realm(cx.raw_cx()) {
1020 assert!(JS_WrapValue(cx, rval));
1021 } else if is_dom_object(obj) {
1022 try_to_outerize(rval);
1023 }
1024}
1025
1026#[inline]
1027pub fn maybe_wrap_object_or_null_value(
1028 cx: &mut crate::context::JSContext,
1029 rval: MutableHandleValue,
1030) {
1031 assert!(rval.is_object_or_null());
1032 if !rval.is_null() {
1033 unsafe { maybe_wrap_object_value(cx, rval) };
1034 }
1035}
1036
1037#[inline]
1038pub fn maybe_wrap_value(cx: &mut crate::context::JSContext, rval: MutableHandleValue) {
1039 if rval.is_string() {
1040 assert!(unsafe { JS_WrapValue(cx, rval) });
1041 } else if rval.is_object() {
1042 unsafe { maybe_wrap_object_value(cx, rval) };
1043 }
1044}
1045
1046#[macro_export]
1048macro_rules! new_jsjitinfo_bitfield_1 {
1049 (
1050 $type_: expr,
1051 $aliasSet_: expr,
1052 $returnType_: expr,
1053 $isInfallible: expr,
1054 $isMovable: expr,
1055 $isEliminatable: expr,
1056 $isAlwaysInSlot: expr,
1057 $isLazilyCachedInSlot: expr,
1058 $isTypedMethod: expr,
1059 $slotIndex: expr,
1060 ) => {
1061 0 | (($type_ as u32) << 0u32)
1062 | (($aliasSet_ as u32) << 4u32)
1063 | (($returnType_ as u32) << 8u32)
1064 | (($isInfallible as u32) << 16u32)
1065 | (($isMovable as u32) << 17u32)
1066 | (($isEliminatable as u32) << 18u32)
1067 | (($isAlwaysInSlot as u32) << 19u32)
1068 | (($isLazilyCachedInSlot as u32) << 20u32)
1069 | (($isTypedMethod as u32) << 21u32)
1070 | (($slotIndex as u32) << 22u32)
1071 };
1072}
1073
1074#[derive(Debug, Default)]
1075pub struct ScriptedCaller {
1076 pub filename: String,
1077 pub line: u32,
1078 pub col: u32,
1079}
1080
1081pub fn describe_scripted_caller(cx: &crate::context::JSContext) -> Result<ScriptedCaller, ()> {
1082 let mut filename = String::new();
1083 let mut line = 0;
1084 let mut col = 0;
1085 if unsafe {
1086 !wrappers2::DescribeScriptedCaller(
1087 cx,
1088 Some(fill_string_callback),
1089 &raw mut filename as *mut c_void,
1090 &mut line,
1091 &mut col,
1092 )
1093 } {
1094 return Err(());
1095 }
1096 Ok(ScriptedCaller {
1097 filename,
1098 line,
1099 col,
1100 })
1101}
1102
1103pub struct ErrorInfo {
1104 pub message: String,
1105 pub filename: String,
1106 pub line: u32,
1107 pub col: u32,
1108}
1109
1110unsafe extern "C" fn fill_string_callback(ptr: *const c_char, len: usize, target: *mut c_void) {
1119 assert!(!ptr.is_null());
1120 let target = &mut *(target as *mut String);
1121
1122 let slice = String::from_utf8_lossy(slice::from_raw_parts(ptr as *const u8, len));
1123 target.push_str(&slice);
1124}
1125
1126pub fn error_info_from_exception_stack(
1129 cx: &mut crate::context::JSContext,
1130 rval: MutableHandleValue,
1131) -> Option<ErrorInfo> {
1132 let mut message = String::new();
1133 let mut filename = String::new();
1134
1135 let mut line = 0;
1136 let mut col = 0;
1137
1138 unsafe {
1139 if !wrappers2::PendingExceptionStackInfo(
1140 cx,
1141 Some(fill_string_callback),
1142 &raw mut message as *mut c_void,
1143 &raw mut filename as *mut c_void,
1144 &mut line,
1145 &mut col,
1146 rval,
1147 ) {
1148 return None;
1149 }
1150 }
1151
1152 Some(ErrorInfo {
1153 message,
1154 filename,
1155 line,
1156 col,
1157 })
1158}
1159
1160pub struct CapturedJSStack<'a> {
1161 cx: &'a mut crate::context::JSContext,
1162 stack: RootedGuard<'a, *mut JSObject>,
1163}
1164
1165impl<'a> CapturedJSStack<'a> {
1166 pub unsafe fn new(
1167 cx: &'a mut crate::context::JSContext,
1168 mut guard: RootedGuard<'a, *mut JSObject>,
1169 max_frame_count: Option<u32>,
1170 ) -> Option<Self> {
1171 let ref mut stack_capture = MaybeUninit::uninit();
1172 match max_frame_count {
1173 None => JS_StackCapture_AllFrames(stack_capture.as_mut_ptr()),
1174 Some(count) => JS_StackCapture_MaxFrames(count, stack_capture.as_mut_ptr()),
1175 };
1176 let ref mut stack_capture = stack_capture.assume_init();
1177
1178 if !CaptureCurrentStack(cx, guard.handle_mut(), stack_capture, HandleObject::null()) {
1179 None
1180 } else {
1181 Some(CapturedJSStack { cx, stack: guard })
1182 }
1183 }
1184
1185 pub fn as_string(&mut self, indent: Option<usize>, format: StackFormat) -> Option<String> {
1186 let stack_handle = self.stack.handle();
1187 rooted!(&in(self.cx) let mut js_string = ptr::null_mut::<JSString>());
1188
1189 unsafe {
1190 if !BuildStackString(
1191 self.cx,
1192 ptr::null_mut(),
1193 stack_handle,
1194 js_string.handle_mut(),
1195 indent.unwrap_or(0),
1196 format,
1197 ) {
1198 return None;
1199 }
1200
1201 Some(crate::conversions::jsstr_to_string(
1202 self.cx,
1203 NonNull::new(js_string.get())?,
1204 ))
1205 }
1206 }
1207
1208 pub fn for_each_stack_frame<F>(&mut self, mut f: F)
1210 where
1211 F: FnMut(&mut crate::context::JSContext, Handle<*mut JSObject>),
1212 {
1213 rooted!(&in(self.cx) let mut current_element = self.stack.clone());
1214 rooted!(&in(self.cx) let mut next_element = ptr::null_mut::<JSObject>());
1215
1216 loop {
1217 f(self.cx, current_element.handle());
1218
1219 unsafe {
1220 let result = wrappers2::GetSavedFrameParent(
1221 self.cx,
1222 ptr::null_mut(),
1223 current_element.handle(),
1224 next_element.handle_mut(),
1225 jsapi::SavedFrameSelfHosted::Include,
1226 );
1227
1228 if result != SavedFrameResult::Ok || next_element.is_null() {
1229 return;
1230 }
1231 }
1232 current_element.set(next_element.get());
1233 }
1234 }
1235}
1236
1237#[macro_export]
1238macro_rules! capture_stack {
1239 (&in($cx:expr) let $name:ident = with max depth($max_frame_count:expr)) => {
1240 rooted!(&in($cx) let mut __obj = ::std::ptr::null_mut());
1241 let $name = $crate::rust::CapturedJSStack::new($cx, __obj, Some($max_frame_count));
1242 };
1243 (&in($cx:expr) let $name:ident ) => {
1244 rooted!(&in($cx) let mut __obj = ::std::ptr::null_mut());
1245 let $name = $crate::rust::CapturedJSStack::new($cx, __obj, None);
1246 }
1247}
1248
1249pub struct EnvironmentChain {
1250 chain: *mut crate::jsapi::JS::EnvironmentChain,
1251}
1252
1253impl EnvironmentChain {
1254 pub fn new(
1255 cx: &mut crate::context::JSContext,
1256 support_unscopeables: crate::jsapi::JS::SupportUnscopables,
1257 ) -> Self {
1258 Self {
1259 chain: unsafe { wrappers2::NewEnvironmentChain(cx, support_unscopeables) },
1260 }
1261 }
1262
1263 pub fn append(&self, obj: *mut JSObject) {
1264 unsafe {
1265 assert!(crate::jsapi::glue::AppendToEnvironmentChain(
1266 self.chain, obj
1267 ));
1268 }
1269 }
1270
1271 pub fn get(&self) -> *mut crate::jsapi::JS::EnvironmentChain {
1272 self.chain
1273 }
1274}
1275
1276impl Drop for EnvironmentChain {
1277 fn drop(&mut self) {
1278 unsafe {
1279 crate::jsapi::glue::DeleteEnvironmentChain(self.chain);
1280 }
1281 }
1282}
1283
1284impl<'a> Handle<'a, StackGCVector<JSVal, js::TempAllocPolicy>> {
1285 pub fn at(&'a self, index: u32) -> Option<Handle<'a, JSVal>> {
1286 if index >= self.len() {
1287 return None;
1288 }
1289 let handle =
1290 unsafe { Handle::from_marked_location(StackGCVectorValueAtIndex(*self, index)) };
1291 Some(handle)
1292 }
1293
1294 pub fn len(&self) -> u32 {
1295 unsafe { StackGCVectorValueLength(*self) }
1296 }
1297}
1298
1299impl<'a> Handle<'a, StackGCVector<*mut JSString, js::TempAllocPolicy>> {
1300 pub fn at(&'a self, index: u32) -> Option<Handle<'a, *mut JSString>> {
1301 if index >= self.len() {
1302 return None;
1303 }
1304 let handle =
1305 unsafe { Handle::from_marked_location(StackGCVectorStringAtIndex(*self, index)) };
1306 Some(handle)
1307 }
1308
1309 pub fn len(&self) -> u32 {
1310 unsafe { StackGCVectorStringLength(*self) }
1311 }
1312}
1313
1314#[derive(Clone, Copy, Debug)]
1315pub enum ForOfIterationFailure<OtherError> {
1316 ValueIsNotIterable,
1317 JSFailed,
1319 Other(OtherError),
1320}
1321
1322impl<OtherError> From<OtherError> for ForOfIterationFailure<OtherError> {
1323 fn from(value: OtherError) -> Self {
1324 Self::Other(value)
1325 }
1326}
1327
1328pub fn for_of<Context, Callback, OtherError>(
1335 cx: &mut Context,
1336 iterable: HandleValue<'_>,
1337 mut callback: Callback,
1338) -> Result<(), ForOfIterationFailure<OtherError>>
1339where
1340 Context: AsMut<crate::context::JSContext>,
1341 Callback: FnMut(
1342 &mut Context,
1343 HandleValue<'_>,
1344 ) -> Result<ControlFlow<()>, ForOfIterationFailure<OtherError>>,
1345{
1346 let raw_cx = unsafe { cx.as_mut().raw_cx() };
1347
1348 #[allow(unused_variables)]
1354 let zero = unsafe { mem::zeroed() };
1355 let mut iterator = jsapi::ForOfIterator {
1356 cx_: raw_cx,
1357 iterator: RootedObject::new_unrooted(ptr::null_mut()),
1358 nextMethod: RootedValue::new_unrooted(JSVal { asBits_: 0 }),
1359 index: ::std::u32::MAX, ..zero
1361 };
1362
1363 struct IteratorRootGuard<'a> {
1365 inner: &'a mut jsapi::ForOfIterator,
1366 }
1367
1368 impl<'a> Drop for IteratorRootGuard<'a> {
1369 fn drop(&mut self) {
1370 unsafe {
1372 self.inner.iterator.remove_from_root_stack();
1373 self.inner.nextMethod.remove_from_root_stack();
1374 }
1375 }
1376 }
1377 let guard = IteratorRootGuard {
1378 inner: &mut iterator,
1379 };
1380 let iterator = &mut *guard.inner;
1381
1382 unsafe {
1383 RootedObject::add_to_root_stack(&raw mut iterator.iterator, raw_cx);
1384 RootedValue::add_to_root_stack(&raw mut iterator.nextMethod, raw_cx);
1385 }
1386
1387 let success = unsafe {
1388 iterator.init(
1389 iterable.into_handle(),
1390 jsapi::ForOfIterator_NonIterableBehavior::AllowNonIterable,
1391 )
1392 };
1393 if !success {
1394 return Err(ForOfIterationFailure::JSFailed);
1395 }
1396 if !iterator.is_iterable() {
1397 return Err(ForOfIterationFailure::ValueIsNotIterable);
1398 }
1399
1400 let mut done = false;
1401 rooted!(&in(cx.as_mut()) let mut value = UndefinedValue());
1402 loop {
1403 if !unsafe { iterator.next(value.handle_mut().into(), &mut done) } {
1404 return Err(ForOfIterationFailure::JSFailed);
1405 }
1406
1407 if done {
1408 break;
1409 }
1410
1411 if callback(cx, value.handle())?.is_break() {
1412 break;
1413 }
1414 }
1415
1416 Ok(())
1417}
1418
1419pub fn borrowed_error_report<F, R>(cx: &crate::context::JSContext, f: F) -> R
1423where
1424 F: FnOnce(&crate::context::JSContext, &mut BorrowedErrorReport) -> R,
1425{
1426 let mut report = BorrowedErrorReport {
1427 owner_: Rooted::new_unrooted(ptr::null_mut()),
1428 report_: ptr::null_mut(),
1429 };
1430 unsafe {
1431 Rooted::add_to_root_stack(&mut report.owner_, cx.raw_cx_no_gc());
1432 }
1433 let result = f(cx, &mut report);
1434 unsafe {
1435 report.owner_.remove_from_root_stack();
1436 }
1437 result
1438}
1439
1440pub mod wrappers2 {
1442 macro_rules! wrap {
1443 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: Handle<$gentype:ty>, $($rest:tt)*) => {
1447 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: Handle<$gentype>) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1448 };
1449 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandle<$gentype:ty>, $($rest:tt)*) => {
1450 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandle<$gentype>) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1451 };
1452 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: Handle, $($rest:tt)*) => {
1453 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: Handle) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1454 };
1455 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandle, $($rest:tt)*) => {
1456 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandle) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1457 };
1458 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleFunction , $($rest:tt)*) => {
1459 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleFunction) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1460 };
1461 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleId , $($rest:tt)*) => {
1462 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleId) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1463 };
1464 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleObject , $($rest:tt)*) => {
1465 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleObject) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1466 };
1467 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleScript , $($rest:tt)*) => {
1468 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleScript) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1469 };
1470 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleString , $($rest:tt)*) => {
1471 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleString) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1472 };
1473 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleSymbol , $($rest:tt)*) => {
1474 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleSymbol) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1475 };
1476 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleValue , $($rest:tt)*) => {
1477 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleValue) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1478 };
1479 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleFunction , $($rest:tt)*) => {
1480 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleFunction) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1481 };
1482 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleId , $($rest:tt)*) => {
1483 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleId) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1484 };
1485 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleObject , $($rest:tt)*) => {
1486 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleObject) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1487 };
1488 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleScript , $($rest:tt)*) => {
1489 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleScript) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1490 };
1491 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleString , $($rest:tt)*) => {
1492 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleString) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1493 };
1494 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleSymbol , $($rest:tt)*) => {
1495 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleSymbol) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1496 };
1497 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleValue , $($rest:tt)*) => {
1498 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleValue) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1499 };
1500 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: &mut JSContext , $($rest:tt)*) => {
1501 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: &mut JSContext) <> ($($arg_expr_acc,)* $arg.raw_cx(),) <> $($rest)*);
1502 };
1503 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: &JSContext , $($rest:tt)*) => {
1504 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: &JSContext) <> ($($arg_expr_acc,)* $arg.raw_cx_no_gc(),) <> $($rest)*);
1505 };
1506 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: *const AutoRequireNoGC , $($rest:tt)*) => {
1508 wrap!(@inner $saved <> ($($arg_sig_acc)*) <> ($($arg_expr_acc,)* ::std::ptr::null(),) <> $($rest)*);
1509 };
1510 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: $type:ty, $($rest:tt)*) => {
1511 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: $type) <> ($($arg_expr_acc,)* $arg,) <> $($rest)*);
1512 };
1513 (@inner ($module:tt: $func_name:ident -> $outtype:ty) <> (, $($args:tt)*) <> ($($argexprs:expr,)*) <> ) => {
1514 #[inline]
1515 pub unsafe fn $func_name($($args)*) -> $outtype {
1516 $module::$func_name($($argexprs),*)
1517 }
1518 };
1519 ($module:tt: pub fn $func_name:ident($($args:tt)*) -> $outtype:ty) => {
1520 wrap!(@inner ($module: $func_name -> $outtype) <> () <> () <> $($args)* ,);
1521 };
1522 ($module:tt: pub fn $func_name:ident($($args:tt)*)) => {
1523 wrap!($module: pub fn $func_name($($args)*) -> ());
1524 }
1525 }
1526
1527 use super::*;
1528 use super::{
1529 Handle, HandleFunction, HandleId, HandleObject, HandleScript, HandleString, HandleValue,
1530 HandleValueArray, MutableHandle, MutableHandleId, MutableHandleObject, MutableHandleString,
1531 MutableHandleValue, StackGCVector,
1532 };
1533 use crate::context::JSContext;
1534 use crate::glue;
1535 use crate::glue::*;
1536 use crate::jsapi;
1537 use crate::jsapi::js::TempAllocPolicy;
1538 use crate::jsapi::mozilla::Utf8Unit;
1539 use crate::jsapi::mozilla::*;
1540 use crate::jsapi::BigInt;
1541 use crate::jsapi::CallArgs;
1542 use crate::jsapi::CloneDataPolicy;
1543 use crate::jsapi::CompartmentTransplantCallback;
1544 use crate::jsapi::ESClass;
1545 use crate::jsapi::EnvironmentChain;
1546 use crate::jsapi::ExceptionStackBehavior;
1547 use crate::jsapi::ForOfIterator;
1548 use crate::jsapi::ForOfIterator_NonIterableBehavior;
1549 use crate::jsapi::FrontendContext;
1550 use crate::jsapi::HandleObjectVector;
1551 use crate::jsapi::InstantiateOptions;
1552 use crate::jsapi::JSClass;
1553 use crate::jsapi::JSErrorReport;
1554 use crate::jsapi::JSExnType;
1555 use crate::jsapi::JSFunctionSpecWithHelp;
1556 use crate::jsapi::JSJitInfo;
1557 use crate::jsapi::JSONParseHandler;
1558 use crate::jsapi::JSONWriteCallback;
1559 use crate::jsapi::JSPrincipals;
1560 use crate::jsapi::JSPropertySpec;
1561 use crate::jsapi::JSPropertySpec_Name;
1562 use crate::jsapi::JSProtoKey;
1563 use crate::jsapi::JSScript;
1564 use crate::jsapi::JSStructuredCloneData;
1565 use crate::jsapi::JSType;
1566 use crate::jsapi::Latin1Char;
1567 use crate::jsapi::ModuleErrorBehaviour;
1568 use crate::jsapi::ModuleType;
1569 use crate::jsapi::MutableHandleIdVector;
1570 use crate::jsapi::PromiseState;
1571 use crate::jsapi::PromiseUserInputEventHandlingState;
1572 use crate::jsapi::PropertyKey;
1573 use crate::jsapi::ReadOnlyCompileOptions;
1574 use crate::jsapi::Realm;
1575 use crate::jsapi::RealmOptions;
1576 use crate::jsapi::RefPtr;
1577 use crate::jsapi::RegExpFlags;
1578 use crate::jsapi::ScriptEnvironmentPreparer_Closure;
1579 use crate::jsapi::SourceText;
1580 use crate::jsapi::StackCapture;
1581 use crate::jsapi::Stencil;
1582 use crate::jsapi::StructuredCloneScope;
1583 use crate::jsapi::Symbol;
1584 use crate::jsapi::SymbolCode;
1585 use crate::jsapi::TaggedColumnNumberOneOrigin;
1586 use crate::jsapi::TwoByteChars;
1587 use crate::jsapi::UniqueChars;
1588 use crate::jsapi::Value;
1589 use crate::jsapi::WasmModule;
1590 use crate::jsapi::*;
1591 use crate::jsapi::{ElementAdder, IsArrayAnswer, PropertyDescriptor};
1592 use crate::jsapi::{JSFunction, JSNative, JSObject, JSString};
1593 use crate::jsapi::{
1594 JSStructuredCloneCallbacks, JSStructuredCloneReader, JSStructuredCloneWriter,
1595 };
1596 use crate::jsapi::{MallocSizeOf, ObjectOpResult, ObjectPrivateVisitor, TabSizes};
1597 use crate::jsapi::{SavedFrameResult, SavedFrameSelfHosted};
1598 include!("jsapi2_wrappers.in.rs");
1599 include!("glue2_wrappers.in.rs");
1600
1601 #[inline]
1602 pub unsafe fn SetPropertyIgnoringNamedGetter(
1603 cx: &mut JSContext,
1604 obj: HandleObject,
1605 id: HandleId,
1606 v: HandleValue,
1607 receiver: HandleValue,
1608 ownDesc: Option<Handle<PropertyDescriptor>>,
1609 result: *mut ObjectOpResult,
1610 ) -> bool {
1611 if let Some(ownDesc) = ownDesc {
1612 let ownDesc = ownDesc.into();
1613 jsapi::SetPropertyIgnoringNamedGetter(
1614 cx.raw_cx(),
1615 obj.into(),
1616 id.into(),
1617 v.into(),
1618 receiver.into(),
1619 &raw const ownDesc,
1620 result,
1621 )
1622 } else {
1623 jsapi::SetPropertyIgnoringNamedGetter(
1624 cx.raw_cx(),
1625 obj.into(),
1626 id.into(),
1627 v.into(),
1628 receiver.into(),
1629 ptr::null(),
1630 result,
1631 )
1632 }
1633 }
1634}