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