1#![allow(non_camel_case_types)]
6#![allow(non_snake_case)]
7
8use crate::jsapi::JSContext;
9use crate::jsapi::JSObject;
10use crate::jsapi::JSString;
11use crate::jsapi::JSValueType;
12use crate::jsapi::JS::BigInt;
13use crate::jsapi::JS::Symbol;
14use crate::jsapi::JS::TraceKind;
15use crate::jsapi::JS::Value;
16
17use libc::c_void;
18use std::default::Default;
19
20pub type JSVal = Value;
21
22#[cfg(target_pointer_width = "64")]
23const JSVAL_TAG_SHIFT: usize = 47;
24
25#[cfg(target_pointer_width = "64")]
26const JSVAL_TAG_MAX_DOUBLE: u32 = 0x1FFF0u32;
27
28#[cfg(target_pointer_width = "32")]
29const JSVAL_TAG_CLEAR: u32 = 0xFFFFFF80;
30
31#[cfg(target_pointer_width = "64")]
32#[repr(u32)]
33#[allow(dead_code)]
34enum ValueTag {
35 INT32 = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_INT32 as u32),
36 UNDEFINED = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_UNDEFINED as u32),
37 STRING = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_STRING as u32),
38 SYMBOL = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_SYMBOL as u32),
39 BIGINT = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_BIGINT as u32),
40 BOOLEAN = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_BOOLEAN as u32),
41 MAGIC = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_MAGIC as u32),
42 NULL = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_NULL as u32),
43 OBJECT = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_OBJECT as u32),
44}
45
46#[cfg(target_pointer_width = "32")]
47#[repr(u32)]
48#[allow(dead_code)]
49enum ValueTag {
50 PRIVATE = 0,
51 INT32 = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_INT32 as u32),
52 UNDEFINED = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_UNDEFINED as u32),
53 STRING = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_STRING as u32),
54 SYMBOL = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_SYMBOL as u32),
55 BIGINT = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_BIGINT as u32),
56 BOOLEAN = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_BOOLEAN as u32),
57 MAGIC = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_MAGIC as u32),
58 NULL = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_NULL as u32),
59 OBJECT = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_OBJECT as u32),
60}
61
62#[cfg(target_pointer_width = "64")]
63#[repr(u64)]
64#[allow(dead_code)]
65enum ValueShiftedTag {
66 MAX_DOUBLE = ((JSVAL_TAG_MAX_DOUBLE as u64) << JSVAL_TAG_SHIFT) | 0xFFFFFFFFu64,
67 INT32 = (ValueTag::INT32 as u64) << JSVAL_TAG_SHIFT,
68 UNDEFINED = (ValueTag::UNDEFINED as u64) << JSVAL_TAG_SHIFT,
69 STRING = (ValueTag::STRING as u64) << JSVAL_TAG_SHIFT,
70 SYMBOL = (ValueTag::SYMBOL as u64) << JSVAL_TAG_SHIFT,
71 BIGINT = (ValueTag::BIGINT as u64) << JSVAL_TAG_SHIFT,
72 BOOLEAN = (ValueTag::BOOLEAN as u64) << JSVAL_TAG_SHIFT,
73 MAGIC = (ValueTag::MAGIC as u64) << JSVAL_TAG_SHIFT,
74 NULL = (ValueTag::NULL as u64) << JSVAL_TAG_SHIFT,
75 OBJECT = (ValueTag::OBJECT as u64) << JSVAL_TAG_SHIFT,
76}
77
78const JSVAL_PAYLOAD_MASK: u64 = 0x00007FFFFFFFFFFF;
79
80#[inline(always)]
81fn AsJSVal(val: u64) -> JSVal {
82 JSVal { asBits_: val }
83}
84
85#[cfg(target_pointer_width = "64")]
86#[inline(always)]
87fn BuildJSVal(tag: ValueTag, payload: u64) -> JSVal {
88 AsJSVal(((tag as u32 as u64) << JSVAL_TAG_SHIFT) | payload)
89}
90
91#[cfg(target_pointer_width = "32")]
92#[inline(always)]
93fn BuildJSVal(tag: ValueTag, payload: u64) -> JSVal {
94 AsJSVal(((tag as u32 as u64) << 32) | payload)
95}
96
97#[inline(always)]
98pub fn NullValue() -> JSVal {
99 BuildJSVal(ValueTag::NULL, 0)
100}
101
102#[inline(always)]
103pub fn UndefinedValue() -> JSVal {
104 BuildJSVal(ValueTag::UNDEFINED, 0)
105}
106
107#[inline(always)]
108pub fn Int32Value(i: i32) -> JSVal {
109 BuildJSVal(ValueTag::INT32, i as u32 as u64)
110}
111
112#[cfg(target_pointer_width = "64")]
113#[inline(always)]
114pub fn DoubleValue(f: f64) -> JSVal {
115 let bits: u64 = f64::to_bits(f);
116 assert!(bits <= ValueShiftedTag::MAX_DOUBLE as u64);
117 AsJSVal(bits)
118}
119
120#[cfg(target_pointer_width = "32")]
121#[inline(always)]
122pub fn DoubleValue(f: f64) -> JSVal {
123 let bits: u64 = f64::to_bits(f);
124 let val = AsJSVal(bits);
125 assert!(val.is_double());
126 val
127}
128
129#[inline(always)]
130pub fn UInt32Value(ui: u32) -> JSVal {
131 if ui > 0x7fffffff {
132 DoubleValue(ui as f64)
133 } else {
134 Int32Value(ui as i32)
135 }
136}
137
138#[cfg(target_pointer_width = "64")]
139#[inline(always)]
140pub fn StringValue(s: &JSString) -> JSVal {
141 let bits = s as *const JSString as usize as u64;
142 assert!((bits >> JSVAL_TAG_SHIFT) == 0);
143 BuildJSVal(ValueTag::STRING, bits)
144}
145
146#[cfg(target_pointer_width = "32")]
147#[inline(always)]
148pub fn StringValue(s: &JSString) -> JSVal {
149 let bits = s as *const JSString as usize as u64;
150 BuildJSVal(ValueTag::STRING, bits)
151}
152
153#[inline(always)]
154pub fn BooleanValue(b: bool) -> JSVal {
155 BuildJSVal(ValueTag::BOOLEAN, b as u64)
156}
157
158#[cfg(target_pointer_width = "64")]
159#[inline(always)]
160pub fn ObjectValue(o: *mut JSObject) -> JSVal {
161 let bits = o as usize as u64;
162 assert!((bits >> JSVAL_TAG_SHIFT) == 0);
163 BuildJSVal(ValueTag::OBJECT, bits)
164}
165
166#[cfg(target_pointer_width = "32")]
167#[inline(always)]
168pub fn ObjectValue(o: *mut JSObject) -> JSVal {
169 let bits = o as usize as u64;
170 BuildJSVal(ValueTag::OBJECT, bits)
171}
172
173#[inline(always)]
174pub fn ObjectOrNullValue(o: *mut JSObject) -> JSVal {
175 if o.is_null() {
176 NullValue()
177 } else {
178 ObjectValue(o)
179 }
180}
181
182#[cfg(target_pointer_width = "64")]
183#[inline(always)]
184pub fn SymbolValue(s: &Symbol) -> JSVal {
185 let bits = s as *const Symbol as usize as u64;
186 assert!((bits >> JSVAL_TAG_SHIFT) == 0);
187 BuildJSVal(ValueTag::SYMBOL, bits)
188}
189
190#[cfg(target_pointer_width = "32")]
191#[inline(always)]
192pub fn SymbolValue(s: &Symbol) -> JSVal {
193 let bits = s as *const Symbol as usize as u64;
194 BuildJSVal(ValueTag::SYMBOL, bits)
195}
196
197#[cfg(target_pointer_width = "64")]
198#[inline(always)]
199pub fn BigIntValue(s: &BigInt) -> JSVal {
200 let bits = s as *const BigInt as usize as u64;
201 assert!((bits >> JSVAL_TAG_SHIFT) == 0);
202 BuildJSVal(ValueTag::BIGINT, bits)
203}
204
205#[cfg(target_pointer_width = "32")]
206#[inline(always)]
207pub fn BigIntValue(s: &BigInt) -> JSVal {
208 let bits = s as *const BigInt as usize as u64;
209 BuildJSVal(ValueTag::BIGINT, bits)
210}
211
212#[inline(always)]
213pub fn PrivateValue(o: *const c_void) -> JSVal {
214 let ptrBits = o as usize as u64;
215 #[cfg(target_pointer_width = "64")]
216 assert_eq!(ptrBits & 0xFFFF000000000000, 0);
217 AsJSVal(ptrBits)
218}
219
220impl JSVal {
221 #[inline(always)]
222 fn asBits(&self) -> u64 {
223 self.asBits_
224 }
225
226 #[inline(always)]
227 #[cfg(target_pointer_width = "64")]
228 pub fn is_undefined(&self) -> bool {
229 self.asBits() == ValueShiftedTag::UNDEFINED as u64
230 }
231
232 #[inline(always)]
233 #[cfg(target_pointer_width = "32")]
234 pub fn is_undefined(&self) -> bool {
235 (self.asBits() >> 32) == ValueTag::UNDEFINED as u64
236 }
237
238 #[inline(always)]
239 #[cfg(target_pointer_width = "64")]
240 pub fn is_null(&self) -> bool {
241 self.asBits() == ValueShiftedTag::NULL as u64
242 }
243
244 #[inline(always)]
245 #[cfg(target_pointer_width = "32")]
246 pub fn is_null(&self) -> bool {
247 (self.asBits() >> 32) == ValueTag::NULL as u64
248 }
249
250 #[inline(always)]
251 pub fn is_null_or_undefined(&self) -> bool {
252 self.is_null() || self.is_undefined()
253 }
254
255 #[inline(always)]
256 #[cfg(target_pointer_width = "64")]
257 pub fn is_boolean(&self) -> bool {
258 (self.asBits() >> JSVAL_TAG_SHIFT) == ValueTag::BOOLEAN as u64
259 }
260
261 #[inline(always)]
262 #[cfg(target_pointer_width = "32")]
263 pub fn is_boolean(&self) -> bool {
264 (self.asBits() >> 32) == ValueTag::BOOLEAN as u64
265 }
266
267 #[inline(always)]
268 #[cfg(target_pointer_width = "64")]
269 pub fn is_int32(&self) -> bool {
270 (self.asBits() >> JSVAL_TAG_SHIFT) == ValueTag::INT32 as u64
271 }
272
273 #[inline(always)]
274 #[cfg(target_pointer_width = "32")]
275 pub fn is_int32(&self) -> bool {
276 (self.asBits() >> 32) == ValueTag::INT32 as u64
277 }
278
279 #[inline(always)]
280 #[cfg(target_pointer_width = "64")]
281 pub fn is_double(&self) -> bool {
282 self.asBits() <= ValueShiftedTag::MAX_DOUBLE as u64
283 }
284
285 #[inline(always)]
286 #[cfg(target_pointer_width = "32")]
287 pub fn is_double(&self) -> bool {
288 (self.asBits() >> 32) <= JSVAL_TAG_CLEAR as u64
289 }
290
291 #[inline(always)]
292 #[cfg(target_pointer_width = "64")]
293 pub fn is_number(&self) -> bool {
294 const JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET: u64 = ValueShiftedTag::BOOLEAN as u64;
295 self.asBits() < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET
296 }
297
298 #[inline(always)]
299 #[cfg(target_pointer_width = "32")]
300 pub fn is_number(&self) -> bool {
301 const JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET: u64 = ValueTag::INT32 as u64;
302 (self.asBits() >> 32) <= JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET
303 }
304
305 #[inline(always)]
306 #[cfg(target_pointer_width = "64")]
307 pub fn is_primitive(&self) -> bool {
308 const JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET: u64 = ValueShiftedTag::OBJECT as u64;
309 self.asBits() < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET
310 }
311
312 #[inline(always)]
313 #[cfg(target_pointer_width = "32")]
314 pub fn is_primitive(&self) -> bool {
315 const JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET: u64 = ValueTag::OBJECT as u64;
316 (self.asBits() >> 32) < JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET
317 }
318
319 #[inline(always)]
320 #[cfg(target_pointer_width = "64")]
321 pub fn is_string(&self) -> bool {
322 (self.asBits() >> JSVAL_TAG_SHIFT) == ValueTag::STRING as u64
323 }
324
325 #[inline(always)]
326 #[cfg(target_pointer_width = "32")]
327 pub fn is_string(&self) -> bool {
328 (self.asBits() >> 32) == ValueTag::STRING as u64
329 }
330
331 #[inline(always)]
332 #[cfg(target_pointer_width = "64")]
333 pub fn is_object(&self) -> bool {
334 assert!((self.asBits() >> JSVAL_TAG_SHIFT) <= ValueTag::OBJECT as u64);
335 self.asBits() >= ValueShiftedTag::OBJECT as u64
336 }
337
338 #[inline(always)]
339 #[cfg(target_pointer_width = "32")]
340 pub fn is_object(&self) -> bool {
341 (self.asBits() >> 32) == ValueTag::OBJECT as u64
342 }
343
344 #[inline(always)]
345 #[cfg(target_pointer_width = "64")]
346 pub fn is_object_or_null(&self) -> bool {
347 const JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET: u64 = ValueShiftedTag::NULL as u64;
348 assert!((self.asBits() >> JSVAL_TAG_SHIFT) <= ValueTag::OBJECT as u64);
349 self.asBits() >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET
350 }
351
352 #[inline(always)]
353 #[cfg(target_pointer_width = "32")]
354 pub fn is_object_or_null(&self) -> bool {
355 const JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET: u64 = ValueTag::NULL as u64;
356 assert!((self.asBits() >> 32) <= ValueTag::OBJECT as u64);
357 (self.asBits() >> 32) >= JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET
358 }
359
360 #[inline(always)]
361 #[cfg(target_pointer_width = "64")]
362 pub fn is_magic(&self) -> bool {
363 (self.asBits() >> JSVAL_TAG_SHIFT) == ValueTag::MAGIC as u64
364 }
365
366 #[inline(always)]
367 #[cfg(target_pointer_width = "32")]
368 pub fn is_magic(&self) -> bool {
369 (self.asBits() >> 32) == ValueTag::MAGIC as u64
370 }
371
372 #[inline(always)]
373 #[cfg(target_pointer_width = "64")]
374 pub fn is_symbol(&self) -> bool {
375 (self.asBits() >> JSVAL_TAG_SHIFT) == ValueTag::SYMBOL as u64
376 }
377
378 #[inline(always)]
379 #[cfg(target_pointer_width = "32")]
380 pub fn is_symbol(&self) -> bool {
381 (self.asBits() >> 32) == ValueTag::SYMBOL as u64
382 }
383
384 #[inline(always)]
385 #[cfg(target_pointer_width = "64")]
386 pub fn is_bigint(&self) -> bool {
387 (self.asBits() >> JSVAL_TAG_SHIFT) == ValueTag::BIGINT as u64
388 }
389
390 #[inline(always)]
391 #[cfg(target_pointer_width = "32")]
392 pub fn is_bigint(&self) -> bool {
393 (self.asBits() >> 32) == ValueTag::BIGINT as u64
394 }
395
396 #[inline(always)]
397 #[cfg(target_pointer_width = "64")]
398 pub fn is_gcthing(&self) -> bool {
399 const JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET: u64 = ValueShiftedTag::STRING as u64;
400 self.asBits() >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET
401 }
402
403 #[inline(always)]
404 #[cfg(target_pointer_width = "32")]
405 pub fn is_gcthing(&self) -> bool {
406 const JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET: u64 = ValueTag::STRING as u64;
407 (self.asBits() >> 32) >= JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET
408 }
409
410 #[inline(always)]
411 #[cfg(target_pointer_width = "64")]
412 pub fn to_boolean(&self) -> bool {
413 assert!(self.is_boolean());
414 (self.asBits() & JSVAL_PAYLOAD_MASK) != 0
415 }
416
417 #[inline(always)]
418 #[cfg(target_pointer_width = "32")]
419 pub fn to_boolean(&self) -> bool {
420 (self.asBits() & 0x00000000FFFFFFFF) != 0
421 }
422
423 #[inline(always)]
424 pub fn to_int32(&self) -> i32 {
425 assert!(self.is_int32());
426 (self.asBits() & 0x00000000FFFFFFFF) as i32
427 }
428
429 #[inline(always)]
430 pub fn to_double(&self) -> f64 {
431 assert!(self.is_double());
432 f64::from_bits(self.asBits())
433 }
434
435 #[inline(always)]
436 pub fn to_number(&self) -> f64 {
437 assert!(self.is_number());
438 if self.is_double() {
439 self.to_double()
440 } else {
441 self.to_int32() as f64
442 }
443 }
444
445 #[inline(always)]
446 #[cfg(target_pointer_width = "64")]
447 pub fn to_string(&self) -> *mut JSString {
448 assert!(self.is_string());
449 let ptrBits = self.asBits() & JSVAL_PAYLOAD_MASK;
450 ptrBits as usize as *mut JSString
451 }
452
453 #[inline(always)]
454 #[cfg(target_pointer_width = "32")]
455 pub fn to_string(&self) -> *mut JSString {
456 assert!(self.is_string());
457 let ptrBits: u32 = (self.asBits() & 0x00000000FFFFFFFF) as u32;
458 ptrBits as *mut JSString
459 }
460
461 #[inline(always)]
462 pub fn to_object(&self) -> *mut JSObject {
463 assert!(self.is_object());
464 self.to_object_or_null()
465 }
466
467 #[inline(always)]
468 #[cfg(target_pointer_width = "64")]
469 pub fn to_object_or_null(&self) -> *mut JSObject {
470 assert!(self.is_object_or_null());
471 let ptrBits = self.asBits() & JSVAL_PAYLOAD_MASK;
472 assert!((ptrBits & 0x7) == 0);
473 ptrBits as usize as *mut JSObject
474 }
475
476 #[inline(always)]
477 #[cfg(target_pointer_width = "32")]
478 pub fn to_object_or_null(&self) -> *mut JSObject {
479 assert!(self.is_object_or_null());
480 let ptrBits: u32 = (self.asBits() & 0x00000000FFFFFFFF) as u32;
481 ptrBits as *mut JSObject
482 }
483
484 #[inline(always)]
485 pub fn to_symbol(&self) -> *mut Symbol {
486 assert!(self.is_symbol());
487 let ptrBits = self.asBits() & JSVAL_PAYLOAD_MASK;
488 assert!((ptrBits & 0x7) == 0);
489 ptrBits as usize as *mut Symbol
490 }
491
492 #[inline(always)]
493 pub fn to_bigint(&self) -> *mut BigInt {
494 assert!(self.is_bigint());
495 let ptrBits = self.asBits() & JSVAL_PAYLOAD_MASK;
496 assert!((ptrBits & 0x7) == 0);
497 ptrBits as usize as *mut BigInt
498 }
499
500 #[inline(always)]
501 pub fn to_private(&self) -> *const c_void {
502 assert!(self.is_double());
503 #[cfg(target_pointer_width = "64")]
504 assert_eq!(self.asBits() & 0xFFFF000000000000, 0);
505 self.asBits() as usize as *const c_void
506 }
507
508 #[inline(always)]
509 #[cfg(target_pointer_width = "64")]
510 pub fn to_gcthing(&self) -> *mut c_void {
511 assert!(self.is_gcthing());
512 let ptrBits = self.asBits() & JSVAL_PAYLOAD_MASK;
513 assert!((ptrBits & 0x7) == 0);
514 ptrBits as *mut c_void
515 }
516
517 #[inline(always)]
518 #[cfg(target_pointer_width = "32")]
519 pub fn to_gcthing(&self) -> *mut c_void {
520 assert!(self.is_gcthing());
521 let ptrBits: u32 = (self.asBits() & 0x00000000FFFFFFFF) as u32;
522 ptrBits as *mut c_void
523 }
524
525 #[inline(always)]
526 pub fn is_markable(&self) -> bool {
527 self.is_gcthing() && !self.is_null()
528 }
529
530 #[inline(always)]
531 pub fn trace_kind(&self) -> TraceKind {
532 assert!(self.is_markable());
533 if self.is_object() {
534 TraceKind::Object
535 } else if self.is_string() {
536 TraceKind::String
537 } else if self.is_symbol() {
538 TraceKind::Symbol
539 } else {
540 TraceKind::BigInt
541 }
542 }
543}
544
545impl Default for JSVal {
546 fn default() -> JSVal {
547 UndefinedValue()
548 }
549}
550
551#[inline(always)]
552pub unsafe fn JS_ARGV(_cx: *mut JSContext, vp: *mut JSVal) -> *mut JSVal {
553 vp.offset(2)
554}
555
556#[inline(always)]
557pub unsafe fn JS_CALLEE(_cx: *mut JSContext, vp: *mut JSVal) -> JSVal {
558 *vp
559}
560
561#[test]
563fn test_representation_agreement() {
564 use crate::jsapi::glue::*;
568 let mut val1 = UndefinedValue();
569 let mut val2;
570
571 unsafe {
572 JS_ValueSetBoolean(&mut val1, true);
573 }
574 val2 = BooleanValue(true);
575 assert_agreement(val1, val2);
576
577 unsafe {
578 JS_ValueSetDouble(&mut val1, 3.14159);
579 }
580 val2 = DoubleValue(3.14159);
581 assert_agreement(val1, val2);
582
583 unsafe {
584 JS_ValueSetInt32(&mut val1, 37);
585 }
586 val2 = Int32Value(37);
587 assert_agreement(val1, val2);
588
589 unsafe {
590 JS_ValueSetNull(&mut val1);
591 }
592 val2 = NullValue();
593 assert_agreement(val1, val2);
594}
595
596#[cfg(test)]
597fn assert_agreement(val1: JSVal, val2: JSVal) {
598 use crate::jsapi::glue::*;
599
600 assert_eq!(val1.asBits(), val2.asBits());
601
602 assert_eq!(unsafe { JS_ValueIsBoolean(&val1) }, val2.is_boolean());
603 if val2.is_boolean() {
604 assert_eq!(unsafe { JS_ValueToBoolean(&val1) }, val2.to_boolean());
605 }
606
607 assert_eq!(unsafe { JS_ValueIsDouble(&val1) }, val2.is_double());
608 if val2.is_double() {
609 assert_eq!(unsafe { JS_ValueToDouble(&val1) }, val2.to_double());
610 }
611
612 assert_eq!(unsafe { JS_ValueIsInt32(&val1) }, val2.is_int32());
613 if val2.is_int32() {
614 assert_eq!(unsafe { JS_ValueToInt32(&val1) }, val2.to_int32());
615 }
616
617 assert_eq!(unsafe { JS_ValueIsNumber(&val1) }, val2.is_number());
618 if val2.is_number() {
619 assert_eq!(unsafe { JS_ValueToNumber(&val1) }, val2.to_number());
620 }
621
622 assert_eq!(unsafe { JS_ValueIsNull(&val1) }, val2.is_null());
623
624 assert_eq!(unsafe { JS_ValueIsUndefined(&val1) }, val2.is_undefined());
625}