1use crate::jsapi::glue::JS_ForOfIteratorInit;
6use crate::jsapi::glue::JS_ForOfIteratorNext;
7use crate::jsapi::jsid;
8use crate::jsapi::mozilla;
9use crate::jsapi::JSAutoRealm;
10use crate::jsapi::JSContext;
11use crate::jsapi::JSErrNum;
12use crate::jsapi::JSFunctionSpec;
13use crate::jsapi::JSJitGetterCallArgs;
14use crate::jsapi::JSJitMethodCallArgs;
15use crate::jsapi::JSJitSetterCallArgs;
16use crate::jsapi::JSNativeWrapper;
17use crate::jsapi::JSObject;
18use crate::jsapi::JSPropertySpec;
19use crate::jsapi::JSPropertySpec_Kind;
20use crate::jsapi::JSPropertySpec_Name;
21use crate::jsapi::JS;
22use crate::jsapi::JS::Scalar::Type;
23use crate::jsgc::{RootKind, Rooted, RootedBase, ValueArray};
24use crate::jsid::VoidId;
25use crate::jsval::{JSVal, UndefinedValue};
26
27use std::marker::PhantomData;
28use std::ops::Deref;
29use std::ptr;
30
31impl<T> Deref for JS::Handle<T> {
32 type Target = T;
33
34 fn deref<'a>(&'a self) -> &'a T {
35 unsafe { &*self.ptr }
36 }
37}
38
39impl<T> Deref for JS::MutableHandle<T> {
40 type Target = T;
41
42 fn deref<'a>(&'a self) -> &'a T {
43 unsafe { &*self.ptr }
44 }
45}
46
47impl Default for jsid {
48 fn default() -> Self {
49 VoidId()
50 }
51}
52
53impl Default for JS::PropertyDescriptor {
54 fn default() -> Self {
55 JS::PropertyDescriptor {
56 _bitfield_align_1: [],
57 _bitfield_1: Default::default(),
58 getter_: ptr::null_mut(),
59 setter_: ptr::null_mut(),
60 value_: UndefinedValue(),
61 }
62 }
63}
64
65impl Drop for JSAutoRealm {
66 fn drop(&mut self) {
67 unsafe {
68 JS::LeaveRealm(self.cx_, self.oldRealm_);
69 }
70 }
71}
72
73impl<T> JS::Handle<T> {
74 pub fn get(&self) -> T
75 where
76 T: Copy,
77 {
78 unsafe { *self.ptr }
79 }
80
81 pub unsafe fn from_marked_location(ptr: *const T) -> JS::Handle<T> {
82 JS::Handle {
83 ptr: ptr as *mut T,
84 _phantom_0: PhantomData,
85 }
86 }
87}
88
89impl<T> JS::MutableHandle<T> {
90 pub unsafe fn from_marked_location(ptr: *mut T) -> JS::MutableHandle<T> {
91 JS::MutableHandle {
92 ptr,
93 _phantom_0: PhantomData,
94 }
95 }
96
97 pub fn handle(&self) -> JS::Handle<T> {
98 unsafe { JS::Handle::from_marked_location(self.ptr as *const _) }
99 }
100
101 pub fn get(&self) -> T
102 where
103 T: Copy,
104 {
105 unsafe { *self.ptr }
106 }
107
108 pub fn set(&self, v: T)
109 where
110 T: Copy,
111 {
112 unsafe { *self.ptr = v }
113 }
114
115 pub fn as_ptr(self) -> *mut T {
119 self.ptr
120 }
121}
122
123impl JS::HandleValue {
124 pub fn null() -> JS::HandleValue {
125 unsafe { JS::NullHandleValue }
126 }
127
128 pub fn undefined() -> JS::HandleValue {
129 unsafe { JS::UndefinedHandleValue }
130 }
131}
132
133impl JS::HandleValueArray {
134 pub fn empty() -> JS::HandleValueArray {
135 JS::HandleValueArray {
136 length_: 0,
137 elements_: ptr::null(),
138 }
139 }
140}
141
142impl<const N: usize> From<&Rooted<ValueArray<N>>> for JS::HandleValueArray {
143 fn from(array: &Rooted<ValueArray<N>>) -> JS::HandleValueArray {
144 JS::HandleValueArray {
145 length_: N,
146 elements_: array.data.get_ptr(),
147 }
148 }
149}
150
151impl From<&JS::CallArgs> for JS::HandleValueArray {
152 fn from(args: &JS::CallArgs) -> JS::HandleValueArray {
153 JS::HandleValueArray {
154 length_: args.argc_ as usize,
155 elements_: args.argv_ as *const _,
156 }
157 }
158}
159
160impl From<JS::Handle<JSVal>> for JS::HandleValueArray {
161 fn from(handle: JS::Handle<JSVal>) -> JS::HandleValueArray {
162 JS::HandleValueArray {
163 length_: 1,
164 elements_: handle.ptr,
165 }
166 }
167}
168
169const NULL_OBJECT: *mut JSObject = 0 as *mut JSObject;
170
171impl JS::HandleObject {
172 pub fn null() -> JS::HandleObject {
173 unsafe { JS::HandleObject::from_marked_location(&NULL_OBJECT) }
174 }
175}
176
177impl JSAutoRealm {
181 pub fn new(cx: *mut JSContext, target: *mut JSObject) -> JSAutoRealm {
182 JSAutoRealm {
183 cx_: cx,
184 oldRealm_: unsafe { JS::EnterRealm(cx, target) },
185 }
186 }
187}
188
189impl JS::AutoGCRooter {
190 pub fn new_unrooted(kind: JS::AutoGCRooterKind) -> JS::AutoGCRooter {
191 JS::AutoGCRooter {
192 down: ptr::null_mut(),
193 kind_: kind,
194 stackTop: ptr::null_mut(),
195 }
196 }
197
198 pub unsafe fn add_to_root_stack(&mut self, cx: *mut JSContext) {
199 #[allow(non_snake_case)]
200 let autoGCRooters: *mut _ = {
201 let rooting_cx = cx as *mut JS::RootingContext;
202 &mut (*rooting_cx).autoGCRooters_.0[self.kind_ as usize]
203 };
204 self.stackTop = autoGCRooters as *mut *mut _;
205 self.down = *autoGCRooters as *mut _;
206
207 assert!(*self.stackTop != self);
208 *autoGCRooters = self as *mut _ as _;
209 }
210
211 pub unsafe fn remove_from_root_stack(&mut self) {
212 assert!(*self.stackTop == self);
213 *self.stackTop = self.down;
214 }
215}
216
217impl JSJitMethodCallArgs {
218 #[inline]
219 pub fn get(&self, i: u32) -> JS::HandleValue {
220 unsafe {
221 if i < self.argc_ {
222 JS::HandleValue::from_marked_location(self.argv_.offset(i as isize))
223 } else {
224 JS::UndefinedHandleValue
225 }
226 }
227 }
228
229 #[inline]
230 pub fn index(&self, i: u32) -> JS::HandleValue {
231 assert!(i < self.argc_);
232 unsafe { JS::HandleValue::from_marked_location(self.argv_.offset(i as isize)) }
233 }
234
235 #[inline]
236 pub fn index_mut(&self, i: u32) -> JS::MutableHandleValue {
237 assert!(i < self.argc_);
238 unsafe { JS::MutableHandleValue::from_marked_location(self.argv_.offset(i as isize)) }
239 }
240
241 #[inline]
242 pub fn rval(&self) -> JS::MutableHandleValue {
243 unsafe { JS::MutableHandleValue::from_marked_location(self.argv_.offset(-2)) }
244 }
245}
246
247impl JSJitGetterCallArgs {
248 #[inline]
249 pub fn rval(&self) -> JS::MutableHandleValue {
250 self._base
251 }
252}
253
254impl JS::CallArgs {
257 #[inline]
258 pub unsafe fn from_vp(vp: *mut JS::Value, argc: u32) -> JS::CallArgs {
259 JS::CallArgs {
264 _bitfield_align_1: Default::default(),
265 _bitfield_1: JS::CallArgs::new_bitfield_1((*vp.offset(1)).is_magic(), false),
266 argc_: argc,
267 argv_: vp.offset(2),
268 #[cfg(not(feature = "debugmozjs"))]
269 __bindgen_padding_0: [0, 0, 0],
270 #[cfg(feature = "debugmozjs")]
271 wantUsedRval_: JS::detail::IncludeUsedRval { usedRval_: false },
272 }
273 }
274
275 #[inline]
276 pub fn index(&self, i: u32) -> JS::HandleValue {
277 assert!(i < self.argc_);
278 unsafe { JS::HandleValue::from_marked_location(self.argv_.offset(i as isize)) }
279 }
280
281 #[inline]
282 pub fn index_mut(&self, i: u32) -> JS::MutableHandleValue {
283 assert!(i < self.argc_);
284 unsafe { JS::MutableHandleValue::from_marked_location(self.argv_.offset(i as isize)) }
285 }
286
287 #[inline]
288 pub fn get(&self, i: u32) -> JS::HandleValue {
289 unsafe {
290 if i < self.argc_ {
291 JS::HandleValue::from_marked_location(self.argv_.offset(i as isize))
292 } else {
293 JS::UndefinedHandleValue
294 }
295 }
296 }
297
298 #[inline]
299 pub fn rval(&self) -> JS::MutableHandleValue {
300 unsafe { JS::MutableHandleValue::from_marked_location(self.argv_.offset(-2)) }
301 }
302
303 #[inline]
304 pub fn thisv(&self) -> JS::HandleValue {
305 unsafe { JS::HandleValue::from_marked_location(self.argv_.offset(-1)) }
306 }
307
308 #[inline]
309 pub fn calleev(&self) -> JS::HandleValue {
310 unsafe { JS::HandleValue::from_marked_location(self.argv_.offset(-2)) }
311 }
312
313 #[inline]
314 pub fn callee(&self) -> *mut JSObject {
315 self.calleev().to_object()
316 }
317
318 #[inline]
319 pub fn new_target(&self) -> JS::MutableHandleValue {
320 assert!(self.constructing_());
321 unsafe {
322 JS::MutableHandleValue::from_marked_location(self.argv_.offset(self.argc_ as isize))
323 }
324 }
325
326 #[inline]
327 pub fn is_constructing(&self) -> bool {
328 unsafe { (*self.argv_.offset(-1)).is_magic() }
329 }
330}
331
332impl JSJitSetterCallArgs {
333 #[inline]
334 pub fn get(&self, i: u32) -> JS::HandleValue {
335 assert!(i == 0);
336 self._base.handle()
337 }
338}
339
340impl JSFunctionSpec {
341 pub const ZERO: Self = JSFunctionSpec {
342 name: JSPropertySpec_Name {
343 string_: ptr::null(),
344 },
345 selfHostedName: 0 as *const _,
346 flags: 0,
347 nargs: 0,
348 call: JSNativeWrapper::ZERO,
349 };
350
351 pub fn is_zeroed(&self) -> bool {
352 (unsafe { self.name.string_.is_null() })
353 && self.selfHostedName.is_null()
354 && self.flags == 0
355 && self.nargs == 0
356 && self.call.is_zeroed()
357 }
358}
359
360impl JSPropertySpec {
361 pub const ZERO: Self = JSPropertySpec {
362 name: JSPropertySpec_Name {
363 string_: ptr::null(),
364 },
365 attributes_: 0,
366 kind_: JSPropertySpec_Kind::NativeAccessor,
367 u: crate::jsapi::JSPropertySpec_AccessorsOrValue {
368 accessors: crate::jsapi::JSPropertySpec_AccessorsOrValue_Accessors {
369 getter: crate::jsapi::JSPropertySpec_Accessor {
370 native: JSNativeWrapper::ZERO,
371 },
372 setter: crate::jsapi::JSPropertySpec_Accessor {
373 native: JSNativeWrapper::ZERO,
374 },
375 },
376 },
377 };
378
379 pub fn is_accessor(&self) -> bool {
381 self.kind_ == JSPropertySpec_Kind::NativeAccessor
382 || self.kind_ == JSPropertySpec_Kind::SelfHostedAccessor
383 }
384
385 pub fn is_zeroed(&self) -> bool {
386 (unsafe { self.name.string_.is_null() })
387 && self.attributes_ == 0
388 && self.is_accessor()
389 && unsafe { self.u.accessors.getter.native.is_zeroed() }
390 && unsafe { self.u.accessors.setter.native.is_zeroed() }
391 }
392}
393
394impl JSNativeWrapper {
395 pub const ZERO: Self = JSNativeWrapper {
396 info: 0 as *const _,
397 op: None,
398 };
399
400 pub fn is_zeroed(&self) -> bool {
401 self.op.is_none() && self.info.is_null()
402 }
403}
404
405impl RootedBase {
406 unsafe fn add_to_root_stack(this: *mut Self, cx: *mut JSContext, kind: JS::RootKind) {
407 let stack = Self::get_root_stack(cx, kind);
408 (*this).stack = stack;
409 (*this).prev = *stack;
410
411 *stack = this as usize as _;
412 }
413
414 unsafe fn remove_from_root_stack(&mut self) {
415 assert!(*self.stack == self as *mut _ as usize as _);
416 *self.stack = self.prev;
417 }
418
419 unsafe fn get_root_stack(cx: *mut JSContext, kind: JS::RootKind) -> *mut *mut RootedBase {
420 let kind = kind as usize;
421 let rooting_cx = Self::get_rooting_context(cx);
422 &mut (*rooting_cx).stackRoots_.0[kind] as *mut _ as *mut _
423 }
424
425 unsafe fn get_rooting_context(cx: *mut JSContext) -> *mut JS::RootingContext {
426 cx as *mut JS::RootingContext
427 }
428}
429
430impl<T: RootKind> JS::Rooted<T> {
431 pub fn new_unrooted(initial: T) -> JS::Rooted<T> {
432 JS::Rooted {
433 vtable: T::VTABLE,
434 base: RootedBase {
435 stack: ptr::null_mut(),
436 prev: ptr::null_mut(),
437 },
438 data: initial,
439 }
440 }
441
442 pub unsafe fn add_to_root_stack(this: *mut Self, cx: *mut JSContext) {
443 let base = unsafe { &raw mut (*this).base };
444 RootedBase::add_to_root_stack(base, cx, T::KIND)
445 }
446
447 pub unsafe fn remove_from_root_stack(&mut self) {
448 self.base.remove_from_root_stack()
449 }
450}
451
452impl JS::ObjectOpResult {
453 pub fn ok(&self) -> bool {
454 assert_ne!(
455 self.code_,
456 JS::ObjectOpResult_SpecialCodes::Uninitialized as usize
457 );
458 self.code_ == JS::ObjectOpResult_SpecialCodes::OkCode as usize
459 }
460
461 pub fn succeed(&mut self) -> bool {
463 self.code_ = JS::ObjectOpResult_SpecialCodes::OkCode as usize;
464 true
465 }
466
467 pub fn fail(&mut self, code: JSErrNum) -> bool {
468 assert_ne!(
469 code as usize,
470 JS::ObjectOpResult_SpecialCodes::OkCode as usize
471 );
472 self.code_ = code as usize;
473 true
474 }
475
476 pub fn fail_cant_redefine_prop(&mut self) -> bool {
477 self.fail(JSErrNum::JSMSG_CANT_REDEFINE_PROP)
478 }
479
480 pub fn fail_read_only(&mut self) -> bool {
481 self.fail(JSErrNum::JSMSG_READ_ONLY)
482 }
483
484 pub fn fail_getter_only(&mut self) -> bool {
485 self.fail(JSErrNum::JSMSG_GETTER_ONLY)
486 }
487
488 pub fn fail_cant_delete(&mut self) -> bool {
489 self.fail(JSErrNum::JSMSG_CANT_DELETE)
490 }
491
492 pub fn fail_cant_set_interposed(&mut self) -> bool {
493 self.fail(JSErrNum::JSMSG_CANT_SET_INTERPOSED)
494 }
495
496 pub fn fail_cant_define_window_element(&mut self) -> bool {
497 self.fail(JSErrNum::JSMSG_CANT_DEFINE_WINDOW_ELEMENT)
498 }
499
500 pub fn fail_cant_delete_window_element(&mut self) -> bool {
501 self.fail(JSErrNum::JSMSG_CANT_DELETE_WINDOW_ELEMENT)
502 }
503
504 pub fn fail_cant_define_window_named_property(&mut self) -> bool {
505 self.fail(JSErrNum::JSMSG_CANT_DEFINE_WINDOW_NAMED_PROPERTY)
506 }
507
508 pub fn fail_cant_delete_window_named_property(&mut self) -> bool {
509 self.fail(JSErrNum::JSMSG_CANT_DELETE_WINDOW_NAMED_PROPERTY)
510 }
511
512 pub fn fail_cant_define_window_non_configurable(&mut self) -> bool {
513 self.fail(JSErrNum::JSMSG_CANT_DEFINE_WINDOW_NC)
514 }
515
516 pub fn fail_cant_prevent_extensions(&mut self) -> bool {
517 self.fail(JSErrNum::JSMSG_CANT_PREVENT_EXTENSIONS)
518 }
519
520 pub fn fail_cant_set_proto(&mut self) -> bool {
521 self.fail(JSErrNum::JSMSG_CANT_SET_PROTO)
522 }
523
524 pub fn fail_no_named_setter(&mut self) -> bool {
525 self.fail(JSErrNum::JSMSG_NO_NAMED_SETTER)
526 }
527
528 pub fn fail_no_indexed_setter(&mut self) -> bool {
529 self.fail(JSErrNum::JSMSG_NO_INDEXED_SETTER)
530 }
531
532 pub fn fail_not_data_descriptor(&mut self) -> bool {
533 self.fail(JSErrNum::JSMSG_NOT_DATA_DESCRIPTOR)
534 }
535
536 pub fn fail_invalid_descriptor(&mut self) -> bool {
537 self.fail(JSErrNum::JSMSG_INVALID_DESCRIPTOR)
538 }
539
540 pub fn fail_bad_array_length(&mut self) -> bool {
541 self.fail(JSErrNum::JSMSG_BAD_ARRAY_LENGTH)
542 }
543
544 pub fn fail_bad_index(&mut self) -> bool {
545 self.fail(JSErrNum::JSMSG_BAD_INDEX)
546 }
547
548 pub fn failure_code(&self) -> u32 {
549 assert!(!self.ok());
550 self.code_ as u32
551 }
552
553 #[deprecated]
554 #[allow(non_snake_case)]
555 pub fn failNoNamedSetter(&mut self) -> bool {
556 self.fail_no_named_setter()
557 }
558}
559
560impl Default for JS::ObjectOpResult {
561 fn default() -> JS::ObjectOpResult {
562 JS::ObjectOpResult {
563 code_: JS::ObjectOpResult_SpecialCodes::Uninitialized as usize,
564 }
565 }
566}
567
568impl JS::ForOfIterator {
569 pub unsafe fn init(
570 &mut self,
571 iterable: JS::HandleValue,
572 non_iterable_behavior: JS::ForOfIterator_NonIterableBehavior,
573 ) -> bool {
574 JS_ForOfIteratorInit(self, iterable, non_iterable_behavior)
575 }
576
577 pub unsafe fn next(&mut self, val: JS::MutableHandleValue, done: *mut bool) -> bool {
578 JS_ForOfIteratorNext(self, val, done)
579 }
580}
581
582impl<T> mozilla::Range<T> {
583 pub fn new(start: &mut T, end: &mut T) -> mozilla::Range<T> {
584 mozilla::Range {
585 mStart: mozilla::RangedPtr {
586 mPtr: start,
587 #[cfg(feature = "debugmozjs")]
588 mRangeStart: start,
589 #[cfg(feature = "debugmozjs")]
590 mRangeEnd: end,
591 _phantom_0: PhantomData,
592 },
593 mEnd: mozilla::RangedPtr {
594 mPtr: end,
595 #[cfg(feature = "debugmozjs")]
596 mRangeStart: start,
597 #[cfg(feature = "debugmozjs")]
598 mRangeEnd: end,
599 _phantom_0: PhantomData,
600 },
601 _phantom_0: PhantomData,
602 }
603 }
604}
605
606impl Type {
607 pub const fn byte_size(&self) -> Option<usize> {
611 match self {
612 Type::Int8 | Type::Uint8 | Type::Uint8Clamped => Some(1),
613 Type::Int16 | Type::Uint16 | Type::Float16 => Some(2),
614 Type::Int32 | Type::Uint32 | Type::Float32 => Some(4),
615 Type::Int64 | Type::Float64 | Type::BigInt64 | Type::BigUint64 => Some(8),
616 Type::Simd128 => Some(16),
617 Type::MaxTypedArrayViewType => None,
618 }
619 }
620}