diff --git a/src/binding.cc b/src/binding.cc index ede648d4..9cef8e1c 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -473,6 +473,11 @@ const v8::Object* v8__Value__ToObject(const v8::Value& self, return maybe_local_to_ptr(self.ToObject(ptr_to_local(&context))); } +const v8::Boolean* v8__Value__ToBoolean(const v8::Value& self, + v8::Isolate* isolate) { + return local_to_ptr(self.ToBoolean(isolate)); +} + void v8__Value__NumberValue(const v8::Value& self, const v8::Context& context, v8::Maybe* out) { *out = self.NumberValue(ptr_to_local(&context)); @@ -493,6 +498,10 @@ void v8__Value__Int32Value(const v8::Value& self, const v8::Context& context, *out = self.Int32Value(ptr_to_local(&context)); } +bool v8__Value__BooleanValue(const v8::Value& self, v8::Isolate* isolate) { + return self.BooleanValue(isolate); +} + const v8::Primitive* v8__Null(v8::Isolate* isolate) { return local_to_ptr(v8::Null(isolate)); } diff --git a/src/value.rs b/src/value.rs index 321be98b..bc9dba20 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1,9 +1,11 @@ use crate::support::Maybe; use crate::BigInt; +use crate::Boolean; use crate::Context; use crate::HandleScope; use crate::Int32; use crate::Integer; +use crate::Isolate; use crate::Local; use crate::Number; use crate::Object; @@ -102,6 +104,10 @@ extern "C" { this: *const Value, context: *const Context, ) -> *const Int32; + fn v8__Value__ToBoolean( + this: *const Value, + isolate: *mut Isolate, + ) -> *const Boolean; fn v8__Value__NumberValue( this: *const Value, @@ -123,6 +129,8 @@ extern "C" { context: *const Context, out: *mut Maybe, ); + fn v8__Value__BooleanValue(this: *const Value, isolate: *mut Isolate) + -> bool; } impl Value { @@ -500,6 +508,17 @@ impl Value { } } + /// Perform the equivalent of Boolean(value) in JS. This can never fail. + pub fn to_boolean<'s>( + &self, + scope: &mut HandleScope<'s, ()>, + ) -> Local<'s, Boolean> { + unsafe { + scope.cast_local(|sd| v8__Value__ToBoolean(self, sd.get_isolate_ptr())) + } + .unwrap() + } + pub fn number_value<'s>(&self, scope: &mut HandleScope<'s>) -> Option { let mut out = Maybe::::default(); unsafe { @@ -531,4 +550,8 @@ impl Value { }; out.into() } + + pub fn boolean_value<'s>(&self, scope: &mut HandleScope<'s, ()>) -> bool { + unsafe { v8__Value__BooleanValue(self, scope.get_isolate_ptr()) } + } } diff --git a/tests/test_api.rs b/tests/test_api.rs index 0df76c66..601a4c33 100644 --- a/tests/test_api.rs +++ b/tests/test_api.rs @@ -2070,6 +2070,8 @@ fn value_checker() { assert!(value != v8::undefined(scope)); assert!(value != v8::Boolean::new(scope, false)); assert!(value != v8::Integer::new(scope, 0)); + assert!(value.to_boolean(scope) == v8::Boolean::new(scope, false)); + assert!(!value.boolean_value(scope)); let value = eval(scope, "true").unwrap(); assert!(value.is_boolean()); @@ -2083,6 +2085,7 @@ fn value_checker() { assert!(v8::Global::new(scope, value) == eval(scope, "!false").unwrap()); assert!(v8::Global::new(scope, value) != eval(scope, "1").unwrap()); assert!(value != v8::Boolean::new(scope, false)); + assert!(value.boolean_value(scope)); let value = eval(scope, "false").unwrap(); assert!(value.is_boolean()); @@ -2099,6 +2102,7 @@ fn value_checker() { assert!(value != v8::null(scope)); assert!(value != v8::undefined(scope)); assert!(value != v8::Integer::new(scope, 0)); + assert!(!value.boolean_value(scope)); let value = eval(scope, "'name'").unwrap(); assert!(value.is_name()); @@ -2108,6 +2112,8 @@ fn value_checker() { assert!(value == v8::String::new(scope, "name").unwrap()); assert!(value != v8::String::new(scope, "name\0").unwrap()); assert!(value != v8::Object::new(scope)); + assert!(value.to_boolean(scope) == v8::Boolean::new(scope, true)); + assert!(value.boolean_value(scope)); let value = eval(scope, "Symbol()").unwrap(); assert!(value.is_name());