rusty_v8/
value.rs

1use crate::support::Maybe;
2use crate::BigInt;
3use crate::Boolean;
4use crate::Context;
5use crate::HandleScope;
6use crate::Int32;
7use crate::Integer;
8use crate::Isolate;
9use crate::Local;
10use crate::Number;
11use crate::Object;
12use crate::String;
13use crate::Uint32;
14use crate::Value;
15
16extern "C" {
17  fn v8__Value__IsUndefined(this: *const Value) -> bool;
18  fn v8__Value__IsNull(this: *const Value) -> bool;
19  fn v8__Value__IsNullOrUndefined(this: *const Value) -> bool;
20  fn v8__Value__IsTrue(this: *const Value) -> bool;
21  fn v8__Value__IsFalse(this: *const Value) -> bool;
22  fn v8__Value__IsName(this: *const Value) -> bool;
23  fn v8__Value__IsString(this: *const Value) -> bool;
24  fn v8__Value__IsSymbol(this: *const Value) -> bool;
25  fn v8__Value__IsFunction(this: *const Value) -> bool;
26  fn v8__Value__IsArray(this: *const Value) -> bool;
27  fn v8__Value__IsObject(this: *const Value) -> bool;
28  fn v8__Value__IsBigInt(this: *const Value) -> bool;
29  fn v8__Value__IsBoolean(this: *const Value) -> bool;
30  fn v8__Value__IsNumber(this: *const Value) -> bool;
31  fn v8__Value__IsExternal(this: *const Value) -> bool;
32  fn v8__Value__IsInt32(this: *const Value) -> bool;
33  fn v8__Value__IsUint32(this: *const Value) -> bool;
34  fn v8__Value__IsDate(this: *const Value) -> bool;
35  fn v8__Value__IsArgumentsObject(this: *const Value) -> bool;
36  fn v8__Value__IsBigIntObject(this: *const Value) -> bool;
37  fn v8__Value__IsBooleanObject(this: *const Value) -> bool;
38  fn v8__Value__IsNumberObject(this: *const Value) -> bool;
39  fn v8__Value__IsStringObject(this: *const Value) -> bool;
40  fn v8__Value__IsSymbolObject(this: *const Value) -> bool;
41  fn v8__Value__IsNativeError(this: *const Value) -> bool;
42  fn v8__Value__IsRegExp(this: *const Value) -> bool;
43  fn v8__Value__IsAsyncFunction(this: *const Value) -> bool;
44  fn v8__Value__IsGeneratorFunction(this: *const Value) -> bool;
45  fn v8__Value__IsGeneratorObject(this: *const Value) -> bool;
46  fn v8__Value__IsPromise(this: *const Value) -> bool;
47  fn v8__Value__IsMap(this: *const Value) -> bool;
48  fn v8__Value__IsSet(this: *const Value) -> bool;
49  fn v8__Value__IsMapIterator(this: *const Value) -> bool;
50  fn v8__Value__IsSetIterator(this: *const Value) -> bool;
51  fn v8__Value__IsWeakMap(this: *const Value) -> bool;
52  fn v8__Value__IsWeakSet(this: *const Value) -> bool;
53  fn v8__Value__IsArrayBuffer(this: *const Value) -> bool;
54  fn v8__Value__IsArrayBufferView(this: *const Value) -> bool;
55  fn v8__Value__IsTypedArray(this: *const Value) -> bool;
56  fn v8__Value__IsUint8Array(this: *const Value) -> bool;
57  fn v8__Value__IsUint8ClampedArray(this: *const Value) -> bool;
58  fn v8__Value__IsInt8Array(this: *const Value) -> bool;
59  fn v8__Value__IsUint16Array(this: *const Value) -> bool;
60  fn v8__Value__IsInt16Array(this: *const Value) -> bool;
61  fn v8__Value__IsUint32Array(this: *const Value) -> bool;
62  fn v8__Value__IsInt32Array(this: *const Value) -> bool;
63  fn v8__Value__IsFloat32Array(this: *const Value) -> bool;
64  fn v8__Value__IsFloat64Array(this: *const Value) -> bool;
65  fn v8__Value__IsBigInt64Array(this: *const Value) -> bool;
66  fn v8__Value__IsBigUint64Array(this: *const Value) -> bool;
67  fn v8__Value__IsDataView(this: *const Value) -> bool;
68  fn v8__Value__IsSharedArrayBuffer(this: *const Value) -> bool;
69  fn v8__Value__IsProxy(this: *const Value) -> bool;
70  fn v8__Value__IsWasmModuleObject(this: *const Value) -> bool;
71  fn v8__Value__IsModuleNamespaceObject(this: *const Value) -> bool;
72  fn v8__Value__StrictEquals(this: *const Value, that: *const Value) -> bool;
73  fn v8__Value__SameValue(this: *const Value, that: *const Value) -> bool;
74
75  fn v8__Value__ToBigInt(
76    this: *const Value,
77    context: *const Context,
78  ) -> *const BigInt;
79  fn v8__Value__ToNumber(
80    this: *const Value,
81    context: *const Context,
82  ) -> *const Number;
83  fn v8__Value__ToString(
84    this: *const Value,
85    context: *const Context,
86  ) -> *const String;
87  fn v8__Value__ToDetailString(
88    this: *const Value,
89    context: *const Context,
90  ) -> *const String;
91  fn v8__Value__ToObject(
92    this: *const Value,
93    context: *const Context,
94  ) -> *const Object;
95  fn v8__Value__ToInteger(
96    this: *const Value,
97    context: *const Context,
98  ) -> *const Integer;
99  fn v8__Value__ToUint32(
100    this: *const Value,
101    context: *const Context,
102  ) -> *const Uint32;
103  fn v8__Value__ToInt32(
104    this: *const Value,
105    context: *const Context,
106  ) -> *const Int32;
107  fn v8__Value__ToBoolean(
108    this: *const Value,
109    isolate: *mut Isolate,
110  ) -> *const Boolean;
111
112  fn v8__Value__NumberValue(
113    this: *const Value,
114    context: *const Context,
115    out: *mut Maybe<f64>,
116  );
117  fn v8__Value__IntegerValue(
118    this: *const Value,
119    context: *const Context,
120    out: *mut Maybe<i64>,
121  );
122  fn v8__Value__Uint32Value(
123    this: *const Value,
124    context: *const Context,
125    out: *mut Maybe<u32>,
126  );
127  fn v8__Value__Int32Value(
128    this: *const Value,
129    context: *const Context,
130    out: *mut Maybe<i32>,
131  );
132  fn v8__Value__BooleanValue(this: *const Value, isolate: *mut Isolate)
133    -> bool;
134}
135
136impl Value {
137  /// Returns true if this value is the undefined value.  See ECMA-262 4.3.10.
138  pub fn is_undefined(&self) -> bool {
139    unsafe { v8__Value__IsUndefined(self) }
140  }
141
142  /// Returns true if this value is the null value.  See ECMA-262 4.3.11.
143  pub fn is_null(&self) -> bool {
144    unsafe { v8__Value__IsNull(self) }
145  }
146
147  /// Returns true if this value is either the null or the undefined value.
148  /// See ECMA-262 4.3.11. and 4.3.12
149  pub fn is_null_or_undefined(&self) -> bool {
150    unsafe { v8__Value__IsNullOrUndefined(self) }
151  }
152
153  /// Returns true if this value is true.
154  /// This is not the same as `BooleanValue()`. The latter performs a
155  /// conversion to boolean, i.e. the result of `Boolean(value)` in JS, whereas
156  /// this checks `value === true`.
157  pub fn is_true(&self) -> bool {
158    unsafe { v8__Value__IsTrue(self) }
159  }
160
161  /// Returns true if this value is false.
162  /// This is not the same as `!BooleanValue()`. The latter performs a
163  /// conversion to boolean, i.e. the result of `!Boolean(value)` in JS, whereas
164  /// this checks `value === false`.
165  pub fn is_false(&self) -> bool {
166    unsafe { v8__Value__IsFalse(self) }
167  }
168
169  /// Returns true if this value is a symbol or a string.
170  /// This is equivalent to
171  /// `typeof value === 'string' || typeof value === 'symbol'` in JS.
172  pub fn is_name(&self) -> bool {
173    unsafe { v8__Value__IsName(self) }
174  }
175
176  /// Returns true if this value is an instance of the String type.
177  /// See ECMA-262 8.4.
178  pub fn is_string(&self) -> bool {
179    unsafe { v8__Value__IsString(self) }
180  }
181
182  /// Returns true if this value is a symbol.
183  /// This is equivalent to `typeof value === 'symbol'` in JS.
184  pub fn is_symbol(&self) -> bool {
185    unsafe { v8__Value__IsSymbol(self) }
186  }
187
188  /// Returns true if this value is a function.
189  pub fn is_function(&self) -> bool {
190    unsafe { v8__Value__IsFunction(self) }
191  }
192
193  /// Returns true if this value is an array. Note that it will return false for
194  /// an Proxy for an array.
195  pub fn is_array(&self) -> bool {
196    unsafe { v8__Value__IsArray(self) }
197  }
198
199  /// Returns true if this value is an object.
200  pub fn is_object(&self) -> bool {
201    unsafe { v8__Value__IsObject(self) }
202  }
203
204  /// Returns true if this value is a bigint.
205  /// This is equivalent to `typeof value === 'bigint'` in JS.
206  pub fn is_big_int(&self) -> bool {
207    unsafe { v8__Value__IsBigInt(self) }
208  }
209
210  /// Returns true if this value is boolean.
211  /// This is equivalent to `typeof value === 'boolean'` in JS.
212  pub fn is_boolean(&self) -> bool {
213    unsafe { v8__Value__IsBoolean(self) }
214  }
215
216  /// Returns true if this value is a number.
217  pub fn is_number(&self) -> bool {
218    unsafe { v8__Value__IsNumber(self) }
219  }
220
221  /// Returns true if this value is an `External` object.
222  pub fn is_external(&self) -> bool {
223    unsafe { v8__Value__IsExternal(self) }
224  }
225
226  /// Returns true if this value is a 32-bit signed integer.
227  pub fn is_int32(&self) -> bool {
228    unsafe { v8__Value__IsInt32(self) }
229  }
230
231  /// Returns true if this value is a 32-bit unsigned integer.
232  pub fn is_uint32(&self) -> bool {
233    unsafe { v8__Value__IsUint32(self) }
234  }
235
236  /// Returns true if this value is a Date.
237  pub fn is_date(&self) -> bool {
238    unsafe { v8__Value__IsDate(self) }
239  }
240
241  /// Returns true if this value is an Arguments object.
242  pub fn is_arguments_object(&self) -> bool {
243    unsafe { v8__Value__IsArgumentsObject(self) }
244  }
245
246  /// Returns true if this value is a BigInt object.
247  pub fn is_big_int_object(&self) -> bool {
248    unsafe { v8__Value__IsBigIntObject(self) }
249  }
250
251  /// Returns true if this value is a Boolean object.
252  pub fn is_boolean_object(&self) -> bool {
253    unsafe { v8__Value__IsBooleanObject(self) }
254  }
255
256  /// Returns true if this value is a Number object.
257  pub fn is_number_object(&self) -> bool {
258    unsafe { v8__Value__IsNumberObject(self) }
259  }
260
261  /// Returns true if this value is a String object.
262  pub fn is_string_object(&self) -> bool {
263    unsafe { v8__Value__IsStringObject(self) }
264  }
265
266  /// Returns true if this value is a Symbol object.
267  pub fn is_symbol_object(&self) -> bool {
268    unsafe { v8__Value__IsSymbolObject(self) }
269  }
270
271  /// Returns true if this value is a NativeError.
272  pub fn is_native_error(&self) -> bool {
273    unsafe { v8__Value__IsNativeError(self) }
274  }
275
276  /// Returns true if this value is a RegExp.
277  pub fn is_reg_exp(&self) -> bool {
278    unsafe { v8__Value__IsRegExp(self) }
279  }
280
281  /// Returns true if this value is an async function.
282  pub fn is_async_function(&self) -> bool {
283    unsafe { v8__Value__IsAsyncFunction(self) }
284  }
285
286  /// Returns true if this value is a Generator function.
287  pub fn is_generator_function(&self) -> bool {
288    unsafe { v8__Value__IsGeneratorFunction(self) }
289  }
290
291  /// Returns true if this value is a Promise.
292  pub fn is_promise(&self) -> bool {
293    unsafe { v8__Value__IsPromise(self) }
294  }
295
296  /// Returns true if this value is a Map.
297  pub fn is_map(&self) -> bool {
298    unsafe { v8__Value__IsMap(self) }
299  }
300
301  /// Returns true if this value is a Set.
302  pub fn is_set(&self) -> bool {
303    unsafe { v8__Value__IsSet(self) }
304  }
305
306  /// Returns true if this value is a Map Iterator.
307  pub fn is_map_iterator(&self) -> bool {
308    unsafe { v8__Value__IsMapIterator(self) }
309  }
310
311  /// Returns true if this value is a Set Iterator.
312  pub fn is_set_iterator(&self) -> bool {
313    unsafe { v8__Value__IsSetIterator(self) }
314  }
315
316  /// Returns true if this value is a WeakMap.
317  pub fn is_weak_map(&self) -> bool {
318    unsafe { v8__Value__IsWeakMap(self) }
319  }
320
321  /// Returns true if this value is a WeakSet.
322  pub fn is_weak_set(&self) -> bool {
323    unsafe { v8__Value__IsWeakSet(self) }
324  }
325
326  /// Returns true if this value is an ArrayBuffer.
327  pub fn is_array_buffer(&self) -> bool {
328    unsafe { v8__Value__IsArrayBuffer(self) }
329  }
330
331  /// Returns true if this value is an ArrayBufferView.
332  pub fn is_array_buffer_view(&self) -> bool {
333    unsafe { v8__Value__IsArrayBufferView(self) }
334  }
335
336  /// Returns true if this value is one of TypedArrays.
337  pub fn is_typed_array(&self) -> bool {
338    unsafe { v8__Value__IsTypedArray(self) }
339  }
340
341  /// Returns true if this value is an Uint8Array.
342  pub fn is_uint8_array(&self) -> bool {
343    unsafe { v8__Value__IsUint8Array(self) }
344  }
345
346  /// Returns true if this value is an Uint8ClampedArray.
347  pub fn is_uint8_clamped_array(&self) -> bool {
348    unsafe { v8__Value__IsUint8ClampedArray(self) }
349  }
350
351  /// Returns true if this value is an Int8Array.
352  pub fn is_int8_array(&self) -> bool {
353    unsafe { v8__Value__IsInt8Array(self) }
354  }
355
356  /// Returns true if this value is an Uint16Array.
357  pub fn is_uint16_array(&self) -> bool {
358    unsafe { v8__Value__IsUint16Array(self) }
359  }
360
361  /// Returns true if this value is an Int16Array.
362  pub fn is_int16_array(&self) -> bool {
363    unsafe { v8__Value__IsInt16Array(self) }
364  }
365
366  /// Returns true if this value is an Uint32Array.
367  pub fn is_uint32_array(&self) -> bool {
368    unsafe { v8__Value__IsUint32Array(self) }
369  }
370
371  /// Returns true if this value is an Int32Array.
372  pub fn is_int32_array(&self) -> bool {
373    unsafe { v8__Value__IsInt32Array(self) }
374  }
375
376  /// Returns true if this value is a Float32Array.
377  pub fn is_float32_array(&self) -> bool {
378    unsafe { v8__Value__IsFloat32Array(self) }
379  }
380
381  /// Returns true if this value is a Float64Array.
382  pub fn is_float64_array(&self) -> bool {
383    unsafe { v8__Value__IsFloat64Array(self) }
384  }
385
386  /// Returns true if this value is a BigInt64Array.
387  pub fn is_big_int64_array(&self) -> bool {
388    unsafe { v8__Value__IsBigInt64Array(self) }
389  }
390
391  /// Returns true if this value is a BigUint64Array.
392  pub fn is_big_uint64_array(&self) -> bool {
393    unsafe { v8__Value__IsBigUint64Array(self) }
394  }
395
396  /// Returns true if this value is a DataView.
397  pub fn is_data_view(&self) -> bool {
398    unsafe { v8__Value__IsDataView(self) }
399  }
400
401  /// Returns true if this value is a SharedArrayBuffer.
402  /// This is an experimental feature.
403  pub fn is_shared_array_buffer(&self) -> bool {
404    unsafe { v8__Value__IsSharedArrayBuffer(self) }
405  }
406
407  /// Returns true if this value is a JavaScript Proxy.
408  pub fn is_proxy(&self) -> bool {
409    unsafe { v8__Value__IsProxy(self) }
410  }
411
412  /// Returns true if this value is a WasmModuleObject.
413  pub fn is_wasm_module_object(&self) -> bool {
414    unsafe { v8__Value__IsWasmModuleObject(self) }
415  }
416
417  /// Returns true if the value is a Module Namespace Object.
418  pub fn is_module_namespace_object(&self) -> bool {
419    unsafe { v8__Value__IsModuleNamespaceObject(self) }
420  }
421
422  pub fn strict_equals(&self, that: Local<Value>) -> bool {
423    unsafe { v8__Value__StrictEquals(self, &*that) }
424  }
425
426  pub fn same_value(&self, that: Local<Value>) -> bool {
427    unsafe { v8__Value__SameValue(self, &*that) }
428  }
429
430  /// Implements the the abstract operation `SameValueZero`, which is defined in
431  /// ECMA-262 6th edition ยง 7.2.10
432  /// (http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero).
433  ///
434  /// This operation is used to compare values for the purpose of insertion into
435  /// a `Set`, or determining whether `Map` keys are equivalent. Its semantics
436  /// are almost the same as `strict_equals()` and `same_value()`, with the
437  /// following important distinctions:
438  ///   - It considers `NaN` equal to `NaN` (unlike `strict_equals()`).
439  ///   - It considers `-0` equal to `0` (unlike `same_value()`).
440  pub fn same_value_zero(&self, that: Local<Value>) -> bool {
441    // The SMI representation of zero is also zero. In debug builds, double
442    // check this, so in the unlikely event that V8 changes its internal
443    // representation of SMIs such that this invariant no longer holds, we'd
444    // catch it.
445    self.same_value(that) || {
446      let zero = Integer::zero().into();
447      self.strict_equals(zero) && that.strict_equals(zero)
448    }
449  }
450
451  pub fn to_big_int<'s>(
452    &self,
453    scope: &mut HandleScope<'s>,
454  ) -> Option<Local<'s, BigInt>> {
455    unsafe {
456      scope
457        .cast_local(|sd| v8__Value__ToBigInt(self, &*sd.get_current_context()))
458    }
459  }
460
461  pub fn to_number<'s>(
462    &self,
463    scope: &mut HandleScope<'s>,
464  ) -> Option<Local<'s, Number>> {
465    unsafe {
466      scope
467        .cast_local(|sd| v8__Value__ToNumber(self, &*sd.get_current_context()))
468    }
469  }
470
471  pub fn to_string<'s>(
472    &self,
473    scope: &mut HandleScope<'s>,
474  ) -> Option<Local<'s, String>> {
475    unsafe {
476      scope
477        .cast_local(|sd| v8__Value__ToString(self, &*sd.get_current_context()))
478    }
479  }
480
481  /// Convenience function not present in the original V8 API.
482  pub fn to_rust_string_lossy<'s>(
483    &self,
484    scope: &mut HandleScope<'s>,
485  ) -> std::string::String {
486    self
487      .to_string(scope)
488      .map_or_else(std::string::String::new, |s| s.to_rust_string_lossy(scope))
489  }
490
491  pub fn to_detail_string<'s>(
492    &self,
493    scope: &mut HandleScope<'s>,
494  ) -> Option<Local<'s, String>> {
495    unsafe {
496      scope.cast_local(|sd| {
497        v8__Value__ToDetailString(self, &*sd.get_current_context())
498      })
499    }
500  }
501
502  pub fn to_object<'s>(
503    &self,
504    scope: &mut HandleScope<'s>,
505  ) -> Option<Local<'s, Object>> {
506    unsafe {
507      scope
508        .cast_local(|sd| v8__Value__ToObject(self, &*sd.get_current_context()))
509    }
510  }
511
512  pub fn to_integer<'s>(
513    &self,
514    scope: &mut HandleScope<'s>,
515  ) -> Option<Local<'s, Integer>> {
516    unsafe {
517      scope
518        .cast_local(|sd| v8__Value__ToInteger(self, &*sd.get_current_context()))
519    }
520  }
521
522  pub fn to_uint32<'s>(
523    &self,
524    scope: &mut HandleScope<'s>,
525  ) -> Option<Local<'s, Uint32>> {
526    unsafe {
527      scope
528        .cast_local(|sd| v8__Value__ToUint32(self, &*sd.get_current_context()))
529    }
530  }
531
532  pub fn to_int32<'s>(
533    &self,
534    scope: &mut HandleScope<'s>,
535  ) -> Option<Local<'s, Int32>> {
536    unsafe {
537      scope
538        .cast_local(|sd| v8__Value__ToInt32(self, &*sd.get_current_context()))
539    }
540  }
541
542  /// Perform the equivalent of Boolean(value) in JS. This can never fail.
543  pub fn to_boolean<'s>(
544    &self,
545    scope: &mut HandleScope<'s, ()>,
546  ) -> Local<'s, Boolean> {
547    unsafe {
548      scope.cast_local(|sd| v8__Value__ToBoolean(self, sd.get_isolate_ptr()))
549    }
550    .unwrap()
551  }
552
553  pub fn number_value<'s>(&self, scope: &mut HandleScope<'s>) -> Option<f64> {
554    let mut out = Maybe::<f64>::default();
555    unsafe {
556      v8__Value__NumberValue(self, &*scope.get_current_context(), &mut out)
557    };
558    out.into()
559  }
560
561  pub fn integer_value<'s>(&self, scope: &mut HandleScope<'s>) -> Option<i64> {
562    let mut out = Maybe::<i64>::default();
563    unsafe {
564      v8__Value__IntegerValue(self, &*scope.get_current_context(), &mut out)
565    };
566    out.into()
567  }
568
569  pub fn uint32_value<'s>(&self, scope: &mut HandleScope<'s>) -> Option<u32> {
570    let mut out = Maybe::<u32>::default();
571    unsafe {
572      v8__Value__Uint32Value(self, &*scope.get_current_context(), &mut out)
573    };
574    out.into()
575  }
576
577  pub fn int32_value<'s>(&self, scope: &mut HandleScope<'s>) -> Option<i32> {
578    let mut out = Maybe::<i32>::default();
579    unsafe {
580      v8__Value__Int32Value(self, &*scope.get_current_context(), &mut out)
581    };
582    out.into()
583  }
584
585  pub fn boolean_value<'s>(&self, scope: &mut HandleScope<'s, ()>) -> bool {
586    unsafe { v8__Value__BooleanValue(self, scope.get_isolate_ptr()) }
587  }
588}