ion/
value.rs

1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 */
6
7use std::ops::{Deref, DerefMut};
8
9use mozjs::jsapi::{JS_ValueToSource, NullHandleValue, SameValue, UndefinedHandleValue};
10use mozjs::jsval::{
11	BigIntValue, BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, ObjectValue, SymbolValue, UInt32Value,
12	UndefinedValue,
13};
14
15use crate::bigint::BigInt;
16use crate::conversions::ToValue as _;
17use crate::{Array, Context, Local, Object, Symbol};
18
19/// Represents a JavaScript Value in the runtime.
20/// It can represent either a primitive or an object.
21#[derive(Debug)]
22pub struct Value<'v> {
23	val: Local<'v, JSVal>,
24}
25
26impl<'v> Value<'v> {
27	/// Creates a [Value] from a boolean.
28	pub fn bool(cx: &Context, b: bool) -> Value<'_> {
29		Value::from(cx.root(BooleanValue(b)))
30	}
31
32	/// Creates a [Value] from a 32-bit signed integer.
33	pub fn i32(cx: &Context, i: i32) -> Value<'_> {
34		Value::from(cx.root(Int32Value(i)))
35	}
36
37	/// Creates a [Value] from a 32-bit unsigned integer.
38	pub fn u32(cx: &Context, u: u32) -> Value<'_> {
39		Value::from(cx.root(UInt32Value(u)))
40	}
41
42	/// Creates a [Value] from a 64-bit float.
43	pub fn f64(cx: &Context, f: f64) -> Value<'_> {
44		Value::from(cx.root(DoubleValue(f)))
45	}
46
47	/// Creates a [Value] from a string.
48	pub fn string(cx: &'v Context, str: &str) -> Value<'v> {
49		str.as_value(cx)
50	}
51
52	/// Creates a [Value] from a [BigInt].
53	pub fn bigint<'cx>(cx: &'cx Context, bi: &BigInt) -> Value<'cx> {
54		Value::from(cx.root(BigIntValue(unsafe { &*bi.get() })))
55	}
56
57	/// Creates a [Value] from a [Symbol].
58	pub fn symbol<'cx>(cx: &'cx Context, sym: &Symbol) -> Value<'cx> {
59		Value::from(cx.root(SymbolValue(unsafe { &*sym.get() })))
60	}
61
62	/// Creates a [Value] from an [Object].
63	pub fn object<'cx>(cx: &'cx Context, object: &Object) -> Value<'cx> {
64		Value::from(cx.root(ObjectValue(object.handle().get())))
65	}
66
67	/// Creates a [Value] from an [Array].
68	pub fn array<'cx>(cx: &'cx Context, array: &Array) -> Value<'cx> {
69		Value::from(cx.root(ObjectValue(array.handle().get())))
70	}
71
72	/// Creates an `undefined` [Value].
73	pub fn undefined(cx: &Context) -> Value<'_> {
74		Value::from(cx.root(UndefinedValue()))
75	}
76
77	/// Creates a `null` [Value].
78	pub fn null(cx: &Context) -> Value<'_> {
79		Value::from(cx.root(NullValue()))
80	}
81
82	pub fn undefined_handle() -> Value<'v> {
83		Value::from(unsafe { Local::from_raw_handle(UndefinedHandleValue) })
84	}
85
86	pub fn null_handle() -> Value<'v> {
87		Value::from(unsafe { Local::from_raw_handle(NullHandleValue) })
88	}
89
90	/// Converts a [Value] to an [Object].
91	///
92	/// ### Panics
93	/// This panics if the [Value] is not an object.
94	pub fn to_object<'cx>(&self, cx: &'cx Context) -> Object<'cx> {
95		cx.root(self.handle().to_object()).into()
96	}
97
98	/// Compares two values for equality using the [SameValue algorithm](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-samevalue).
99	/// This is identical to strict equality (===), except that NaN's are equal and 0 !== -0.
100	pub fn is_same(&self, cx: &Context, other: &Value) -> bool {
101		let mut same = false;
102		unsafe { SameValue(cx.as_ptr(), self.handle().into(), other.handle().into(), &raw mut same) && same }
103	}
104
105	pub fn to_source<'cx>(&self, cx: &'cx Context) -> crate::String<'cx> {
106		crate::String::from(cx.root(unsafe { JS_ValueToSource(cx.as_ptr(), self.handle().into()) }))
107	}
108}
109
110impl<'v> From<Local<'v, JSVal>> for Value<'v> {
111	fn from(val: Local<'v, JSVal>) -> Value<'v> {
112		Value { val }
113	}
114}
115
116impl<'v> Deref for Value<'v> {
117	type Target = Local<'v, JSVal>;
118
119	fn deref(&self) -> &Self::Target {
120		&self.val
121	}
122}
123
124impl DerefMut for Value<'_> {
125	fn deref_mut(&mut self) -> &mut Self::Target {
126		&mut self.val
127	}
128}