0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2025-01-21 05:02:11 -05:00

Add v8::Eternal<T> (#1669)

Eternal handles are set-once handles that live for the lifetime of the isolate.

https://v8.github.io/api/head/classv8_1_1Eternal.html
This commit is contained in:
Divy Srivastava 2024-12-30 19:14:33 -08:00 committed by GitHub
parent 6b12ea15d0
commit d72f9d3e6f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 124 additions and 0 deletions

View file

@ -441,6 +441,28 @@ const v8::Data* v8__TracedReference__Get(v8::TracedReference<v8::Data>* self,
return local_to_ptr(self->Get(isolate));
}
void v8__Eternal__CONSTRUCT(uninit_t<v8::Eternal<v8::Data>>* buf) {
construct_in_place<v8::Eternal<v8::Data>>(buf);
}
void v8__Eternal__DESTRUCT(v8::Eternal<v8::Data>* self) { self->~Eternal(); }
void v8__Eternal__Clear(v8::Eternal<v8::Data>* self) { self->Clear(); }
bool v8__Eternal__IsEmpty(v8::Eternal<v8::Data>* self) {
return self->IsEmpty();
}
void v8__Eternal__Set(v8::Eternal<v8::Data>* self, v8::Isolate* isolate,
const v8::Data* value) {
self->Set(isolate, ptr_to_local(value));
}
const v8::Data* v8__Eternal__Get(v8::Eternal<v8::Data>* self,
v8::Isolate* isolate) {
return local_to_ptr(self->Get(isolate));
}
v8::Isolate* v8__WeakCallbackInfo__GetIsolate(
const v8::WeakCallbackInfo<void>* self) {
return self->GetIsolate();

View file

@ -18,6 +18,8 @@ static size_t cppgc__WeakMember_SIZE = sizeof(cppgc::WeakMember<RustObj>);
static size_t v8__TracedReference_SIZE = sizeof(v8::TracedReference<v8::Data>);
static size_t v8__Eternal_SIZE = sizeof(v8::Eternal<v8::Data>);
static size_t v8__String__ValueView_SIZE = sizeof(v8::String::ValueView);
static int v8__String__kMaxLength = v8::String::kMaxLength;

View file

@ -47,6 +47,20 @@ extern "C" {
this: *const TracedReference<Data>,
isolate: *mut Isolate,
) -> *const Data;
fn v8__Eternal__CONSTRUCT(this: *mut Eternal<Data>);
fn v8__Eternal__DESTRUCT(this: *mut Eternal<Data>);
fn v8__Eternal__Clear(this: *mut Eternal<Data>);
fn v8__Eternal__Get(
this: *const Eternal<Data>,
isolate: *mut Isolate,
) -> *const Data;
fn v8__Eternal__Set(
this: *mut Eternal<Data>,
isolate: *mut Isolate,
data: *mut Data,
);
fn v8__Eternal__IsEmpty(this: *const Eternal<Data>) -> bool;
}
/// An object reference managed by the v8 garbage collector.
@ -1100,3 +1114,61 @@ impl<T> Drop for TracedReference<T> {
}
}
}
/// Eternal handles are set-once handles that live for the lifetime of the isolate.
#[repr(C)]
pub struct Eternal<T> {
data: [u8; crate::binding::v8__Eternal_SIZE],
_phantom: PhantomData<T>,
}
impl<T> Eternal<T> {
pub fn empty() -> Self {
let mut this = std::mem::MaybeUninit::uninit();
unsafe {
v8__Eternal__CONSTRUCT(this.as_mut_ptr() as _);
this.assume_init()
}
}
pub fn clear(&self) {
unsafe {
v8__Eternal__Clear(self as *const Self as *mut Eternal<Data>);
}
}
pub fn set(&self, scope: &mut HandleScope<()>, data: Local<T>) {
unsafe {
v8__Eternal__Set(
self as *const Self as *mut Eternal<Data>,
scope.get_isolate_ptr(),
data.as_non_null().as_ptr().cast(),
);
}
}
pub fn get<'s>(&self, scope: &mut HandleScope<'s, ()>) -> Local<'s, T> {
unsafe {
scope
.cast_local(|sd| {
v8__Eternal__Get(
self as *const Self as *const Eternal<Data>,
sd.get_isolate_ptr(),
) as *const T
})
.unwrap()
}
}
pub fn is_empty(&self) -> bool {
unsafe { v8__Eternal__IsEmpty(self as *const Self as *const Eternal<Data>) }
}
}
impl<T> Drop for Eternal<T> {
fn drop(&mut self) {
unsafe {
v8__Eternal__DESTRUCT(self as *mut Self as *mut Eternal<Data>);
}
}
}

View file

@ -96,6 +96,7 @@ pub use external_references::ExternalReferences;
pub use function::*;
pub use gc::*;
pub use get_property_names_args_builder::*;
pub use handle::Eternal;
pub use handle::Global;
pub use handle::Handle;
pub use handle::Local;

View file

@ -11977,3 +11977,30 @@ fn use_counter_callback() {
assert_eq!(COUNT.load(Ordering::Relaxed), 1);
}
#[test]
fn test_eternals() {
let _setup_guard = setup::parallel_test();
let eternal1 = v8::Eternal::empty();
{
let mut isolate = v8::Isolate::new(Default::default());
let mut scope = v8::HandleScope::new(&mut isolate);
let str1 = v8::String::new(&mut scope, "hello").unwrap();
assert!(eternal1.is_empty());
eternal1.set(&mut scope, str1);
assert!(!eternal1.is_empty());
let str1_get = eternal1.get(&mut scope);
assert_eq!(str1, str1_get);
eternal1.clear();
assert!(eternal1.is_empty());
}
// Try all 'standalone' methods after isolate has dropped.
assert!(eternal1.is_empty());
eternal1.clear();
}