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