/rust/git/checkouts/mozjs-fa11ffc7d4f1cc2d/d90edd1/mozjs-sys/src/jsval.rs
Line | Count | Source (jump to first uncovered line) |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
3 | | * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | | |
5 | | #![allow(non_camel_case_types)] |
6 | | #![allow(non_snake_case)] |
7 | | |
8 | | use crate::jsapi::JSContext; |
9 | | use crate::jsapi::JSObject; |
10 | | use crate::jsapi::JSString; |
11 | | use crate::jsapi::JSValueType; |
12 | | use crate::jsapi::JS::BigInt; |
13 | | use crate::jsapi::JS::Symbol; |
14 | | use crate::jsapi::JS::TraceKind; |
15 | | use crate::jsapi::JS::Value; |
16 | | |
17 | | use libc::c_void; |
18 | | use std::default::Default; |
19 | | use std::mem; |
20 | | |
21 | | pub type JSVal = Value; |
22 | | |
23 | | #[cfg(target_pointer_width = "64")] |
24 | | const JSVAL_TAG_SHIFT: usize = 47; |
25 | | |
26 | | #[cfg(target_pointer_width = "64")] |
27 | | const JSVAL_TAG_MAX_DOUBLE: u32 = 0x1FFF0u32; |
28 | | |
29 | | #[cfg(target_pointer_width = "32")] |
30 | | const JSVAL_TAG_CLEAR: u32 = 0xFFFFFF80; |
31 | | |
32 | | #[cfg(target_pointer_width = "64")] |
33 | | #[repr(u32)] |
34 | | #[allow(dead_code)] |
35 | | enum 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)] |
50 | | enum 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)] |
66 | | enum 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 | | |
79 | | const JSVAL_PAYLOAD_MASK: u64 = 0x00007FFFFFFFFFFF; |
80 | | |
81 | | #[inline(always)] |
82 | 118k | fn AsJSVal(val: u64) -> JSVal { |
83 | 118k | JSVal { asBits_: val } |
84 | 118k | } |
85 | | |
86 | | #[cfg(target_pointer_width = "64")] |
87 | | #[inline(always)] |
88 | 118k | fn BuildJSVal(tag: ValueTag, payload: u64) -> JSVal { |
89 | 118k | AsJSVal(((tag as u32 as u64) << JSVAL_TAG_SHIFT) | payload) |
90 | 118k | } |
91 | | |
92 | | #[cfg(target_pointer_width = "32")] |
93 | | #[inline(always)] |
94 | | fn BuildJSVal(tag: ValueTag, payload: u64) -> JSVal { |
95 | | AsJSVal(((tag as u32 as u64) << 32) | payload) |
96 | | } |
97 | | |
98 | | #[inline(always)] |
99 | 0 | pub fn NullValue() -> JSVal { |
100 | 0 | BuildJSVal(ValueTag::NULL, 0) |
101 | 0 | } |
102 | | |
103 | | #[inline(always)] |
104 | 105k | pub fn UndefinedValue() -> JSVal { |
105 | 105k | BuildJSVal(ValueTag::UNDEFINED, 0) |
106 | 105k | } |
107 | | |
108 | | #[inline(always)] |
109 | 0 | pub fn Int32Value(i: i32) -> JSVal { |
110 | 0 | BuildJSVal(ValueTag::INT32, i as u32 as u64) |
111 | 0 | } |
112 | | |
113 | | #[cfg(target_pointer_width = "64")] |
114 | | #[inline(always)] |
115 | 0 | pub fn DoubleValue(f: f64) -> JSVal { |
116 | 0 | let bits: u64 = unsafe { mem::transmute(f) }; |
117 | 0 | assert!(bits <= ValueShiftedTag::MAX_DOUBLE as u64); |
118 | 0 | AsJSVal(bits) |
119 | 0 | } |
120 | | |
121 | | #[cfg(target_pointer_width = "32")] |
122 | | #[inline(always)] |
123 | | pub 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)] |
131 | 0 | pub fn UInt32Value(ui: u32) -> JSVal { |
132 | 0 | if ui > 0x7fffffff { |
133 | 0 | DoubleValue(ui as f64) |
134 | | } else { |
135 | 0 | Int32Value(ui as i32) |
136 | | } |
137 | 0 | } |
138 | | |
139 | | #[cfg(target_pointer_width = "64")] |
140 | | #[inline(always)] |
141 | 13.1k | pub fn StringValue(s: &JSString) -> JSVal { |
142 | 13.1k | let bits = s as *const JSString as usize as u64; |
143 | 13.1k | assert!((bits >> JSVAL_TAG_SHIFT) == 0); |
144 | 13.1k | BuildJSVal(ValueTag::STRING, bits) |
145 | 13.1k | } |
146 | | |
147 | | #[cfg(target_pointer_width = "32")] |
148 | | #[inline(always)] |
149 | | pub 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)] |
155 | 0 | pub fn BooleanValue(b: bool) -> JSVal { |
156 | 0 | BuildJSVal(ValueTag::BOOLEAN, b as u64) |
157 | 0 | } |
158 | | |
159 | | #[cfg(target_pointer_width = "64")] |
160 | | #[inline(always)] |
161 | 0 | pub fn ObjectValue(o: *mut JSObject) -> JSVal { |
162 | 0 | let bits = o as usize as u64; |
163 | 0 | assert!((bits >> JSVAL_TAG_SHIFT) == 0); |
164 | 0 | BuildJSVal(ValueTag::OBJECT, bits) |
165 | 0 | } |
166 | | |
167 | | #[cfg(target_pointer_width = "32")] |
168 | | #[inline(always)] |
169 | | pub fn ObjectValue(o: *mut JSObject) -> JSVal { |
170 | | let bits = o as usize as u64; |
171 | | BuildJSVal(ValueTag::OBJECT, bits) |
172 | | } |
173 | | |
174 | | #[inline(always)] |
175 | 0 | pub fn ObjectOrNullValue(o: *mut JSObject) -> JSVal { |
176 | 0 | if o.is_null() { |
177 | 0 | NullValue() |
178 | | } else { |
179 | 0 | ObjectValue(o) |
180 | | } |
181 | 0 | } |
182 | | |
183 | | #[cfg(target_pointer_width = "64")] |
184 | | #[inline(always)] |
185 | 0 | pub fn SymbolValue(s: &Symbol) -> JSVal { |
186 | 0 | let bits = s as *const Symbol as usize as u64; |
187 | 0 | assert!((bits >> JSVAL_TAG_SHIFT) == 0); |
188 | 0 | BuildJSVal(ValueTag::SYMBOL, bits) |
189 | 0 | } |
190 | | |
191 | | #[cfg(target_pointer_width = "32")] |
192 | | #[inline(always)] |
193 | | pub 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)] |
200 | 0 | pub fn BigIntValue(s: &BigInt) -> JSVal { |
201 | 0 | let bits = s as *const BigInt as usize as u64; |
202 | 0 | assert!((bits >> JSVAL_TAG_SHIFT) == 0); |
203 | 0 | BuildJSVal(ValueTag::BIGINT, bits) |
204 | 0 | } |
205 | | |
206 | | #[cfg(target_pointer_width = "32")] |
207 | | #[inline(always)] |
208 | | pub 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)] |
214 | 0 | pub fn PrivateValue(o: *const c_void) -> JSVal { |
215 | 0 | let ptrBits = o as usize as u64; |
216 | 0 | #[cfg(target_pointer_width = "64")] |
217 | 0 | assert_eq!(ptrBits & 0xFFFF000000000000, 0); |
218 | 0 | AsJSVal(ptrBits) |
219 | 0 | } |
220 | | |
221 | | impl JSVal { |
222 | | #[inline(always)] |
223 | 26.3k | fn asBits(&self) -> u64 { |
224 | 26.3k | self.asBits_ |
225 | 26.3k | } |
226 | | |
227 | | #[inline(always)] |
228 | | #[cfg(target_pointer_width = "64")] |
229 | 0 | pub fn is_undefined(&self) -> bool { |
230 | 0 | self.asBits() == ValueShiftedTag::UNDEFINED as u64 |
231 | 0 | } |
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 | 0 | pub fn is_null(&self) -> bool { |
242 | 0 | self.asBits() == ValueShiftedTag::NULL as u64 |
243 | 0 | } |
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 | 0 | pub fn is_null_or_undefined(&self) -> bool { |
253 | 0 | self.is_null() || self.is_undefined() |
254 | 0 | } |
255 | | |
256 | | #[inline(always)] |
257 | | #[cfg(target_pointer_width = "64")] |
258 | 0 | pub fn is_boolean(&self) -> bool { |
259 | 0 | (self.asBits() >> JSVAL_TAG_SHIFT) == ValueTag::BOOLEAN as u64 |
260 | 0 | } |
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 | 0 | pub fn is_int32(&self) -> bool { |
271 | 0 | (self.asBits() >> JSVAL_TAG_SHIFT) == ValueTag::INT32 as u64 |
272 | 0 | } |
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 | 0 | pub fn is_double(&self) -> bool { |
283 | 0 | self.asBits() <= ValueShiftedTag::MAX_DOUBLE as u64 |
284 | 0 | } |
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 | 0 | pub fn is_number(&self) -> bool { |
295 | | const JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET: u64 = ValueShiftedTag::BOOLEAN as u64; |
296 | 0 | self.asBits() < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET |
297 | 0 | } |
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 | 0 | pub fn is_primitive(&self) -> bool { |
309 | | const JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET: u64 = ValueShiftedTag::OBJECT as u64; |
310 | 0 | self.asBits() < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET |
311 | 0 | } |
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 | 13.1k | pub fn is_string(&self) -> bool { |
323 | 13.1k | (self.asBits() >> JSVAL_TAG_SHIFT) == ValueTag::STRING as u64 |
324 | 13.1k | } |
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 | 0 | pub fn is_object(&self) -> bool { |
335 | 0 | assert!((self.asBits() >> JSVAL_TAG_SHIFT) <= ValueTag::OBJECT as u64); |
336 | 0 | self.asBits() >= ValueShiftedTag::OBJECT as u64 |
337 | 0 | } |
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 | 0 | 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 | 0 | assert!((self.asBits() >> JSVAL_TAG_SHIFT) <= ValueTag::OBJECT as u64); |
350 | 0 | self.asBits() >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET |
351 | 0 | } |
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 | 0 | pub fn is_magic(&self) -> bool { |
364 | 0 | (self.asBits() >> JSVAL_TAG_SHIFT) == ValueTag::MAGIC as u64 |
365 | 0 | } |
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 | 0 | pub fn is_symbol(&self) -> bool { |
376 | 0 | (self.asBits() >> JSVAL_TAG_SHIFT) == ValueTag::SYMBOL as u64 |
377 | 0 | } |
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 | 0 | pub fn is_bigint(&self) -> bool { |
388 | 0 | (self.asBits() >> JSVAL_TAG_SHIFT) == ValueTag::BIGINT as u64 |
389 | 0 | } |
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 | 0 | pub fn is_gcthing(&self) -> bool { |
400 | | const JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET: u64 = ValueShiftedTag::STRING as u64; |
401 | 0 | self.asBits() >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET |
402 | 0 | } |
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 | 0 | pub fn to_boolean(&self) -> bool { |
414 | 0 | assert!(self.is_boolean()); |
415 | 0 | (self.asBits() & JSVAL_PAYLOAD_MASK) != 0 |
416 | 0 | } |
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 | 0 | pub fn to_int32(&self) -> i32 { |
426 | 0 | assert!(self.is_int32()); |
427 | 0 | (self.asBits() & 0x00000000FFFFFFFF) as i32 |
428 | 0 | } |
429 | | |
430 | | #[inline(always)] |
431 | 0 | pub fn to_double(&self) -> f64 { |
432 | 0 | assert!(self.is_double()); |
433 | 0 | unsafe { mem::transmute(self.asBits()) } |
434 | 0 | } |
435 | | |
436 | | #[inline(always)] |
437 | 0 | pub fn to_number(&self) -> f64 { |
438 | 0 | assert!(self.is_number()); |
439 | 0 | if self.is_double() { |
440 | 0 | self.to_double() |
441 | | } else { |
442 | 0 | self.to_int32() as f64 |
443 | | } |
444 | 0 | } |
445 | | |
446 | | #[inline(always)] |
447 | | #[cfg(target_pointer_width = "64")] |
448 | 13.1k | pub fn to_string(&self) -> *mut JSString { |
449 | 13.1k | assert!(self.is_string()); |
450 | 13.1k | let ptrBits = self.asBits() & JSVAL_PAYLOAD_MASK; |
451 | 13.1k | ptrBits as usize as *mut JSString |
452 | 13.1k | } |
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 | 0 | pub fn to_object(&self) -> *mut JSObject { |
464 | 0 | assert!(self.is_object()); |
465 | 0 | self.to_object_or_null() |
466 | 0 | } |
467 | | |
468 | | #[inline(always)] |
469 | | #[cfg(target_pointer_width = "64")] |
470 | 0 | pub fn to_object_or_null(&self) -> *mut JSObject { |
471 | 0 | assert!(self.is_object_or_null()); |
472 | 0 | let ptrBits = self.asBits() & JSVAL_PAYLOAD_MASK; |
473 | 0 | assert!((ptrBits & 0x7) == 0); |
474 | 0 | ptrBits as usize as *mut JSObject |
475 | 0 | } |
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 | 0 | pub fn to_symbol(&self) -> *mut Symbol { |
487 | 0 | assert!(self.is_symbol()); |
488 | 0 | let ptrBits = self.asBits() & JSVAL_PAYLOAD_MASK; |
489 | 0 | assert!((ptrBits & 0x7) == 0); |
490 | 0 | ptrBits as usize as *mut Symbol |
491 | 0 | } |
492 | | |
493 | | #[inline(always)] |
494 | 0 | pub fn to_bigint(&self) -> *mut BigInt { |
495 | 0 | assert!(self.is_bigint()); |
496 | 0 | let ptrBits = self.asBits() & JSVAL_PAYLOAD_MASK; |
497 | 0 | assert!((ptrBits & 0x7) == 0); |
498 | 0 | ptrBits as usize as *mut BigInt |
499 | 0 | } |
500 | | |
501 | | #[inline(always)] |
502 | 0 | pub fn to_private(&self) -> *const c_void { |
503 | 0 | assert!(self.is_double()); |
504 | | #[cfg(target_pointer_width = "64")] |
505 | 0 | assert_eq!(self.asBits() & 0xFFFF000000000000, 0); |
506 | 0 | self.asBits() as usize as *const c_void |
507 | 0 | } |
508 | | |
509 | | #[inline(always)] |
510 | | #[cfg(target_pointer_width = "64")] |
511 | 0 | pub fn to_gcthing(&self) -> *mut c_void { |
512 | 0 | assert!(self.is_gcthing()); |
513 | 0 | let ptrBits = self.asBits() & JSVAL_PAYLOAD_MASK; |
514 | 0 | assert!((ptrBits & 0x7) == 0); |
515 | 0 | ptrBits as *mut c_void |
516 | 0 | } |
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 | 0 | pub fn is_markable(&self) -> bool { |
528 | 0 | self.is_gcthing() && !self.is_null() |
529 | 0 | } |
530 | | |
531 | | #[inline(always)] |
532 | 0 | pub fn trace_kind(&self) -> TraceKind { |
533 | 0 | assert!(self.is_markable()); |
534 | 0 | if self.is_object() { |
535 | 0 | TraceKind::Object |
536 | 0 | } else if self.is_string() { |
537 | 0 | TraceKind::String |
538 | 0 | } else if self.is_symbol() { |
539 | 0 | TraceKind::Symbol |
540 | | } else { |
541 | 0 | TraceKind::BigInt |
542 | | } |
543 | 0 | } |
544 | | } |
545 | | |
546 | | impl Default for JSVal { |
547 | 52.6k | fn default() -> JSVal { |
548 | 52.6k | UndefinedValue() |
549 | 52.6k | } |
550 | | } |
551 | | |
552 | | #[inline(always)] |
553 | 0 | pub unsafe fn JS_ARGV(_cx: *mut JSContext, vp: *mut JSVal) -> *mut JSVal { |
554 | 0 | vp.offset(2) |
555 | 0 | } |
556 | | |
557 | | #[inline(always)] |
558 | 0 | pub unsafe fn JS_CALLEE(_cx: *mut JSContext, vp: *mut JSVal) -> JSVal { |
559 | 0 | *vp |
560 | 0 | } |
561 | | |
562 | | // These tests make sure that the Rust definitions agree with the C++ definitions. |
563 | | #[test] |
564 | | fn test_representation_agreement() { |
565 | | // Annoyingly, we can't check JSObject, JSString, etc. without creating a runtime, |
566 | | // since the constructor has checks that fail if we try mocking. There are no-check |
567 | | // versions of the setters, but they're private. |
568 | | 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)] |
598 | | fn 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 | | } |