diff --git a/BUILD.gn b/BUILD.gn index 9f75b344..4ebaf9b2 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -13,6 +13,7 @@ v8_static_library("rusty_v8") { "src/platform/mod.cc", "src/platform/task.cc", "src/string_buffer.cc", + "src/value.cc", ] deps = [ ":v8", diff --git a/src/handle_scope.cc b/src/handle_scope.cc index fb00754d..8de90448 100644 --- a/src/handle_scope.cc +++ b/src/handle_scope.cc @@ -18,4 +18,8 @@ void v8__HandleScope__CONSTRUCT(uninit_t& buf, Isolate* isolate) { void v8__HandleScope__DESTRUCT(HandleScope& self) { self.~HandleScope(); } -} \ No newline at end of file + +Isolate* v8__HandleScope__GetIsolate(const HandleScope& self) { + return self.GetIsolate(); +} +} diff --git a/src/handle_scope.rs b/src/handle_scope.rs index 0bfba32c..b153d7c6 100644 --- a/src/handle_scope.rs +++ b/src/handle_scope.rs @@ -1,63 +1,40 @@ -use std::mem::drop; +use std::marker::PhantomData; use std::mem::MaybeUninit; use crate::isolate::CxxIsolate; use crate::isolate::LockedIsolate; -use crate::support::Scope; extern "C" { fn v8__HandleScope__CONSTRUCT( - buf: &mut MaybeUninit, + buf: &mut MaybeUninit, isolate: &mut CxxIsolate, ); - fn v8__HandleScope__DESTRUCT(this: &mut CxxHandleScope); + fn v8__HandleScope__DESTRUCT(this: &mut HandleScope); + fn v8__HandleScope__GetIsolate<'sc>( + this: &'sc HandleScope, + ) -> &'sc mut CxxIsolate; } #[repr(C)] -pub struct CxxHandleScope([usize; 3]); +pub struct HandleScope<'sc>([usize; 3], PhantomData<&'sc mut ()>); -pub struct HandleScope<'a, P> { - parent: &'a mut P, - cxx_handle_scope: MaybeUninit, -} - -impl<'a, 'b, P> LockedIsolate for Scope<'a, HandleScope<'b, P>> -where - P: LockedIsolate, -{ - fn cxx_isolate(&mut self) -> &mut CxxIsolate { - self.0.parent.cxx_isolate() - } -} - -impl<'a, P> HandleScope<'a, P> -where - P: LockedIsolate, -{ - pub fn new(parent: &'a mut P) -> Self { - Self { - parent, - cxx_handle_scope: MaybeUninit::uninit(), - } - } - - pub fn enter(&mut self, mut f: impl FnMut(&mut Scope) -> ()) { - unsafe { - v8__HandleScope__CONSTRUCT( - &mut self.cxx_handle_scope, - self.parent.cxx_isolate(), - ) - }; - - let mut scope = Scope::new(self); +impl<'sc> HandleScope<'sc> { + pub fn enter

(parent: &mut P, mut f: impl FnMut(&mut HandleScope<'_>) -> ()) + where + P: LockedIsolate, + { + let mut scope: MaybeUninit = MaybeUninit::uninit(); + unsafe { v8__HandleScope__CONSTRUCT(&mut scope, parent.cxx_isolate()) }; + let mut scope = unsafe { &mut *(&mut scope as *mut _ as *mut HandleScope) }; f(&mut scope); - drop(scope); - unsafe { - v8__HandleScope__DESTRUCT( - &mut *(&mut self.cxx_handle_scope as *mut _ as *mut CxxHandleScope), - ) - }; + unsafe { v8__HandleScope__DESTRUCT(&mut scope) }; + } +} + +impl<'sc> LockedIsolate for HandleScope<'sc> { + fn cxx_isolate(&mut self) -> &mut CxxIsolate { + unsafe { v8__HandleScope__GetIsolate(self) } } } @@ -66,17 +43,29 @@ mod tests { use super::*; use crate::array_buffer::Allocator; use crate::isolate::*; + use crate::Integer; use crate::Locker; + use crate::Number; #[test] + #[allow(clippy::float_cmp)] fn test_handle_scope() { let g = crate::test_util::setup(); let mut params = CreateParams::new(); params.set_array_buffer_allocator(Allocator::new_default_allocator()); - let isolate = Isolate::new(params); - let mut locker = Locker::new(&isolate); - HandleScope::new(&mut locker).enter(|scope| { - HandleScope::new(scope).enter(|_scope| {}); + let mut isolate = Isolate::new(params); + let mut locker = Locker::new(&mut isolate); + HandleScope::enter(&mut locker, |scope| { + let l1 = Integer::new(scope, -123); + let l2 = Integer::new_from_unsigned(scope, 456); + HandleScope::enter(scope, |scope2| { + let l3 = Number::new(scope2, 78.9); + assert_eq!(l1.value(), -123); + assert_eq!(l2.value(), 456); + assert_eq!(l3.value(), 78.9); + assert_eq!(Number::value(&l1), -123f64); + assert_eq!(Number::value(&l2), 456f64); + }); }); drop(g); } diff --git a/src/isolate.cc b/src/isolate.cc index d9255c9c..530427b3 100644 --- a/src/isolate.cc +++ b/src/isolate.cc @@ -34,4 +34,4 @@ void v8__Isolate__CreateParams__SET__array_buffer_allocator( delete self.array_buffer_allocator; self.array_buffer_allocator = value; } -} \ No newline at end of file +} diff --git a/src/isolate.rs b/src/isolate.rs index 66a714ec..3ccee1bf 100644 --- a/src/isolate.rs +++ b/src/isolate.rs @@ -1,4 +1,5 @@ use std::ops::Deref; +use std::ops::DerefMut; use crate::array_buffer::Allocator; use crate::support::Delete; @@ -43,11 +44,17 @@ impl Drop for Isolate { impl Deref for Isolate { type Target = CxxIsolate; - fn deref(&self) -> &CxxIsolate { + fn deref(&self) -> &Self::Target { self.0 } } +impl DerefMut for Isolate { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + #[repr(C)] pub struct CreateParams(Opaque); diff --git a/src/lib.rs b/src/lib.rs index 5b6f6bcb..17746e2e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,7 @@ pub mod array_buffer; pub mod handle_scope; pub mod inspector; pub mod isolate; +pub mod local; pub mod locker; pub mod platform; pub mod string_buffer; @@ -25,8 +26,12 @@ mod test_util; // C++ namespace "v8::V8". #[allow(non_snake_case)] pub mod V8; +pub mod value; +pub use handle_scope::HandleScope; pub use isolate::Isolate; +pub use local::Local; pub use locker::Locker; pub use string_buffer::StringBuffer; pub use string_view::StringView; +pub use value::{Integer, Number}; diff --git a/src/local.rs b/src/local.rs new file mode 100644 index 00000000..3356248e --- /dev/null +++ b/src/local.rs @@ -0,0 +1,20 @@ +use std::ops::Deref; + +pub struct Local<'sc, T>(&'sc T); + +impl<'sc, T> Local<'sc, T> { + pub unsafe fn from_raw(ptr: *const T) -> Option { + if ptr.is_null() { + None + } else { + Some(Self(&*ptr)) + } + } +} + +impl<'sc, T> Deref for Local<'sc, T> { + type Target = T; + fn deref(&self) -> &T { + &self.0 + } +} diff --git a/src/locker.cc b/src/locker.cc index 20b70c65..7ba9d1f3 100644 --- a/src/locker.cc +++ b/src/locker.cc @@ -12,4 +12,4 @@ void v8__Locker__CONSTRUCT(uninit_t& buf, Isolate* isolate) { void v8__Locker__DESTRUCT(Locker& self) { self.~Locker(); } -} \ No newline at end of file +} diff --git a/src/locker.rs b/src/locker.rs index eb1eb6ba..8e7914b7 100644 --- a/src/locker.rs +++ b/src/locker.rs @@ -14,7 +14,10 @@ use crate::isolate::LockedIsolate; // } extern "C" { - fn v8__Locker__CONSTRUCT(buf: &mut MaybeUninit, isolate: &CxxIsolate); + fn v8__Locker__CONSTRUCT( + buf: &mut MaybeUninit, + isolate: &mut CxxIsolate, + ); fn v8__Locker__DESTRUCT(this: &mut Locker); } @@ -27,7 +30,7 @@ pub struct Locker<'a> { } impl<'a> Locker<'a> { - pub fn new(isolate: &CxxIsolate) -> Self { + pub fn new(isolate: &mut CxxIsolate) -> Self { let mut buf = MaybeUninit::::uninit(); unsafe { v8__Locker__CONSTRUCT(&mut buf, isolate); diff --git a/src/string_buffer.cc b/src/string_buffer.cc index 03b1f56e..8a5a5b4b 100644 --- a/src/string_buffer.cc +++ b/src/string_buffer.cc @@ -15,4 +15,4 @@ const StringView* v8_inspector__StringBuffer__string(StringBuffer& self) { StringBuffer* v8_inspector__StringBuffer__create(const StringView& source) { return StringBuffer::create(source).release(); } -} \ No newline at end of file +} diff --git a/src/support.rs b/src/support.rs index ab7ff96c..4b15513e 100644 --- a/src/support.rs +++ b/src/support.rs @@ -178,24 +178,3 @@ impl FieldOffset { .unwrap() } } - -pub struct Scope<'a, T>(pub(crate) &'a mut T); - -impl<'a, T> Scope<'a, T> { - pub(crate) fn new(inner: &'a mut T) -> Self { - Self(inner) - } -} - -impl<'a, T> Deref for Scope<'a, T> { - type Target = T; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl<'a, T> DerefMut for Scope<'a, T> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} diff --git a/src/value.cc b/src/value.cc new file mode 100644 index 00000000..7e2c1482 --- /dev/null +++ b/src/value.cc @@ -0,0 +1,27 @@ +#include + +#include "v8/include/v8.h" + +using namespace v8; + +extern "C" { +Number* v8__Number__New(Isolate* isolate, double value) { + return *Number::New(isolate, value); +} + +double v8__Number__Value(const Number& self) { + return self.Value(); +} + +Integer* v8__Integer__New(Isolate* isolate, int32_t value) { + return *Integer::New(isolate, value); +} + +Integer* v8__Integer__NewFromUnsigned(Isolate* isolate, uint32_t value) { + return *Integer::NewFromUnsigned(isolate, value); +} + +int64_t v8__Integer__Value(const Integer& self) { + return self.Value(); +} +} diff --git a/src/value.rs b/src/value.rs new file mode 100644 index 00000000..d2413dc5 --- /dev/null +++ b/src/value.rs @@ -0,0 +1,73 @@ +use std::ops::Deref; + +use crate::isolate::CxxIsolate; +use crate::isolate::LockedIsolate; +use crate::support::Opaque; +use crate::HandleScope; +use crate::Local; + +extern "C" { + fn v8__Number__New(isolate: &mut CxxIsolate, value: f64) -> *const Number; + fn v8__Number__Value(this: &Number) -> f64; + fn v8__Integer__New(isolate: &mut CxxIsolate, value: i32) -> *const Integer; + fn v8__Integer__NewFromUnsigned( + isolate: &mut CxxIsolate, + value: u32, + ) -> *const Integer; + fn v8__Integer__Value(this: &Integer) -> i64; +} + +#[repr(C)] +pub struct Number(Opaque); + +impl Number { + pub fn new<'sc>( + scope: &mut HandleScope<'sc>, + value: f64, + ) -> Local<'sc, Number> { + unsafe { + let local = v8__Number__New(scope.cxx_isolate(), value); + Local::from_raw(local).unwrap() + } + } + + pub fn value(&self) -> f64 { + unsafe { v8__Number__Value(self) } + } +} + +#[repr(C)] +pub struct Integer(Opaque); + +impl Integer { + pub fn new<'sc>( + scope: &mut HandleScope<'sc>, + value: i32, + ) -> Local<'sc, Integer> { + unsafe { + let local = v8__Integer__New(scope.cxx_isolate(), value); + Local::from_raw(local).unwrap() + } + } + + pub fn new_from_unsigned<'sc>( + scope: &mut HandleScope<'sc>, + value: u32, + ) -> Local<'sc, Integer> { + unsafe { + let local = v8__Integer__NewFromUnsigned(scope.cxx_isolate(), value); + Local::from_raw(local).unwrap() + } + } + + pub fn value(&self) -> i64 { + unsafe { v8__Integer__Value(self) } + } +} + +impl Deref for Integer { + type Target = Number; + fn deref(&self) -> &Self::Target { + unsafe { &*(self as *const _ as *const Number) } + } +}