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