mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-12-23 15:50:11 -05:00
Add binding for v8__internal__GetIsolateFromHeapObject() (#348)
This commit is contained in:
parent
2b08fd1651
commit
675d585977
4 changed files with 120 additions and 0 deletions
7
BUILD.gn
7
BUILD.gn
|
@ -24,6 +24,13 @@ config("rusty_v8_config") {
|
|||
configs = [ "//v8:external_config" ]
|
||||
cflags = []
|
||||
|
||||
# We need these directories in the search path to be able to include some
|
||||
# internal V8 headers.
|
||||
include_dirs = [
|
||||
"v8",
|
||||
"$target_gen_dir/v8",
|
||||
]
|
||||
|
||||
if (is_debug) {
|
||||
defines = [ "DEBUG" ]
|
||||
}
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
#include "v8/include/v8-platform.h"
|
||||
#include "v8/include/v8-profiler.h"
|
||||
#include "v8/include/v8.h"
|
||||
#include "v8/src/execution/isolate-utils-inl.h"
|
||||
#include "v8/src/execution/isolate-utils.h"
|
||||
#include "v8/src/objects/maybe-object.h"
|
||||
|
||||
using namespace support;
|
||||
|
||||
|
@ -1652,4 +1655,28 @@ void v8__HeapProfiler__TakeHeapSnapshot(v8::Isolate* isolate,
|
|||
const_cast<v8::HeapSnapshot*>(snapshot)->Delete();
|
||||
}
|
||||
|
||||
// This is necessary for v8__internal__GetIsolateFromHeapObject() to be
|
||||
// reliable enough for our purposes.
|
||||
#if !(defined V8_SHARED_RO_HEAP or defined V8_COMPRESS_POINTERS)
|
||||
#error V8 must be built with either the 'v8_enable_pointer_compression' or \
|
||||
'v8_enable_shared_ro_heap' feature enabled.
|
||||
#endif
|
||||
|
||||
v8::Isolate* v8__internal__GetIsolateFromHeapObject(const v8::Data* location) {
|
||||
if (location == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
auto address = *reinterpret_cast<const v8::internal::Address*>(location);
|
||||
auto maybe_object = v8::internal::MaybeObject(address);
|
||||
if (maybe_object.IsSmi() || maybe_object.IsCleared()) {
|
||||
return nullptr;
|
||||
}
|
||||
auto heap_object = maybe_object.GetHeapObject();
|
||||
v8::internal::Isolate* isolate;
|
||||
if (!v8::internal::GetIsolateFromHeapObject(heap_object, &isolate)) {
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<v8::Isolate*>(isolate);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
|
|
@ -99,6 +99,7 @@ impl Error for TryFromTypeError {}
|
|||
#[repr(C)]
|
||||
pub struct Context(Opaque);
|
||||
|
||||
impl_deref! { Data for Context }
|
||||
impl_eq! { for Context }
|
||||
impl_partial_eq! { Context for Context use identity }
|
||||
|
||||
|
@ -107,6 +108,7 @@ impl_partial_eq! { Context for Context use identity }
|
|||
pub struct Data(Opaque);
|
||||
|
||||
impl_from! { AccessorSignature for Data }
|
||||
impl_from! { Context for Data }
|
||||
impl_from! { Module for Data }
|
||||
impl_from! { Private for Data }
|
||||
impl_from! { Signature for Data }
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
extern crate lazy_static;
|
||||
|
||||
use std::convert::{Into, TryFrom, TryInto};
|
||||
use std::ptr::NonNull;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::Mutex;
|
||||
|
||||
|
@ -287,6 +288,89 @@ fn microtasks() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_isolate_from_handle() {
|
||||
extern "C" {
|
||||
fn v8__internal__GetIsolateFromHeapObject(
|
||||
handle: *const v8::Data,
|
||||
) -> *mut v8::Isolate;
|
||||
}
|
||||
|
||||
fn check_handle_helper(
|
||||
isolate_ptr: NonNull<v8::Isolate>,
|
||||
expect_some: Option<bool>,
|
||||
local: v8::Local<v8::Data>,
|
||||
) {
|
||||
let maybe_ptr = unsafe { v8__internal__GetIsolateFromHeapObject(&*local) };
|
||||
let maybe_ptr = NonNull::new(maybe_ptr);
|
||||
if let Some(ptr) = maybe_ptr {
|
||||
assert_eq!(ptr, isolate_ptr);
|
||||
}
|
||||
if let Some(expected_some) = expect_some {
|
||||
assert_eq!(maybe_ptr.is_some(), expected_some);
|
||||
}
|
||||
};
|
||||
|
||||
fn check_handle<'s, S, F, D>(scope: &mut S, expect_some: Option<bool>, f: F)
|
||||
where
|
||||
S: v8::ToLocal<'s>,
|
||||
F: Fn(&mut S) -> D,
|
||||
D: Into<v8::Local<'s, v8::Data>>,
|
||||
{
|
||||
let isolate_ptr = NonNull::from(scope.isolate());
|
||||
let local = f(scope).into();
|
||||
|
||||
// Check that we can get the isolate from a Local.
|
||||
check_handle_helper(isolate_ptr, expect_some, local);
|
||||
|
||||
// Check that we can still get it after converting it to a Global and back.
|
||||
let global = v8::Global::new_from(scope, local);
|
||||
let local = global.get(scope).unwrap();
|
||||
check_handle_helper(isolate_ptr, expect_some, local);
|
||||
};
|
||||
|
||||
fn check_eval<'s, S>(scope: &mut S, expect_some: Option<bool>, code: &str)
|
||||
where
|
||||
S: v8::ToLocal<'s>,
|
||||
{
|
||||
let context = scope.get_current_context().unwrap();
|
||||
check_handle(scope, expect_some, |scope| {
|
||||
eval(scope, context, code).unwrap()
|
||||
});
|
||||
}
|
||||
|
||||
let _setup_guard = setup();
|
||||
let mut params = v8::Isolate::create_params();
|
||||
params.set_array_buffer_allocator(v8::new_default_allocator());
|
||||
let mut isolate = v8::Isolate::new(params);
|
||||
|
||||
let mut hs = v8::HandleScope::new(&mut isolate);
|
||||
let scope = hs.enter();
|
||||
let context = v8::Context::new(scope);
|
||||
let mut cs = v8::ContextScope::new(scope, context);
|
||||
let s = cs.enter();
|
||||
|
||||
check_handle(s, None, |s| v8::null(s));
|
||||
check_handle(s, None, |s| v8::undefined(s));
|
||||
check_handle(s, None, |s| v8::Boolean::new(s, true));
|
||||
check_handle(s, None, |s| v8::Boolean::new(s, false));
|
||||
check_handle(s, None, |s| v8::String::new(s, "").unwrap());
|
||||
check_eval(s, None, "''");
|
||||
check_handle(s, Some(true), |s| v8::String::new(s, "Words").unwrap());
|
||||
check_eval(s, Some(true), "'Hello'");
|
||||
check_eval(s, Some(true), "Symbol()");
|
||||
check_handle(s, Some(true), |s| v8::Object::new(s));
|
||||
check_eval(s, Some(true), "this");
|
||||
check_handle(s, Some(true), |s| s.get_current_context().unwrap());
|
||||
check_eval(s, Some(true), "({ foo: 'bar' })");
|
||||
check_eval(s, Some(true), "() => {}");
|
||||
check_handle(s, Some(true), |s| v8::Number::new(s, 4.2f64));
|
||||
check_handle(s, Some(true), |s| v8::Number::new(s, -0f64));
|
||||
check_handle(s, Some(false), |s| v8::Integer::new(s, 0));
|
||||
check_eval(s, Some(true), "3.3");
|
||||
check_eval(s, Some(false), "3.3 / 3.3");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_buffer() {
|
||||
let _setup_guard = setup();
|
||||
|
|
Loading…
Reference in a new issue