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, OnceLock, RwLock};
20
21use self::wrappers2::{
22 StackGCVectorStringAtIndex, StackGCVectorStringLength, StackGCVectorValueAtIndex,
23 StackGCVectorValueLength, ToStringSlow,
24};
25use crate::consts::{JSCLASS_GLOBAL_SLOT_COUNT, JSCLASS_RESERVED_SLOTS_MASK};
26use crate::consts::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
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 PendingExceptionStackInfo,
34};
35use crate::glue::{DeleteJSAutoStructuredCloneBuffer, NewJSAutoStructuredCloneBuffer};
36use crate::glue::{
37 GetIdVectorAddress, GetObjectVectorAddress, NewCompileOptions, SliceRootedIdVector,
38};
39use crate::jsapi;
40use crate::jsapi::glue::{DeleteRealmOptions, JS_Init, JS_NewRealmOptions};
41use crate::jsapi::js;
42use crate::jsapi::js::frontend::InitialStencilAndDelazifications;
43use crate::jsapi::mozilla::Utf8Unit;
44use crate::jsapi::shadow::BaseShape;
45use crate::jsapi::HandleObjectVector as RawHandleObjectVector;
46use crate::jsapi::HandleValue as RawHandleValue;
47use crate::jsapi::JS_AddExtraGCRootsTracer;
48use crate::jsapi::MutableHandleIdVector as RawMutableHandleIdVector;
49use crate::jsapi::MutableHandleValue as RawMutableHandleValue;
50use crate::jsapi::{already_AddRefed, jsid};
51use crate::jsapi::{BuildStackString, CaptureCurrentStack, StackFormat};
52use crate::jsapi::{HandleValueArray, StencilRelease};
53use crate::jsapi::{InitSelfHostedCode, IsWindowSlow};
54use crate::jsapi::{JSAutoStructuredCloneBuffer, JSStructuredCloneCallbacks, StructuredCloneScope};
55use crate::jsapi::{JSClass, JSClassOps, JSContext, Realm, JSCLASS_RESERVED_SLOTS_SHIFT};
56use crate::jsapi::{JSErrorReport, JSFunctionSpec, JSGCParamKey};
57use crate::jsapi::{JSObject, JSPropertySpec, JSRuntime};
58use crate::jsapi::{JSString, Object, PersistentRootedIdVector};
59use crate::jsapi::{JS_DefineFunctions, JS_DefineProperties, JS_DestroyContext, JS_ShutDown};
60use crate::jsapi::{JS_EnumerateStandardClasses, JS_GlobalObjectTraceHook};
61use crate::jsapi::{JS_MayResolveStandardClass, JS_NewContext, JS_ResolveStandardClass};
62use crate::jsapi::{JS_RequestInterruptCallback, JS_RequestInterruptCallbackCanWait};
63use crate::jsapi::{JS_SetGCParameter, JS_SetNativeStackQuota, JS_WrapObject, JS_WrapValue};
64use crate::jsapi::{JS_StackCapture_AllFrames, JS_StackCapture_MaxFrames};
65use crate::jsapi::{PersistentRootedObjectVector, ReadOnlyCompileOptions, RootingContext};
66use crate::jsapi::{
67 RootedObject, RootedValue, ToUint32Slow, ToUint64Slow, ToWindowProxyIfWindowSlow,
68};
69use crate::jsapi::{SetWarningReporter, SourceText, ToBooleanSlow};
70use crate::jsapi::{ToInt32Slow, ToInt64Slow, ToNumberSlow, ToUint16Slow};
71use crate::jsval::{JSVal, ObjectValue, UndefinedValue};
72use crate::panic::maybe_resume_unwind;
73use crate::realm::AutoRealm;
74use log::{debug, warn};
75use mozjs_sys::jsapi::JS::SavedFrameResult;
76pub use mozjs_sys::jsgc::{GCMethods, IntoHandle, IntoMutableHandle};
77pub use mozjs_sys::trace::Traceable as Trace;
78
79use crate::rooted;
80
81const STACK_QUOTA: usize = 128 * 8 * 1024;
85
86const SYSTEM_CODE_BUFFER: usize = 10 * 1024;
112
113const TRUSTED_SCRIPT_BUFFER: usize = 8 * 12800;
115
116trait ToResult {
117 fn to_result(self) -> Result<(), ()>;
118}
119
120impl ToResult for bool {
121 fn to_result(self) -> Result<(), ()> {
122 if self {
123 Ok(())
124 } else {
125 Err(())
126 }
127 }
128}
129
130pub struct RealmOptions(*mut jsapi::RealmOptions);
134
135impl Deref for RealmOptions {
136 type Target = jsapi::RealmOptions;
137 fn deref(&self) -> &Self::Target {
138 unsafe { &*self.0 }
139 }
140}
141
142impl DerefMut for RealmOptions {
143 fn deref_mut(&mut self) -> &mut Self::Target {
144 unsafe { &mut *self.0 }
145 }
146}
147
148impl Default for RealmOptions {
149 fn default() -> RealmOptions {
150 RealmOptions(unsafe { JS_NewRealmOptions() })
151 }
152}
153
154impl Drop for RealmOptions {
155 fn drop(&mut self) {
156 unsafe { DeleteRealmOptions(self.0) }
157 }
158}
159
160thread_local!(static CONTEXT: Cell<Option<NonNull<JSContext>>> = Cell::new(None));
161
162#[derive(PartialEq)]
163enum EngineState {
164 Uninitialized,
165 InitFailed,
166 Initialized,
167 ShutDown,
168}
169
170static ENGINE_STATE: Mutex<EngineState> = Mutex::new(EngineState::Uninitialized);
171
172static PROCESS_ENGINE_OUTSTANDING: OnceLock<Arc<AtomicU32>> = OnceLock::new();
179
180#[derive(Debug)]
181pub enum JSEngineError {
182 AlreadyInitialized,
183 AlreadyShutDown,
184 InitFailed,
185}
186
187pub struct JSEngine {
191 outstanding_handles: Arc<AtomicU32>,
193 marker: PhantomData<*mut ()>,
195}
196
197pub struct JSEngineHandle(Arc<AtomicU32>);
198
199impl Clone for JSEngineHandle {
200 fn clone(&self) -> JSEngineHandle {
201 self.0.fetch_add(1, Ordering::SeqCst);
202 JSEngineHandle(self.0.clone())
203 }
204}
205
206impl Drop for JSEngineHandle {
207 fn drop(&mut self) {
208 self.0.fetch_sub(1, Ordering::SeqCst);
209 }
210}
211
212impl JSEngine {
213 pub fn init() -> Result<JSEngine, JSEngineError> {
215 let mut state = ENGINE_STATE.lock().unwrap();
216 match *state {
217 EngineState::Initialized => return Err(JSEngineError::AlreadyInitialized),
218 EngineState::InitFailed => return Err(JSEngineError::InitFailed),
219 EngineState::ShutDown => return Err(JSEngineError::AlreadyShutDown),
220 EngineState::Uninitialized => (),
221 }
222 if unsafe { !JS_Init() } {
223 *state = EngineState::InitFailed;
224 Err(JSEngineError::InitFailed)
225 } else {
226 *state = EngineState::Initialized;
227 let outstanding = Arc::new(AtomicU32::new(0));
228 let _ = PROCESS_ENGINE_OUTSTANDING.set(outstanding.clone());
231 Ok(JSEngine {
232 outstanding_handles: outstanding,
233 marker: PhantomData,
234 })
235 }
236 }
237
238 pub fn process_handle() -> Option<JSEngineHandle> {
244 PROCESS_ENGINE_OUTSTANDING.get().map(|arc| {
245 arc.fetch_add(1, Ordering::SeqCst);
246 JSEngineHandle(arc.clone())
247 })
248 }
249
250 pub fn can_shutdown(&self) -> bool {
251 self.outstanding_handles.load(Ordering::SeqCst) == 0
252 }
253
254 pub fn handle(&self) -> JSEngineHandle {
256 self.outstanding_handles.fetch_add(1, Ordering::SeqCst);
257 JSEngineHandle(self.outstanding_handles.clone())
258 }
259}
260
261impl Drop for JSEngine {
264 fn drop(&mut self) {
265 let mut state = ENGINE_STATE.lock().unwrap();
266 if *state == EngineState::Initialized {
267 assert_eq!(
268 self.outstanding_handles.load(Ordering::SeqCst),
269 0,
270 "There are outstanding JS engine handles"
271 );
272 *state = EngineState::ShutDown;
273 unsafe {
274 JS_ShutDown();
275 }
276 }
277 }
278}
279
280pub fn transform_str_to_source_text(source: &str) -> SourceText<Utf8Unit> {
281 SourceText {
282 units_: source.as_ptr() as *const _,
283 length_: source.len() as u32,
284 ownsUnits_: false,
285 _phantom_0: PhantomData,
286 }
287}
288
289pub fn transform_u16_to_source_text(source: &[u16]) -> SourceText<u16> {
290 SourceText {
291 units_: source.as_ptr() as *const _,
292 length_: source.len() as u32,
293 ownsUnits_: false,
294 _phantom_0: PhantomData,
295 }
296}
297
298pub struct ParentRuntime {
302 parent: *mut JSRuntime,
304 engine: JSEngineHandle,
306 children_of_parent: Arc<()>,
308}
309unsafe impl Send for ParentRuntime {}
310
311pub struct Runtime {
313 cx: crate::context::JSContext,
315 engine: JSEngineHandle,
317 _parent_child_count: Option<Arc<()>>,
322 outstanding_children: Arc<()>,
328 thread_safe_handle: Arc<RwLock<Option<NonNull<JSContext>>>>,
332}
333
334impl Runtime {
335 pub fn get() -> Option<NonNull<JSContext>> {
339 CONTEXT.with(|context| context.get())
340 }
341
342 pub fn thread_safe_js_context(&self) -> ThreadSafeJSContext {
344 ThreadSafeJSContext(self.thread_safe_handle.clone())
347 }
348
349 pub fn new(engine: JSEngineHandle) -> Runtime {
351 unsafe { Self::create(engine, None) }
352 }
353
354 pub fn prepare_for_new_child(&self) -> ParentRuntime {
360 ParentRuntime {
361 parent: self.rt(),
362 engine: self.engine.clone(),
363 children_of_parent: self.outstanding_children.clone(),
364 }
365 }
366
367 pub unsafe fn create_with_parent(parent: ParentRuntime) -> Runtime {
375 Self::create(parent.engine.clone(), Some(parent))
376 }
377
378 unsafe fn create(engine: JSEngineHandle, parent: Option<ParentRuntime>) -> Runtime {
379 let parent_runtime = parent.as_ref().map_or(ptr::null_mut(), |r| r.parent);
380 let js_context = NonNull::new(JS_NewContext(
381 default_heapsize + (ChunkSize as u32),
382 parent_runtime,
383 ))
384 .unwrap();
385
386 JS_SetGCParameter(js_context.as_ptr(), JSGCParamKey::JSGC_MAX_BYTES, u32::MAX);
392
393 JS_AddExtraGCRootsTracer(js_context.as_ptr(), Some(trace_traceables), ptr::null_mut());
394
395 JS_SetNativeStackQuota(
396 js_context.as_ptr(),
397 STACK_QUOTA,
398 STACK_QUOTA - SYSTEM_CODE_BUFFER,
399 STACK_QUOTA - SYSTEM_CODE_BUFFER - TRUSTED_SCRIPT_BUFFER,
400 );
401
402 CONTEXT.with(|context| {
403 assert!(context.get().is_none());
404 context.set(Some(js_context));
405 });
406
407 #[cfg(target_pointer_width = "64")]
408 let cache = crate::jsapi::__BindgenOpaqueArray::<u64, 2>::default();
409 #[cfg(target_pointer_width = "32")]
410 let cache = crate::jsapi::__BindgenOpaqueArray::<u32, 2>::default();
411
412 InitSelfHostedCode(js_context.as_ptr(), cache, None);
413
414 SetWarningReporter(js_context.as_ptr(), Some(report_warning));
415
416 Runtime {
417 engine,
418 _parent_child_count: parent.map(|p| p.children_of_parent),
419 cx: crate::context::JSContext::from_ptr(js_context),
420 outstanding_children: Arc::new(()),
421 thread_safe_handle: Arc::new(RwLock::new(Some(js_context))),
422 }
423 }
424
425 pub fn rt(&self) -> *mut JSRuntime {
427 unsafe { wrappers2::JS_GetRuntime(self.cx_no_gc()) }
428 }
429
430 pub fn cx<'rt>(&'rt mut self) -> &'rt mut crate::context::JSContext {
432 &mut self.cx
433 }
434
435 pub fn cx_no_gc<'rt>(&'rt self) -> &'rt crate::context::JSContext {
437 &self.cx
438 }
439}
440
441pub fn evaluate_script(
442 cx: &mut crate::context::JSContext,
443 glob: HandleObject,
444 script: &str,
445 rval: MutableHandleValue,
446 options: CompileOptionsWrapper,
447) -> Result<(), ()> {
448 debug!(
449 "Evaluating script from {} with content {}",
450 options.filename(),
451 script
452 );
453
454 let mut realm = AutoRealm::new_from_handle(cx, glob);
455
456 unsafe {
457 let mut source = transform_str_to_source_text(&script);
458 if !wrappers2::Evaluate2(&mut realm, options.ptr, &mut source, rval.into()) {
459 debug!("...err!");
460 maybe_resume_unwind();
461 Err(())
462 } else {
463 debug!("...ok!");
466 Ok(())
467 }
468 }
469}
470
471impl Drop for Runtime {
472 fn drop(&mut self) {
473 self.thread_safe_handle.write().unwrap().take();
474 assert!(
475 Arc::get_mut(&mut self.outstanding_children).is_some(),
476 "This runtime still has live children."
477 );
478 unsafe {
479 JS_DestroyContext(self.cx.raw_cx());
480
481 CONTEXT.with(|context| {
482 assert!(context.take().is_some());
483 });
484 }
485 }
486}
487
488#[derive(Clone)]
492pub struct ThreadSafeJSContext(Arc<RwLock<Option<NonNull<JSContext>>>>);
493
494unsafe impl Send for ThreadSafeJSContext {}
495unsafe impl Sync for ThreadSafeJSContext {}
496
497impl ThreadSafeJSContext {
498 pub fn request_interrupt_callback(&self) {
502 if let Some(cx) = self.0.read().unwrap().as_ref() {
503 unsafe {
504 JS_RequestInterruptCallback(cx.as_ptr());
505 }
506 }
507 }
508
509 pub fn request_interrupt_callback_can_wait(&self) {
513 if let Some(cx) = self.0.read().unwrap().as_ref() {
514 unsafe {
515 JS_RequestInterruptCallbackCanWait(cx.as_ptr());
516 }
517 }
518 }
519}
520
521const ChunkShift: usize = 20;
522const ChunkSize: usize = 1 << ChunkShift;
523
524#[cfg(target_pointer_width = "32")]
525const ChunkLocationOffset: usize = ChunkSize - 2 * 4 - 8;
526
527pub struct RootedObjectVectorWrapper {
531 pub ptr: *mut PersistentRootedObjectVector,
532}
533
534impl RootedObjectVectorWrapper {
535 pub fn new(cx: *mut JSContext) -> RootedObjectVectorWrapper {
536 RootedObjectVectorWrapper {
537 ptr: unsafe { CreateRootedObjectVector(cx) },
538 }
539 }
540
541 pub fn append(&self, obj: *mut JSObject) -> bool {
542 unsafe { AppendToRootedObjectVector(self.ptr, obj) }
543 }
544
545 pub fn handle(&self) -> RawHandleObjectVector {
546 RawHandleObjectVector {
547 ptr: unsafe { GetObjectVectorAddress(self.ptr) },
548 }
549 }
550}
551
552impl Drop for RootedObjectVectorWrapper {
553 fn drop(&mut self) {
554 unsafe { DeleteRootedObjectVector(self.ptr) }
555 }
556}
557
558pub struct CompileOptionsWrapper {
559 pub ptr: *mut ReadOnlyCompileOptions,
560 filename: CString,
561}
562
563impl CompileOptionsWrapper {
564 pub fn new(cx: &crate::context::JSContext, filename: CString, line: u32) -> Self {
565 let ptr = unsafe { wrappers2::NewCompileOptions(cx, filename.as_ptr(), line) };
566 assert!(!ptr.is_null());
567 Self { ptr, filename }
568 }
569 #[deprecated(note = "Use CompileOptionsWrapper::new instead")]
573 pub unsafe fn new_raw(cx: *mut JSContext, filename: CString, line: u32) -> Self {
574 let ptr = NewCompileOptions(cx, filename.as_ptr(), line);
575 assert!(!ptr.is_null());
576 Self { ptr, filename }
577 }
578
579 pub fn filename(&self) -> &str {
580 self.filename.to_str().expect("Guaranteed by new")
581 }
582
583 pub fn set_introduction_type(&mut self, introduction_type: &'static CStr) {
584 unsafe {
585 (*self.ptr)._base.introductionType = introduction_type.as_ptr();
586 }
587 }
588
589 pub fn set_muted_errors(&mut self, muted_errors: bool) {
590 unsafe {
591 (*self.ptr)._base.mutedErrors_ = muted_errors;
592 }
593 }
594
595 pub fn set_is_run_once(&mut self, is_run_once: bool) {
596 unsafe {
597 (*self.ptr).isRunOnce = is_run_once;
598 }
599 }
600
601 pub fn set_no_script_rval(&mut self, no_script_rval: bool) {
602 unsafe {
603 (*self.ptr).noScriptRval = no_script_rval;
604 }
605 }
606
607 pub fn set_hide_script_from_debugger(&mut self, hide: bool) {
618 unsafe {
619 (*self.ptr)._base.hideScriptFromDebugger_ = hide;
625 }
626 }
627}
628
629impl Drop for CompileOptionsWrapper {
630 fn drop(&mut self) {
631 unsafe { DeleteCompileOptions(self.ptr) }
632 }
633}
634
635pub struct JSAutoStructuredCloneBufferWrapper {
636 ptr: NonNull<JSAutoStructuredCloneBuffer>,
637}
638
639impl JSAutoStructuredCloneBufferWrapper {
640 pub unsafe fn new(
641 scope: StructuredCloneScope,
642 callbacks: *const JSStructuredCloneCallbacks,
643 ) -> Self {
644 let raw_ptr = NewJSAutoStructuredCloneBuffer(scope, callbacks);
645 Self {
646 ptr: NonNull::new(raw_ptr).unwrap(),
647 }
648 }
649
650 pub fn as_raw_ptr(&self) -> *mut JSAutoStructuredCloneBuffer {
651 self.ptr.as_ptr()
652 }
653}
654
655impl Drop for JSAutoStructuredCloneBufferWrapper {
656 fn drop(&mut self) {
657 unsafe {
658 DeleteJSAutoStructuredCloneBuffer(self.ptr.as_ptr());
659 }
660 }
661}
662
663pub struct Stencil {
664 inner: already_AddRefed<InitialStencilAndDelazifications>,
665}
666
667impl Drop for Stencil {
671 fn drop(&mut self) {
672 if self.is_null() {
673 return;
674 }
675 unsafe {
676 StencilRelease(self.inner.mRawPtr);
677 }
678 }
679}
680
681impl Deref for Stencil {
682 type Target = *mut InitialStencilAndDelazifications;
683
684 fn deref(&self) -> &Self::Target {
685 &self.inner.mRawPtr
686 }
687}
688
689impl Stencil {
690 pub fn is_null(&self) -> bool {
691 self.inner.mRawPtr.is_null()
692 }
693}
694
695#[inline]
699pub unsafe fn ToBoolean(v: HandleValue) -> bool {
700 let val = *v.ptr.as_ptr();
701
702 if val.is_boolean() {
703 return val.to_boolean();
704 }
705
706 if val.is_int32() {
707 return val.to_int32() != 0;
708 }
709
710 if val.is_null_or_undefined() {
711 return false;
712 }
713
714 if val.is_double() {
715 let d = val.to_double();
716 return !d.is_nan() && d != 0f64;
717 }
718
719 if val.is_symbol() {
720 return true;
721 }
722
723 ToBooleanSlow(v.into())
724}
725
726#[inline]
727pub unsafe fn ToNumber(cx: *mut JSContext, v: HandleValue) -> Result<f64, ()> {
728 let val = *v.ptr.as_ptr();
729 if val.is_number() {
730 return Ok(val.to_number());
731 }
732
733 let mut out = Default::default();
734 if ToNumberSlow(cx, v.into_handle(), &mut out) {
735 Ok(out)
736 } else {
737 Err(())
738 }
739}
740
741#[inline]
742unsafe fn convert_from_int32<T: Default + Copy>(
743 cx: *mut JSContext,
744 v: HandleValue,
745 conv_fn: unsafe extern "C" fn(*mut JSContext, RawHandleValue, *mut T) -> bool,
746) -> Result<T, ()> {
747 let val = *v.ptr.as_ptr();
748 if val.is_int32() {
749 let intval: i64 = val.to_int32() as i64;
750 let intval = *(&intval as *const i64 as *const T);
752 return Ok(intval);
753 }
754
755 let mut out = Default::default();
756 if conv_fn(cx, v.into(), &mut out) {
757 Ok(out)
758 } else {
759 Err(())
760 }
761}
762
763#[inline]
764pub unsafe fn ToInt32(cx: *mut JSContext, v: HandleValue) -> Result<i32, ()> {
765 convert_from_int32::<i32>(cx, v, ToInt32Slow)
766}
767
768#[inline]
769pub unsafe fn ToUint32(cx: *mut JSContext, v: HandleValue) -> Result<u32, ()> {
770 convert_from_int32::<u32>(cx, v, ToUint32Slow)
771}
772
773#[inline]
774pub unsafe fn ToUint16(cx: *mut JSContext, v: HandleValue) -> Result<u16, ()> {
775 convert_from_int32::<u16>(cx, v, ToUint16Slow)
776}
777
778#[inline]
779pub unsafe fn ToInt64(cx: *mut JSContext, v: HandleValue) -> Result<i64, ()> {
780 convert_from_int32::<i64>(cx, v, ToInt64Slow)
781}
782
783#[inline]
784pub unsafe fn ToUint64(cx: *mut JSContext, v: HandleValue) -> Result<u64, ()> {
785 convert_from_int32::<u64>(cx, v, ToUint64Slow)
786}
787
788#[inline]
789pub unsafe fn ToString(cx: &mut crate::context::JSContext, v: HandleValue) -> *mut JSString {
790 let val = *v.ptr.as_ptr();
791 if val.is_string() {
792 return val.to_string();
793 }
794
795 ToStringSlow(cx, v.into())
796}
797
798pub unsafe fn ToWindowProxyIfWindow(obj: *mut JSObject) -> *mut JSObject {
799 if is_window(obj) {
800 ToWindowProxyIfWindowSlow(obj)
801 } else {
802 obj
803 }
804}
805
806pub unsafe extern "C" fn report_warning(_cx: *mut JSContext, report: *mut JSErrorReport) {
807 fn latin1_to_string(bytes: &[u8]) -> String {
808 bytes
809 .iter()
810 .map(|c| char::from_u32(*c as u32).unwrap())
811 .collect()
812 }
813
814 let fnptr = (*report)._base.filename.data_;
815 let fname = if !fnptr.is_null() {
816 let c_str = CStr::from_ptr(fnptr);
817 latin1_to_string(c_str.to_bytes())
818 } else {
819 "none".to_string()
820 };
821
822 let lineno = (*report)._base.lineno;
823 let column = (*report)._base.column._base;
824
825 let msg_ptr = (*report)._base.message_.data_ as *const u8;
826 let msg_len = (0usize..)
827 .find(|&i| *msg_ptr.offset(i as isize) == 0)
828 .unwrap();
829 let msg_slice = slice::from_raw_parts(msg_ptr, msg_len);
830 let msg = str::from_utf8_unchecked(msg_slice);
831
832 warn!("Warning at {}:{}:{}: {}\n", fname, lineno, column, msg);
833}
834
835pub struct IdVector(*mut PersistentRootedIdVector);
836
837impl IdVector {
838 pub unsafe fn new(cx: *mut JSContext) -> IdVector {
839 let vector = CreateRootedIdVector(cx);
840 assert!(!vector.is_null());
841 IdVector(vector)
842 }
843
844 pub fn handle_mut(&mut self) -> RawMutableHandleIdVector {
845 RawMutableHandleIdVector {
846 ptr: unsafe { GetIdVectorAddress(self.0) },
847 }
848 }
849}
850
851impl Drop for IdVector {
852 fn drop(&mut self) {
853 unsafe { DestroyRootedIdVector(self.0) }
854 }
855}
856
857impl Deref for IdVector {
858 type Target = [jsid];
859
860 fn deref(&self) -> &[jsid] {
861 unsafe {
862 let mut length = 0;
863 let pointer = SliceRootedIdVector(self.0, &mut length);
864 slice::from_raw_parts(pointer, length)
865 }
866 }
867}
868
869pub unsafe fn define_methods(
885 cx: *mut JSContext,
886 obj: HandleObject,
887 methods: &'static [JSFunctionSpec],
888) -> Result<(), ()> {
889 assert!({
890 match methods.last() {
891 Some(&JSFunctionSpec {
892 name,
893 call,
894 nargs,
895 flags,
896 selfHostedName,
897 }) => {
898 name.string_.is_null()
899 && call.is_zeroed()
900 && nargs == 0
901 && flags == 0
902 && selfHostedName.is_null()
903 }
904 None => false,
905 }
906 });
907
908 JS_DefineFunctions(cx, obj.into(), methods.as_ptr()).to_result()
909}
910
911pub unsafe fn define_properties(
927 cx: *mut JSContext,
928 obj: HandleObject,
929 properties: &'static [JSPropertySpec],
930) -> Result<(), ()> {
931 assert!({
932 match properties.last() {
933 Some(spec) => spec.is_zeroed(),
934 None => false,
935 }
936 });
937
938 JS_DefineProperties(cx, obj.into(), properties.as_ptr()).to_result()
939}
940
941static SIMPLE_GLOBAL_CLASS_OPS: JSClassOps = JSClassOps {
942 addProperty: None,
943 delProperty: None,
944 enumerate: Some(JS_EnumerateStandardClasses),
945 newEnumerate: None,
946 resolve: Some(JS_ResolveStandardClass),
947 mayResolve: Some(JS_MayResolveStandardClass),
948 finalize: None,
949 call: None,
950 construct: None,
951 trace: Some(JS_GlobalObjectTraceHook),
952};
953
954pub static SIMPLE_GLOBAL_CLASS: JSClass = JSClass {
956 name: c"Global".as_ptr(),
957 flags: JSCLASS_IS_GLOBAL
958 | ((JSCLASS_GLOBAL_SLOT_COUNT & JSCLASS_RESERVED_SLOTS_MASK)
959 << JSCLASS_RESERVED_SLOTS_SHIFT),
960 cOps: &SIMPLE_GLOBAL_CLASS_OPS as *const JSClassOps,
961 spec: ptr::null(),
962 ext: ptr::null(),
963 oOps: ptr::null(),
964};
965
966#[inline]
967unsafe fn get_object_group(obj: *mut JSObject) -> *mut BaseShape {
968 assert!(!obj.is_null());
969 let obj = obj as *mut Object;
970 (*(*obj).shape).base
971}
972
973#[inline]
974pub unsafe fn get_object_class(obj: *mut JSObject) -> *const JSClass {
975 (*get_object_group(obj)).clasp as *const _
976}
977
978#[inline]
979pub unsafe fn get_object_realm(obj: *mut JSObject) -> *mut Realm {
980 (*get_object_group(obj)).realm
981}
982
983#[inline]
984pub unsafe fn get_context_realm(cx: *mut JSContext) -> *mut Realm {
985 let cx = cx as *mut RootingContext;
986 (*cx).realm_
987}
988
989#[inline]
990pub fn is_dom_class(class: &JSClass) -> bool {
991 class.flags & JSCLASS_IS_DOMJSCLASS != 0
992}
993
994#[inline]
995pub unsafe fn is_dom_object(obj: *mut JSObject) -> bool {
996 is_dom_class(&*get_object_class(obj))
997}
998
999#[inline]
1000pub unsafe fn is_window(obj: *mut JSObject) -> bool {
1001 (*get_object_class(obj)).flags & JSCLASS_IS_GLOBAL != 0 && IsWindowSlow(obj)
1002}
1003
1004#[inline]
1005pub unsafe fn try_to_outerize(mut rval: MutableHandleValue) {
1006 let obj = rval.to_object();
1007 if is_window(obj) {
1008 let obj = ToWindowProxyIfWindowSlow(obj);
1009 assert!(!obj.is_null());
1010 rval.set(ObjectValue(&mut *obj));
1011 }
1012}
1013
1014#[inline]
1015pub unsafe fn try_to_outerize_object(mut rval: MutableHandleObject) {
1016 if is_window(*rval) {
1017 let obj = ToWindowProxyIfWindowSlow(*rval);
1018 assert!(!obj.is_null());
1019 rval.set(obj);
1020 }
1021}
1022
1023#[inline]
1024pub unsafe fn maybe_wrap_object(cx: *mut JSContext, mut obj: MutableHandleObject) {
1025 if get_object_realm(*obj) != get_context_realm(cx) {
1026 assert!(JS_WrapObject(cx, obj.reborrow().into()));
1027 }
1028 try_to_outerize_object(obj);
1029}
1030
1031#[inline]
1032pub unsafe fn maybe_wrap_object_value(
1033 cx: &mut crate::context::JSContext,
1034 rval: MutableHandleValue,
1035) {
1036 assert!(rval.is_object());
1037 let obj = rval.to_object();
1038 if get_object_realm(obj) != get_context_realm(cx.raw_cx()) {
1039 assert!(JS_WrapValue(cx.raw_cx(), rval.into()));
1040 } else if is_dom_object(obj) {
1041 try_to_outerize(rval);
1042 }
1043}
1044
1045#[inline]
1046pub fn maybe_wrap_object_or_null_value(
1047 cx: &mut crate::context::JSContext,
1048 rval: MutableHandleValue,
1049) {
1050 assert!(rval.is_object_or_null());
1051 if !rval.is_null() {
1052 unsafe { maybe_wrap_object_value(cx, rval) };
1053 }
1054}
1055
1056#[inline]
1057pub fn maybe_wrap_value(cx: &mut crate::context::JSContext, rval: MutableHandleValue) {
1058 if rval.is_string() {
1059 assert!(unsafe { JS_WrapValue(cx.raw_cx(), rval.into()) });
1060 } else if rval.is_object() {
1061 unsafe { maybe_wrap_object_value(cx, rval) };
1062 }
1063}
1064
1065#[macro_export]
1067macro_rules! new_jsjitinfo_bitfield_1 {
1068 (
1069 $type_: expr,
1070 $aliasSet_: expr,
1071 $returnType_: expr,
1072 $isInfallible: expr,
1073 $isMovable: expr,
1074 $isEliminatable: expr,
1075 $isAlwaysInSlot: expr,
1076 $isLazilyCachedInSlot: expr,
1077 $isTypedMethod: expr,
1078 $slotIndex: expr,
1079 ) => {
1080 0 | (($type_ as u32) << 0u32)
1081 | (($aliasSet_ as u32) << 4u32)
1082 | (($returnType_ as u32) << 8u32)
1083 | (($isInfallible as u32) << 16u32)
1084 | (($isMovable as u32) << 17u32)
1085 | (($isEliminatable as u32) << 18u32)
1086 | (($isAlwaysInSlot as u32) << 19u32)
1087 | (($isLazilyCachedInSlot as u32) << 20u32)
1088 | (($isTypedMethod as u32) << 21u32)
1089 | (($slotIndex as u32) << 22u32)
1090 };
1091}
1092
1093#[derive(Debug, Default)]
1094pub struct ScriptedCaller {
1095 pub filename: String,
1096 pub line: u32,
1097 pub col: u32,
1098}
1099
1100#[deprecated(note = "Use describe_scripted_caller_safe instead")]
1101pub unsafe fn describe_scripted_caller(cx: *mut JSContext) -> Result<ScriptedCaller, ()> {
1102 let mut buf = [0; 1024];
1103 let mut line = 0;
1104 let mut col = 0;
1105 if !DescribeScriptedCaller(cx, buf.as_mut_ptr(), buf.len(), &mut line, &mut col) {
1106 return Err(());
1107 }
1108 let filename = CStr::from_ptr((&buf) as *const _ as *const _);
1109 Ok(ScriptedCaller {
1110 filename: String::from_utf8_lossy(filename.to_bytes()).into_owned(),
1111 line,
1112 col,
1113 })
1114}
1115
1116pub fn describe_scripted_caller_safe(cx: &crate::context::JSContext) -> Result<ScriptedCaller, ()> {
1117 let mut buf = [0; 1024];
1118 let mut line = 0;
1119 let mut col = 0;
1120 if unsafe {
1121 !wrappers2::DescribeScriptedCaller(cx, buf.as_mut_ptr(), buf.len(), &mut line, &mut col)
1122 } {
1123 return Err(());
1124 }
1125 let filename = unsafe { CStr::from_ptr(buf.as_ptr()) };
1126 Ok(ScriptedCaller {
1127 filename: String::from_utf8_lossy(filename.to_bytes()).into_owned(),
1128 line,
1129 col,
1130 })
1131}
1132
1133pub struct ErrorInfo {
1134 pub message: String,
1135 pub filename: String,
1136 pub line: u32,
1137 pub col: u32,
1138}
1139
1140unsafe extern "C" fn fill_string_callback(ptr: *const c_char, len: usize, target: *mut c_void) {
1141 assert!(!ptr.is_null());
1142 let target = &mut *(target as *mut String);
1143
1144 let slice = slice::from_raw_parts(ptr as *const u8, len);
1145 target.push_str(str::from_utf8_unchecked(slice));
1146}
1147
1148pub fn error_info_from_exception_stack_safe(
1151 cx: &mut crate::context::JSContext,
1152 rval: MutableHandleValue,
1153) -> Option<ErrorInfo> {
1154 let mut message = String::new();
1155 let mut filename = String::new();
1156
1157 let mut line = 0;
1158 let mut col = 0;
1159
1160 unsafe {
1161 if !wrappers2::PendingExceptionStackInfo(
1162 cx,
1163 Some(fill_string_callback),
1164 &raw mut message as *mut c_void,
1165 &raw mut filename as *mut c_void,
1166 &mut line,
1167 &mut col,
1168 rval,
1169 ) {
1170 return None;
1171 }
1172 }
1173
1174 Some(ErrorInfo {
1175 message,
1176 filename,
1177 line,
1178 col,
1179 })
1180}
1181
1182#[deprecated(note = "Use error_info_from_exception_stack_safe instead")]
1183pub unsafe fn error_info_from_exception_stack(
1184 cx: *mut JSContext,
1185 rval: RawMutableHandleValue,
1186) -> Option<ErrorInfo> {
1187 let mut message = String::new();
1188 let mut filename = String::new();
1189
1190 let mut line = 0;
1191 let mut col = 0;
1192
1193 if !PendingExceptionStackInfo(
1194 cx,
1195 Some(fill_string_callback),
1196 &raw mut message as *mut c_void,
1197 &raw mut filename as *mut c_void,
1198 &mut line,
1199 &mut col,
1200 rval,
1201 ) {
1202 return None;
1203 }
1204
1205 Some(ErrorInfo {
1206 message,
1207 filename,
1208 line,
1209 col,
1210 })
1211}
1212
1213pub struct CapturedJSStack<'a> {
1214 cx: *mut JSContext,
1215 stack: RootedGuard<'a, *mut JSObject>,
1216}
1217
1218impl<'a> CapturedJSStack<'a> {
1219 pub unsafe fn new(
1220 cx: *mut JSContext,
1221 mut guard: RootedGuard<'a, *mut JSObject>,
1222 max_frame_count: Option<u32>,
1223 ) -> Option<Self> {
1224 let ref mut stack_capture = MaybeUninit::uninit();
1225 match max_frame_count {
1226 None => JS_StackCapture_AllFrames(stack_capture.as_mut_ptr()),
1227 Some(count) => JS_StackCapture_MaxFrames(count, stack_capture.as_mut_ptr()),
1228 };
1229 let ref mut stack_capture = stack_capture.assume_init();
1230
1231 if !CaptureCurrentStack(
1232 cx,
1233 guard.handle_mut().raw(),
1234 stack_capture,
1235 HandleObject::null().into(),
1236 ) {
1237 None
1238 } else {
1239 Some(CapturedJSStack { cx, stack: guard })
1240 }
1241 }
1242
1243 pub fn as_string(&self, indent: Option<usize>, format: StackFormat) -> Option<String> {
1244 unsafe {
1245 let stack_handle = self.stack.handle();
1246 rooted!(in(self.cx) let mut js_string = ptr::null_mut::<JSString>());
1247 let mut string_handle = js_string.handle_mut();
1248
1249 if !BuildStackString(
1250 self.cx,
1251 ptr::null_mut(),
1252 stack_handle.into(),
1253 string_handle.raw(),
1254 indent.unwrap_or(0),
1255 format,
1256 ) {
1257 return None;
1258 }
1259
1260 #[expect(deprecated)]
1261 Some(crate::conversions::unsafe_jsstr_to_string(
1262 self.cx,
1263 NonNull::new(string_handle.get())?,
1264 ))
1265 }
1266 }
1267
1268 pub fn for_each_stack_frame<F>(&self, mut f: F)
1270 where
1271 F: FnMut(Handle<*mut JSObject>),
1272 {
1273 rooted!(in(self.cx) let mut current_element = self.stack.clone());
1274 rooted!(in(self.cx) let mut next_element = ptr::null_mut::<JSObject>());
1275
1276 loop {
1277 f(current_element.handle());
1278
1279 unsafe {
1280 let result = jsapi::GetSavedFrameParent(
1281 self.cx,
1282 ptr::null_mut(),
1283 current_element.handle().into_handle(),
1284 next_element.handle_mut().into_handle_mut(),
1285 jsapi::SavedFrameSelfHosted::Include,
1286 );
1287
1288 if result != SavedFrameResult::Ok || next_element.is_null() {
1289 return;
1290 }
1291 }
1292 current_element.set(next_element.get());
1293 }
1294 }
1295}
1296
1297#[macro_export]
1298macro_rules! capture_stack {
1299 (&in($cx:expr) $($t:tt)*) => {
1300 capture_stack!(in(unsafe {$cx.raw_cx()}) $($t)*);
1301 };
1302 (in($cx:expr) let $name:ident = with max depth($max_frame_count:expr)) => {
1303 rooted!(in($cx) let mut __obj = ::std::ptr::null_mut());
1304 let $name = $crate::rust::CapturedJSStack::new($cx, __obj, Some($max_frame_count));
1305 };
1306 (in($cx:expr) let $name:ident ) => {
1307 rooted!(in($cx) let mut __obj = ::std::ptr::null_mut());
1308 let $name = $crate::rust::CapturedJSStack::new($cx, __obj, None);
1309 }
1310}
1311
1312pub struct EnvironmentChain {
1313 chain: *mut crate::jsapi::JS::EnvironmentChain,
1314}
1315
1316impl EnvironmentChain {
1317 pub fn new(
1318 cx: *mut JSContext,
1319 support_unscopeables: crate::jsapi::JS::SupportUnscopables,
1320 ) -> Self {
1321 unsafe {
1322 Self {
1323 chain: crate::jsapi::glue::NewEnvironmentChain(cx, support_unscopeables),
1324 }
1325 }
1326 }
1327
1328 pub fn append(&self, obj: *mut JSObject) {
1329 unsafe {
1330 assert!(crate::jsapi::glue::AppendToEnvironmentChain(
1331 self.chain, obj
1332 ));
1333 }
1334 }
1335
1336 pub fn get(&self) -> *mut crate::jsapi::JS::EnvironmentChain {
1337 self.chain
1338 }
1339}
1340
1341impl Drop for EnvironmentChain {
1342 fn drop(&mut self) {
1343 unsafe {
1344 crate::jsapi::glue::DeleteEnvironmentChain(self.chain);
1345 }
1346 }
1347}
1348
1349impl<'a> Handle<'a, StackGCVector<JSVal, js::TempAllocPolicy>> {
1350 pub fn at(&'a self, index: u32) -> Option<Handle<'a, JSVal>> {
1351 if index >= self.len() {
1352 return None;
1353 }
1354 let handle =
1355 unsafe { Handle::from_marked_location(StackGCVectorValueAtIndex(*self, index)) };
1356 Some(handle)
1357 }
1358
1359 pub fn len(&self) -> u32 {
1360 unsafe { StackGCVectorValueLength(*self) }
1361 }
1362}
1363
1364impl<'a> Handle<'a, StackGCVector<*mut JSString, js::TempAllocPolicy>> {
1365 pub fn at(&'a self, index: u32) -> Option<Handle<'a, *mut JSString>> {
1366 if index >= self.len() {
1367 return None;
1368 }
1369 let handle =
1370 unsafe { Handle::from_marked_location(StackGCVectorStringAtIndex(*self, index)) };
1371 Some(handle)
1372 }
1373
1374 pub fn len(&self) -> u32 {
1375 unsafe { StackGCVectorStringLength(*self) }
1376 }
1377}
1378
1379#[derive(Clone, Copy, Debug)]
1380pub enum ForOfIterationFailure<OtherError> {
1381 ValueIsNotIterable,
1382 JSFailed,
1384 Other(OtherError),
1385}
1386
1387impl<OtherError> From<OtherError> for ForOfIterationFailure<OtherError> {
1388 fn from(value: OtherError) -> Self {
1389 Self::Other(value)
1390 }
1391}
1392
1393pub fn for_of<Callback, OtherError>(
1400 cx: *mut JSContext,
1401 iterable: HandleValue<'_>,
1402 mut callback: Callback,
1403) -> Result<(), ForOfIterationFailure<OtherError>>
1404where
1405 Callback: FnMut(HandleValue<'_>) -> Result<ControlFlow<()>, ForOfIterationFailure<OtherError>>,
1406{
1407 #[allow(unused_variables)]
1413 let zero = unsafe { mem::zeroed() };
1414 let mut iterator = jsapi::ForOfIterator {
1415 cx_: cx,
1416 iterator: RootedObject::new_unrooted(ptr::null_mut()),
1417 nextMethod: RootedValue::new_unrooted(JSVal { asBits_: 0 }),
1418 index: ::std::u32::MAX, ..zero
1420 };
1421
1422 struct IteratorRootGuard<'a> {
1424 inner: &'a mut jsapi::ForOfIterator,
1425 }
1426
1427 impl<'a> Drop for IteratorRootGuard<'a> {
1428 fn drop(&mut self) {
1429 unsafe {
1431 self.inner.iterator.remove_from_root_stack();
1432 self.inner.nextMethod.remove_from_root_stack();
1433 }
1434 }
1435 }
1436 let guard = IteratorRootGuard {
1437 inner: &mut iterator,
1438 };
1439 let iterator = &mut *guard.inner;
1440
1441 unsafe {
1442 RootedObject::add_to_root_stack(&raw mut iterator.iterator, cx);
1443 RootedValue::add_to_root_stack(&raw mut iterator.nextMethod, cx);
1444 }
1445
1446 let success = unsafe {
1447 iterator.init(
1448 iterable.into_handle(),
1449 jsapi::ForOfIterator_NonIterableBehavior::AllowNonIterable,
1450 )
1451 };
1452 if !success {
1453 return Err(ForOfIterationFailure::JSFailed);
1454 }
1455 if !iterator.is_iterable() {
1456 return Err(ForOfIterationFailure::ValueIsNotIterable);
1457 }
1458
1459 let mut done = false;
1460 rooted!(in(cx) let mut value = UndefinedValue());
1461 loop {
1462 if !unsafe { iterator.next(value.handle_mut().into(), &mut done) } {
1463 return Err(ForOfIterationFailure::JSFailed);
1464 }
1465
1466 if done {
1467 break;
1468 }
1469
1470 if callback(value.handle())?.is_break() {
1471 break;
1472 }
1473 }
1474
1475 Ok(())
1476}
1477
1478#[deprecated(note = "Use wrappers2 instead")]
1480pub mod wrappers {
1481 macro_rules! wrap {
1482 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: Handle<$gentype:ty>, $($rest:tt)*) => {
1487 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1488 };
1489 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandle<$gentype:ty>, $($rest:tt)*) => {
1490 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1491 };
1492 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: Handle, $($rest:tt)*) => {
1493 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1494 };
1495 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandle, $($rest:tt)*) => {
1496 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1497 };
1498 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleFunction , $($rest:tt)*) => {
1499 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1500 };
1501 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleId , $($rest:tt)*) => {
1502 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1503 };
1504 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleObject , $($rest:tt)*) => {
1505 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1506 };
1507 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleScript , $($rest:tt)*) => {
1508 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1509 };
1510 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleString , $($rest:tt)*) => {
1511 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1512 };
1513 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleSymbol , $($rest:tt)*) => {
1514 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1515 };
1516 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: HandleValue , $($rest:tt)*) => {
1517 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1518 };
1519 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleFunction , $($rest:tt)*) => {
1520 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1521 };
1522 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleId , $($rest:tt)*) => {
1523 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1524 };
1525 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleObject , $($rest:tt)*) => {
1526 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1527 };
1528 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleScript , $($rest:tt)*) => {
1529 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1530 };
1531 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleString , $($rest:tt)*) => {
1532 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1533 };
1534 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleSymbol , $($rest:tt)*) => {
1535 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1536 };
1537 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: MutableHandleValue , $($rest:tt)*) => {
1538 wrap!(@inner $saved <> ($($acc,)* $arg.into(),) <> $($rest)*);
1539 };
1540 (@inner $saved:tt <> ($($acc:expr,)*) <> $arg:ident: $type:ty, $($rest:tt)*) => {
1541 wrap!(@inner $saved <> ($($acc,)* $arg,) <> $($rest)*);
1542 };
1543 (@inner ($module:tt: $func_name:ident ($($args:tt)*) -> $outtype:ty) <> ($($argexprs:expr,)*) <> ) => {
1544 #[inline]
1545 pub unsafe fn $func_name($($args)*) -> $outtype {
1546 $module::$func_name($($argexprs),*)
1547 }
1548 };
1549 ($module:tt: pub fn $func_name:ident($($args:tt)*) -> $outtype:ty) => {
1550 wrap!(@inner ($module: $func_name ($($args)*) -> $outtype) <> () <> $($args)* ,);
1551 };
1552 ($module:tt: pub fn $func_name:ident($($args:tt)*)) => {
1553 wrap!($module: pub fn $func_name($($args)*) -> ());
1554 }
1555 }
1556
1557 use super::*;
1558 use crate::glue;
1559 use crate::glue::EncodedStringCallback;
1560 use crate::glue::StringCallback;
1561 use crate::jsapi;
1562 use crate::jsapi::js::TempAllocPolicy;
1563 use crate::jsapi::jsid;
1564 use crate::jsapi::mozilla::Utf8Unit;
1565 use crate::jsapi::BigInt;
1566 use crate::jsapi::CallArgs;
1567 use crate::jsapi::CloneDataPolicy;
1568 use crate::jsapi::ColumnNumberOneOrigin;
1569 use crate::jsapi::CompartmentTransplantCallback;
1570 use crate::jsapi::EnvironmentChain;
1571 use crate::jsapi::JSONParseHandler;
1572 use crate::jsapi::Latin1Char;
1573 use crate::jsapi::PropertyKey;
1574 use crate::jsapi::TaggedColumnNumberOneOrigin;
1575 use crate::jsapi::ESClass;
1577 use crate::jsapi::ExceptionStackBehavior;
1578 use crate::jsapi::ForOfIterator;
1579 use crate::jsapi::ForOfIterator_NonIterableBehavior;
1580 use crate::jsapi::HandleObjectVector;
1581 use crate::jsapi::InstantiateOptions;
1582 use crate::jsapi::JSClass;
1583 use crate::jsapi::JSErrorReport;
1584 use crate::jsapi::JSExnType;
1585 use crate::jsapi::JSFunctionSpecWithHelp;
1586 use crate::jsapi::JSJitInfo;
1587 use crate::jsapi::JSONWriteCallback;
1588 use crate::jsapi::JSPrincipals;
1589 use crate::jsapi::JSPropertySpec;
1590 use crate::jsapi::JSPropertySpec_Name;
1591 use crate::jsapi::JSProtoKey;
1592 use crate::jsapi::JSScript;
1593 use crate::jsapi::JSStructuredCloneData;
1594 use crate::jsapi::JSType;
1595 use crate::jsapi::ModuleErrorBehaviour;
1596 use crate::jsapi::ModuleType;
1597 use crate::jsapi::MutableHandleIdVector;
1598 use crate::jsapi::PromiseState;
1599 use crate::jsapi::PromiseUserInputEventHandlingState;
1600 use crate::jsapi::ReadOnlyCompileOptions;
1601 use crate::jsapi::Realm;
1602 use crate::jsapi::RefPtr;
1603 use crate::jsapi::RegExpFlags;
1604 use crate::jsapi::ScriptEnvironmentPreparer_Closure;
1605 use crate::jsapi::SourceText;
1606 use crate::jsapi::StackCapture;
1607 use crate::jsapi::Stencil;
1608 use crate::jsapi::StructuredCloneScope;
1609 use crate::jsapi::Symbol;
1610 use crate::jsapi::SymbolCode;
1611 use crate::jsapi::TranscodeBuffer;
1612 use crate::jsapi::TwoByteChars;
1613 use crate::jsapi::UniqueChars;
1614 use crate::jsapi::Value;
1615 use crate::jsapi::WasmModule;
1616 use crate::jsapi::{ElementAdder, IsArrayAnswer, PropertyDescriptor};
1617 use crate::jsapi::{JSContext, JSFunction, JSNative, JSObject, JSString};
1618 use crate::jsapi::{
1619 JSStructuredCloneCallbacks, JSStructuredCloneReader, JSStructuredCloneWriter,
1620 };
1621 use crate::jsapi::{MallocSizeOf, ObjectOpResult, ObjectPrivateVisitor, TabSizes};
1622 use crate::jsapi::{SavedFrameResult, SavedFrameSelfHosted};
1623 include!("jsapi_wrappers.in.rs");
1624 include!("glue_wrappers.in.rs");
1625}
1626
1627pub mod wrappers2 {
1629 macro_rules! wrap {
1630 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: Handle<$gentype:ty>, $($rest:tt)*) => {
1634 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: Handle<$gentype>) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1635 };
1636 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandle<$gentype:ty>, $($rest:tt)*) => {
1637 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandle<$gentype>) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1638 };
1639 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: Handle, $($rest:tt)*) => {
1640 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: Handle) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1641 };
1642 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandle, $($rest:tt)*) => {
1643 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandle) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1644 };
1645 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleFunction , $($rest:tt)*) => {
1646 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleFunction) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1647 };
1648 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleId , $($rest:tt)*) => {
1649 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleId) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1650 };
1651 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleObject , $($rest:tt)*) => {
1652 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleObject) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1653 };
1654 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleScript , $($rest:tt)*) => {
1655 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleScript) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1656 };
1657 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleString , $($rest:tt)*) => {
1658 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleString) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1659 };
1660 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleSymbol , $($rest:tt)*) => {
1661 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleSymbol) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1662 };
1663 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: HandleValue , $($rest:tt)*) => {
1664 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: HandleValue) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1665 };
1666 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleFunction , $($rest:tt)*) => {
1667 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleFunction) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1668 };
1669 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleId , $($rest:tt)*) => {
1670 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleId) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1671 };
1672 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleObject , $($rest:tt)*) => {
1673 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleObject) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1674 };
1675 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleScript , $($rest:tt)*) => {
1676 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleScript) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1677 };
1678 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleString , $($rest:tt)*) => {
1679 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleString) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1680 };
1681 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleSymbol , $($rest:tt)*) => {
1682 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleSymbol) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1683 };
1684 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: MutableHandleValue , $($rest:tt)*) => {
1685 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: MutableHandleValue) <> ($($arg_expr_acc,)* $arg.into(),) <> $($rest)*);
1686 };
1687 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: &mut JSContext , $($rest:tt)*) => {
1688 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: &mut JSContext) <> ($($arg_expr_acc,)* $arg.raw_cx(),) <> $($rest)*);
1689 };
1690 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: &JSContext , $($rest:tt)*) => {
1691 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: &JSContext) <> ($($arg_expr_acc,)* $arg.raw_cx_no_gc(),) <> $($rest)*);
1692 };
1693 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: *const AutoRequireNoGC , $($rest:tt)*) => {
1695 wrap!(@inner $saved <> ($($arg_sig_acc)*) <> ($($arg_expr_acc,)* ::std::ptr::null(),) <> $($rest)*);
1696 };
1697 (@inner $saved:tt <> ($($arg_sig_acc:tt)*) <> ($($arg_expr_acc:expr,)*) <> $arg:ident: $type:ty, $($rest:tt)*) => {
1698 wrap!(@inner $saved <> ($($arg_sig_acc)* , $arg: $type) <> ($($arg_expr_acc,)* $arg,) <> $($rest)*);
1699 };
1700 (@inner ($module:tt: $func_name:ident -> $outtype:ty) <> (, $($args:tt)*) <> ($($argexprs:expr,)*) <> ) => {
1701 #[inline]
1702 pub unsafe fn $func_name($($args)*) -> $outtype {
1703 $module::$func_name($($argexprs),*)
1704 }
1705 };
1706 ($module:tt: pub fn $func_name:ident($($args:tt)*) -> $outtype:ty) => {
1707 wrap!(@inner ($module: $func_name -> $outtype) <> () <> () <> $($args)* ,);
1708 };
1709 ($module:tt: pub fn $func_name:ident($($args:tt)*)) => {
1710 wrap!($module: pub fn $func_name($($args)*) -> ());
1711 }
1712 }
1713
1714 use super::*;
1715 use super::{
1716 Handle, HandleFunction, HandleId, HandleObject, HandleScript, HandleString, HandleValue,
1717 HandleValueArray, MutableHandle, MutableHandleId, MutableHandleObject, MutableHandleString,
1718 MutableHandleValue, StackGCVector,
1719 };
1720 use crate::context::JSContext;
1721 use crate::glue;
1722 use crate::glue::*;
1723 use crate::jsapi;
1724 use crate::jsapi::js::TempAllocPolicy;
1725 use crate::jsapi::mozilla::Utf8Unit;
1726 use crate::jsapi::mozilla::*;
1727 use crate::jsapi::BigInt;
1728 use crate::jsapi::CallArgs;
1729 use crate::jsapi::CloneDataPolicy;
1730 use crate::jsapi::ColumnNumberOneOrigin;
1731 use crate::jsapi::CompartmentTransplantCallback;
1732 use crate::jsapi::ESClass;
1733 use crate::jsapi::EnvironmentChain;
1734 use crate::jsapi::ExceptionStackBehavior;
1735 use crate::jsapi::ForOfIterator;
1736 use crate::jsapi::ForOfIterator_NonIterableBehavior;
1737 use crate::jsapi::HandleObjectVector;
1738 use crate::jsapi::InstantiateOptions;
1739 use crate::jsapi::JSClass;
1740 use crate::jsapi::JSErrorReport;
1741 use crate::jsapi::JSExnType;
1742 use crate::jsapi::JSFunctionSpecWithHelp;
1743 use crate::jsapi::JSJitInfo;
1744 use crate::jsapi::JSONParseHandler;
1745 use crate::jsapi::JSONWriteCallback;
1746 use crate::jsapi::JSPrincipals;
1747 use crate::jsapi::JSPropertySpec;
1748 use crate::jsapi::JSPropertySpec_Name;
1749 use crate::jsapi::JSProtoKey;
1750 use crate::jsapi::JSScript;
1751 use crate::jsapi::JSStructuredCloneData;
1752 use crate::jsapi::JSType;
1753 use crate::jsapi::Latin1Char;
1754 use crate::jsapi::ModuleErrorBehaviour;
1755 use crate::jsapi::ModuleType;
1756 use crate::jsapi::MutableHandleIdVector;
1757 use crate::jsapi::PromiseState;
1758 use crate::jsapi::PromiseUserInputEventHandlingState;
1759 use crate::jsapi::PropertyKey;
1760 use crate::jsapi::ReadOnlyCompileOptions;
1761 use crate::jsapi::Realm;
1762 use crate::jsapi::RealmOptions;
1763 use crate::jsapi::RefPtr;
1764 use crate::jsapi::RegExpFlags;
1765 use crate::jsapi::ScriptEnvironmentPreparer_Closure;
1766 use crate::jsapi::SourceText;
1767 use crate::jsapi::StackCapture;
1768 use crate::jsapi::Stencil;
1769 use crate::jsapi::StructuredCloneScope;
1770 use crate::jsapi::Symbol;
1771 use crate::jsapi::SymbolCode;
1772 use crate::jsapi::TaggedColumnNumberOneOrigin;
1773 use crate::jsapi::TranscodeBuffer;
1774 use crate::jsapi::TwoByteChars;
1775 use crate::jsapi::UniqueChars;
1776 use crate::jsapi::Value;
1777 use crate::jsapi::WasmModule;
1778 use crate::jsapi::*;
1779 use crate::jsapi::{ElementAdder, IsArrayAnswer, PropertyDescriptor};
1780 use crate::jsapi::{JSFunction, JSNative, JSObject, JSString};
1781 use crate::jsapi::{
1782 JSStructuredCloneCallbacks, JSStructuredCloneReader, JSStructuredCloneWriter,
1783 };
1784 use crate::jsapi::{MallocSizeOf, ObjectOpResult, ObjectPrivateVisitor, TabSizes};
1785 use crate::jsapi::{SavedFrameResult, SavedFrameSelfHosted};
1786 include!("jsapi2_wrappers.in.rs");
1787 include!("glue2_wrappers.in.rs");
1788
1789 #[inline]
1790 pub unsafe fn SetPropertyIgnoringNamedGetter(
1791 cx: &mut JSContext,
1792 obj: HandleObject,
1793 id: HandleId,
1794 v: HandleValue,
1795 receiver: HandleValue,
1796 ownDesc: Option<Handle<PropertyDescriptor>>,
1797 result: *mut ObjectOpResult,
1798 ) -> bool {
1799 if let Some(ownDesc) = ownDesc {
1800 let ownDesc = ownDesc.into();
1801 jsapi::SetPropertyIgnoringNamedGetter(
1802 cx.raw_cx(),
1803 obj.into(),
1804 id.into(),
1805 v.into(),
1806 receiver.into(),
1807 &raw const ownDesc,
1808 result,
1809 )
1810 } else {
1811 jsapi::SetPropertyIgnoringNamedGetter(
1812 cx.raw_cx(),
1813 obj.into(),
1814 id.into(),
1815 v.into(),
1816 receiver.into(),
1817 ptr::null(),
1818 result,
1819 )
1820 }
1821 }
1822}