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