mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-11-21 15:04:33 -05:00
Make EscapableHandleScope::escape() inheritable, tighten lifetimes (#227)
This commit is contained in:
parent
6efb395fdc
commit
36a12142f2
14 changed files with 320 additions and 213 deletions
|
@ -107,7 +107,6 @@ pub struct FunctionCallbackInfo {
|
|||
}
|
||||
|
||||
unsafe impl<'s> ScopeDefinition<'s> for FunctionCallbackInfo {
|
||||
type Parent = ();
|
||||
type Args = ();
|
||||
unsafe fn enter_scope(_: *mut Self, _: Self::Args) {}
|
||||
}
|
||||
|
@ -122,7 +121,6 @@ pub struct PropertyCallbackInfo {
|
|||
}
|
||||
|
||||
unsafe impl<'s> ScopeDefinition<'s> for PropertyCallbackInfo {
|
||||
type Parent = ();
|
||||
type Args = ();
|
||||
unsafe fn enter_scope(_: *mut Self, _: Self::Args) {}
|
||||
}
|
||||
|
@ -235,7 +233,7 @@ where
|
|||
fn mapping() -> Self {
|
||||
let f = |info: *const FunctionCallbackInfo| {
|
||||
let scope: FunctionCallbackScope =
|
||||
&mut crate::scope::Entered::new(info as *mut FunctionCallbackInfo);
|
||||
&mut crate::scope::Entered::new_root(info as *mut FunctionCallbackInfo);
|
||||
let args = FunctionCallbackArguments::from_function_callback_info(info);
|
||||
let rv = ReturnValue::from_function_callback_info(info);
|
||||
(F::get())(scope, args, rv);
|
||||
|
@ -262,7 +260,7 @@ where
|
|||
fn mapping() -> Self {
|
||||
let f = |key: Local<Name>, info: *const PropertyCallbackInfo| {
|
||||
let scope: PropertyCallbackScope =
|
||||
&mut crate::scope::Entered::new(info as *mut PropertyCallbackInfo);
|
||||
&mut crate::scope::Entered::new_root(info as *mut PropertyCallbackInfo);
|
||||
let args = PropertyCallbackArguments::from_property_callback_info(info);
|
||||
let rv = ReturnValue::from_property_callback_info(info);
|
||||
(F::get())(scope, key, args, rv);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// Copyright 2019-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use crate::isolate::Isolate;
|
||||
use crate::scope::Scope;
|
||||
use crate::scope::ScopeDefinition;
|
||||
|
@ -11,15 +9,15 @@ use crate::Local;
|
|||
use crate::Value;
|
||||
|
||||
extern "C" {
|
||||
fn v8__HandleScope__CONSTRUCT(buf: *mut CxxHandleScope, isolate: &Isolate);
|
||||
fn v8__HandleScope__DESTRUCT(this: &mut CxxHandleScope);
|
||||
fn v8__HandleScope__CONSTRUCT(buf: *mut HandleScope, isolate: *mut Isolate);
|
||||
fn v8__HandleScope__DESTRUCT(this: &mut HandleScope);
|
||||
fn v8__EscapableHandleScope__CONSTRUCT(
|
||||
buf: *mut CxxEscapableHandleScope,
|
||||
isolate: &Isolate,
|
||||
buf: *mut EscapableHandleScope,
|
||||
isolate: *mut Isolate,
|
||||
);
|
||||
fn v8__EscapableHandleScope__DESTRUCT(this: &mut CxxEscapableHandleScope);
|
||||
fn v8__EscapableHandleScope__DESTRUCT(this: &mut EscapableHandleScope);
|
||||
fn v8__EscapableHandleScope__Escape(
|
||||
this: &mut CxxEscapableHandleScope,
|
||||
this: &mut EscapableHandleScope,
|
||||
value: *mut Value,
|
||||
) -> *mut Value;
|
||||
}
|
||||
|
@ -36,84 +34,69 @@ extern "C" {
|
|||
/// garbage collector will no longer track the object stored in the
|
||||
/// handle and may deallocate it. The behavior of accessing a handle
|
||||
/// for which the handle scope has been deleted is undefined.
|
||||
pub struct HandleScope<P>(CxxHandleScope, PhantomData<P>);
|
||||
|
||||
#[repr(C)]
|
||||
pub(crate) struct CxxHandleScope([usize; 3]);
|
||||
pub struct HandleScope([usize; 3]);
|
||||
|
||||
impl<'s, P> HandleScope<P>
|
||||
where
|
||||
P: InIsolate,
|
||||
{
|
||||
pub fn new(parent: &'s mut P) -> Scope<'s, Self> {
|
||||
Scope::new(parent.isolate())
|
||||
impl<'s> HandleScope {
|
||||
pub fn new<P>(parent: &'s mut P) -> Scope<'s, Self, P>
|
||||
where
|
||||
P: InIsolate,
|
||||
{
|
||||
let isolate: *mut Isolate = parent.isolate();
|
||||
Scope::new(isolate, parent)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, P> HandleScope<P> {
|
||||
pub(crate) fn inner(&self) -> &CxxHandleScope {
|
||||
&self.0
|
||||
unsafe impl<'s> ScopeDefinition<'s> for HandleScope {
|
||||
type Args = *mut Isolate;
|
||||
unsafe fn enter_scope(buf: *mut Self, isolate: *mut Isolate) {
|
||||
v8__HandleScope__CONSTRUCT(buf, isolate);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'s, P> ScopeDefinition<'s> for HandleScope<P> {
|
||||
type Parent = P;
|
||||
type Args = &'s mut Isolate;
|
||||
unsafe fn enter_scope(ptr: *mut Self, isolate: &mut Isolate) {
|
||||
v8__HandleScope__CONSTRUCT(&mut (*ptr).0, isolate);
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> Drop for HandleScope<P> {
|
||||
impl Drop for HandleScope {
|
||||
fn drop(&mut self) {
|
||||
unsafe { v8__HandleScope__DESTRUCT(&mut self.0) }
|
||||
unsafe { v8__HandleScope__DESTRUCT(self) }
|
||||
}
|
||||
}
|
||||
|
||||
/// A HandleScope which first allocates a handle in the current scope
|
||||
/// which will be later filled with the escape value.
|
||||
pub struct EscapableHandleScope<P>(CxxEscapableHandleScope, PhantomData<P>);
|
||||
|
||||
#[repr(C)]
|
||||
pub(crate) struct CxxEscapableHandleScope([usize; 4]);
|
||||
pub struct EscapableHandleScope([usize; 4]);
|
||||
|
||||
impl<'p: 's, 's, P> EscapableHandleScope<P>
|
||||
where
|
||||
P: ToLocalOrReturnsLocal<'p>,
|
||||
{
|
||||
pub fn new(parent: &'s mut P) -> Scope<'s, Self> {
|
||||
Scope::new(parent.isolate())
|
||||
impl<'s> EscapableHandleScope {
|
||||
pub fn new<'p: 's, P>(parent: &'s mut P) -> Scope<'s, Self, P>
|
||||
where
|
||||
P: ToLocalOrReturnsLocal<'p>,
|
||||
{
|
||||
let isolate: *mut Isolate = parent.isolate();
|
||||
Scope::new(isolate, parent)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> EscapableHandleScope<P> {
|
||||
/// Pushes the value into the previous scope and returns a handle to it.
|
||||
/// Cannot be called twice.
|
||||
pub fn escape<'parent, T>(&mut self, value: Local<T>) -> Local<'parent, T> {
|
||||
unsafe {
|
||||
Local::from_raw(v8__EscapableHandleScope__Escape(
|
||||
&mut self.0,
|
||||
value.as_ptr() as *mut Value,
|
||||
) as *mut T)
|
||||
}
|
||||
pub(crate) unsafe fn escape<'p, T>(
|
||||
&mut self,
|
||||
value: Local<T>,
|
||||
) -> Local<'p, T> {
|
||||
Local::from_raw(v8__EscapableHandleScope__Escape(
|
||||
self,
|
||||
value.as_ptr() as *mut Value,
|
||||
) as *mut T)
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn inner(&self) -> &CxxEscapableHandleScope {
|
||||
&self.0
|
||||
unsafe impl<'s> ScopeDefinition<'s> for EscapableHandleScope {
|
||||
type Args = *mut Isolate;
|
||||
unsafe fn enter_scope(buf: *mut Self, isolate: *mut Isolate) {
|
||||
v8__EscapableHandleScope__CONSTRUCT(buf, isolate);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'s, P> ScopeDefinition<'s> for EscapableHandleScope<P> {
|
||||
type Parent = P;
|
||||
type Args = &'s mut Isolate;
|
||||
unsafe fn enter_scope(ptr: *mut Self, isolate: &mut Isolate) {
|
||||
v8__EscapableHandleScope__CONSTRUCT(&mut (*ptr).0, isolate);
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> Drop for EscapableHandleScope<P> {
|
||||
impl Drop for EscapableHandleScope {
|
||||
fn drop(&mut self) {
|
||||
unsafe { v8__EscapableHandleScope__DESTRUCT(&mut self.0) }
|
||||
unsafe { v8__EscapableHandleScope__DESTRUCT(self) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,10 @@ impl Locker {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn isolate(&mut self) -> &mut Isolate {
|
||||
unsafe { &mut *self.isolate }
|
||||
}
|
||||
|
||||
pub(crate) fn get_raw_isolate_(&self) -> *mut Isolate {
|
||||
self.isolate
|
||||
}
|
||||
|
|
174
src/scope.rs
174
src/scope.rs
|
@ -4,17 +4,16 @@ use std::marker::PhantomData;
|
|||
use std::mem::size_of;
|
||||
use std::mem::take;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ops::Deref;
|
||||
use std::ops::DerefMut;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use crate::scope_traits::internal::GetRawIsolate;
|
||||
use crate::Context;
|
||||
use crate::FunctionCallbackInfo;
|
||||
use crate::InIsolate;
|
||||
use crate::Isolate;
|
||||
use crate::Local;
|
||||
use crate::PromiseRejectMessage;
|
||||
use crate::PropertyCallbackInfo;
|
||||
use crate::ToLocal;
|
||||
|
||||
// Note: the 's lifetime is there to ensure that after entering a scope once,
|
||||
// the same scope object can't ever be entered again.
|
||||
|
@ -24,87 +23,103 @@ pub unsafe trait ScopeDefinition<'s>
|
|||
where
|
||||
Self: Sized,
|
||||
{
|
||||
type Parent;
|
||||
type Args;
|
||||
unsafe fn enter_scope(buf: *mut Self, args: Self::Args) -> ();
|
||||
}
|
||||
|
||||
/// A RAII scope wrapper object that will, when the `enter()` method is called,
|
||||
/// initialize and activate the guarded object.
|
||||
pub struct Scope<'s, S>
|
||||
pub struct Scope<'s, S, P = ()>
|
||||
where
|
||||
S: ScopeDefinition<'s>,
|
||||
{
|
||||
state: ScopeState<'s, S>,
|
||||
state: ScopeState<'s, S, P>,
|
||||
}
|
||||
|
||||
enum ScopeState<'s, S>
|
||||
enum ScopeState<'s, S, P>
|
||||
where
|
||||
S: ScopeDefinition<'s>,
|
||||
{
|
||||
Empty,
|
||||
New(S::Args),
|
||||
Uninit {
|
||||
data: MaybeUninit<S>,
|
||||
enter: MaybeUninit<Entered<'s, S>>,
|
||||
Allocated {
|
||||
args: S::Args,
|
||||
parent: &'s mut P,
|
||||
},
|
||||
Ready {
|
||||
EnteredUninit {
|
||||
data: MaybeUninit<S>,
|
||||
enter: MaybeUninit<Entered<'s, S, P>>,
|
||||
},
|
||||
EnteredReady {
|
||||
data: S,
|
||||
enter: Entered<'s, S>,
|
||||
enter: Entered<'s, S, P>,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'s, S> Scope<'s, S>
|
||||
fn parent_of_root() -> &'static mut () {
|
||||
unsafe { &mut *NonNull::<()>::dangling().as_ptr() }
|
||||
}
|
||||
|
||||
impl<'s, S> Scope<'s, S, ()>
|
||||
where
|
||||
S: ScopeDefinition<'s>,
|
||||
{
|
||||
/// Create a new root Scope object in unentered state.
|
||||
pub(crate) fn new_root(args: S::Args) -> Self {
|
||||
Self::new(args, parent_of_root())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, S, P> Scope<'s, S, P>
|
||||
where
|
||||
S: ScopeDefinition<'s>,
|
||||
{
|
||||
/// Create a new Scope object in unentered state.
|
||||
pub(crate) fn new(args: S::Args) -> Self {
|
||||
pub(crate) fn new(args: S::Args, parent: &'s mut P) -> Self {
|
||||
Self {
|
||||
state: ScopeState::New(args),
|
||||
state: ScopeState::Allocated { args, parent },
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes the guarded object and returns a mutable reference to it.
|
||||
/// A scope can only be entered once.
|
||||
pub fn enter(&'s mut self) -> &'s mut Entered<'s, S> {
|
||||
pub fn enter(&'s mut self) -> &'s mut Entered<'s, S, P> {
|
||||
assert_eq!(size_of::<S>(), size_of::<MaybeUninit<S>>());
|
||||
|
||||
use ScopeState::*;
|
||||
let Self { state } = self;
|
||||
|
||||
let args = match take(state) {
|
||||
New(f) => f,
|
||||
let (parent, args) = match take(state) {
|
||||
Allocated { parent, args } => (parent, args),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
*state = Uninit {
|
||||
*state = EnteredUninit {
|
||||
data: MaybeUninit::uninit(),
|
||||
enter: MaybeUninit::uninit(),
|
||||
};
|
||||
let data_ptr = match state {
|
||||
Uninit { data, .. } => data as *mut _ as *mut S,
|
||||
EnteredUninit { data, .. } => data as *mut _ as *mut S,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
unsafe { S::enter_scope(data_ptr, args) };
|
||||
|
||||
*state = match take(state) {
|
||||
Uninit { data, .. } => Ready {
|
||||
EnteredUninit { data, .. } => EnteredReady {
|
||||
data: unsafe { data.assume_init() },
|
||||
enter: Entered::new(unsafe { &mut *data_ptr }),
|
||||
enter: Entered::new(unsafe { &mut *data_ptr }, parent),
|
||||
},
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
match state {
|
||||
Ready { enter, .. } => enter,
|
||||
EnteredReady { enter, .. } => enter,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, S> Default for ScopeState<'s, S>
|
||||
impl<'s, S, P> Default for ScopeState<'s, S, P>
|
||||
where
|
||||
S: ScopeDefinition<'s>,
|
||||
{
|
||||
|
@ -114,25 +129,40 @@ where
|
|||
}
|
||||
|
||||
/// A wrapper around the an instantiated and entered scope object.
|
||||
#[repr(transparent)]
|
||||
pub struct Entered<'s, S>(*mut S, PhantomData<&'s ()>);
|
||||
#[repr(C)]
|
||||
pub struct Entered<'s, S, P = ()> {
|
||||
data: *mut S,
|
||||
parent: &'s mut P,
|
||||
}
|
||||
|
||||
impl<'s, S> Entered<'s, S> {
|
||||
pub(crate) fn new(data: *mut S) -> Self {
|
||||
Self(data, PhantomData)
|
||||
impl<'s, S> Entered<'s, S, ()> {
|
||||
pub(crate) fn new_root(data: *mut S) -> Self {
|
||||
Self {
|
||||
data,
|
||||
parent: parent_of_root(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, S> Deref for Entered<'s, S> {
|
||||
type Target = S;
|
||||
fn deref(&self) -> &S {
|
||||
unsafe { &*self.0 }
|
||||
impl<'s, S, P> Entered<'s, S, P> {
|
||||
pub(crate) fn new(data: *mut S, parent: &'s mut P) -> Self {
|
||||
Self { data, parent }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, S> DerefMut for Entered<'s, S> {
|
||||
fn deref_mut(&mut self) -> &mut S {
|
||||
unsafe { &mut *self.0 }
|
||||
pub(crate) fn data(&self) -> &S {
|
||||
unsafe { &*self.data }
|
||||
}
|
||||
|
||||
pub(crate) fn data_mut(&mut self) -> &mut S {
|
||||
unsafe { &mut *self.data }
|
||||
}
|
||||
|
||||
pub(crate) fn parent(&self) -> &P {
|
||||
&self.parent
|
||||
}
|
||||
|
||||
pub(crate) fn parent_mut(&mut self) -> &mut P {
|
||||
&mut self.parent
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,7 +216,6 @@ impl<X> CallbackScope<X> {
|
|||
}
|
||||
|
||||
unsafe impl<'s, X> ScopeDefinition<'s> for CallbackScope<X> {
|
||||
type Parent = ();
|
||||
type Args = *mut Isolate;
|
||||
unsafe fn enter_scope(ptr: *mut Self, isolate: Self::Args) {
|
||||
let data = Self {
|
||||
|
@ -199,7 +228,7 @@ unsafe impl<'s, X> ScopeDefinition<'s> for CallbackScope<X> {
|
|||
|
||||
impl<'s, X> From<&'s mut Isolate> for Scope<'s, CallbackScope<X>> {
|
||||
fn from(isolate: &'s mut Isolate) -> Self {
|
||||
Scope::new(isolate as *mut Isolate)
|
||||
Scope::new_root(isolate as *mut Isolate)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,7 +237,7 @@ where
|
|||
Local<'s, T>: GetRawIsolate,
|
||||
{
|
||||
fn from(local: Local<'s, T>) -> Self {
|
||||
Scope::new(local.get_raw_isolate())
|
||||
Scope::new_root(local.get_raw_isolate())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,64 +249,43 @@ impl<'s, X> From<&'s PromiseRejectMessage<'s>> for Scope<'s, CallbackScope<X>> {
|
|||
|
||||
/// Stack-allocated class which sets the execution context for all operations
|
||||
/// executed within a local scope.
|
||||
pub struct ContextScope<P> {
|
||||
context: ContextContainer,
|
||||
phantom: PhantomData<P>,
|
||||
pub struct ContextScope {
|
||||
context: *mut Context,
|
||||
}
|
||||
|
||||
impl<'s, P> ContextScope<P>
|
||||
where
|
||||
P: ToLocal<'s>,
|
||||
{
|
||||
pub fn new(
|
||||
_parent: &'s mut P,
|
||||
impl<'s> ContextScope {
|
||||
pub fn new<P>(
|
||||
parent: &'s mut P,
|
||||
context: Local<'s, Context>,
|
||||
) -> Scope<'s, Self> {
|
||||
Scope::new(context)
|
||||
) -> Scope<'s, Self, P>
|
||||
where
|
||||
P: InIsolate,
|
||||
{
|
||||
Scope::new(context, parent)
|
||||
}
|
||||
|
||||
pub(crate) fn get_captured_context(&self) -> Local<'s, Context> {
|
||||
unsafe { self.context.to_local() }
|
||||
pub(crate) unsafe fn get_captured_context(&self) -> Local<'s, Context> {
|
||||
Local::from_raw(self.context).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'s, P> ScopeDefinition<'s> for ContextScope<P>
|
||||
where
|
||||
P: ToLocal<'s>,
|
||||
{
|
||||
type Parent = P;
|
||||
unsafe impl<'s> ScopeDefinition<'s> for ContextScope {
|
||||
type Args = Local<'s, Context>;
|
||||
|
||||
unsafe fn enter_scope(ptr: *mut Self, mut context: Self::Args) {
|
||||
context.enter();
|
||||
let data = Self {
|
||||
context: context.into(),
|
||||
phantom: PhantomData,
|
||||
};
|
||||
std::ptr::write(ptr, data);
|
||||
std::ptr::write(
|
||||
ptr,
|
||||
Self {
|
||||
context: &mut *context,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(piscisaureus): It should not be necessary to create an inner struct
|
||||
// to appease the drop checker.
|
||||
struct ContextContainer(*mut Context);
|
||||
|
||||
impl<'s> From<Local<'s, Context>> for ContextContainer {
|
||||
fn from(mut local: Local<Context>) -> Self {
|
||||
let context = &mut *local as *mut Context;
|
||||
Self(context)
|
||||
}
|
||||
}
|
||||
|
||||
impl ContextContainer {
|
||||
unsafe fn to_local<'s>(&self) -> Local<'s, Context> {
|
||||
Local::from_raw(self.0).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ContextContainer {
|
||||
impl Drop for ContextScope {
|
||||
fn drop(&mut self) {
|
||||
unsafe { self.to_local() }.exit()
|
||||
unsafe { self.get_captured_context() }.exit()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// Copyright 2019-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::handle_scope::CxxEscapableHandleScope;
|
||||
use crate::handle_scope::CxxHandleScope;
|
||||
use crate::scope::Entered;
|
||||
use crate::scope::Escapable;
|
||||
use crate::CallbackScope;
|
||||
|
@ -24,12 +22,12 @@ pub(crate) mod internal {
|
|||
extern "C" {
|
||||
fn v8__Context__GetIsolate(self_: &Context) -> *mut Isolate;
|
||||
fn v8__EscapableHandleScope__GetIsolate(
|
||||
self_: &CxxEscapableHandleScope,
|
||||
self_: &EscapableHandleScope,
|
||||
) -> *mut Isolate;
|
||||
fn v8__FunctionCallbackInfo__GetIsolate(
|
||||
self_: &FunctionCallbackInfo,
|
||||
) -> *mut Isolate;
|
||||
fn v8__HandleScope__GetIsolate(self_: &CxxHandleScope) -> *mut Isolate;
|
||||
fn v8__HandleScope__GetIsolate(self_: &HandleScope) -> *mut Isolate;
|
||||
fn v8__Message__GetIsolate(self_: &Message) -> *mut Isolate;
|
||||
fn v8__Object__GetIsolate(self_: &Object) -> *mut Isolate;
|
||||
fn v8__PropertyCallbackInfo__GetIsolate(
|
||||
|
@ -71,7 +69,7 @@ pub(crate) mod internal {
|
|||
S: GetRawIsolate,
|
||||
{
|
||||
fn get_raw_isolate(&self) -> *mut Isolate {
|
||||
(&**self).get_raw_isolate()
|
||||
self.data().get_raw_isolate()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,12 +79,9 @@ pub(crate) mod internal {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'s, P> GetRawIsolate for ContextScope<P>
|
||||
where
|
||||
P: ToLocal<'s>,
|
||||
{
|
||||
impl<'s> GetRawIsolate for ContextScope {
|
||||
fn get_raw_isolate(&self) -> *mut Isolate {
|
||||
self.get_captured_context().get_raw_isolate()
|
||||
unsafe { self.get_captured_context() }.get_raw_isolate()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,9 +97,9 @@ pub(crate) mod internal {
|
|||
}
|
||||
}
|
||||
|
||||
impl<P> GetRawIsolate for EscapableHandleScope<P> {
|
||||
impl GetRawIsolate for EscapableHandleScope {
|
||||
fn get_raw_isolate(&self) -> *mut Isolate {
|
||||
unsafe { v8__EscapableHandleScope__GetIsolate(self.inner()) }
|
||||
unsafe { v8__EscapableHandleScope__GetIsolate(self) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,9 +109,9 @@ pub(crate) mod internal {
|
|||
}
|
||||
}
|
||||
|
||||
impl<P> GetRawIsolate for HandleScope<P> {
|
||||
impl GetRawIsolate for HandleScope {
|
||||
fn get_raw_isolate(&self) -> *mut Isolate {
|
||||
unsafe { v8__HandleScope__GetIsolate(self.inner()) }
|
||||
unsafe { v8__HandleScope__GetIsolate(self) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,25 +155,25 @@ impl InIsolate for Locker {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'s, S> InIsolate for Entered<'s, S>
|
||||
impl<'s, S, P> InIsolate for Entered<'s, S, P>
|
||||
where
|
||||
S: internal::GetRawIsolate,
|
||||
{
|
||||
fn isolate(&mut self) -> &mut Isolate {
|
||||
unsafe { &mut *self.get_raw_isolate() }
|
||||
unsafe { &mut *(self.data().get_raw_isolate()) }
|
||||
}
|
||||
}
|
||||
|
||||
pub trait InContext {}
|
||||
impl<'s> InContext for Entered<'s, FunctionCallbackInfo> {}
|
||||
impl<'s> InContext for Entered<'s, PropertyCallbackInfo> {}
|
||||
pub trait InContext: InIsolate {}
|
||||
impl<'s> InContext for Entered<'s, FunctionCallbackInfo, ()> {}
|
||||
impl<'s> InContext for Entered<'s, PropertyCallbackInfo, ()> {}
|
||||
impl<'s, X> InContext for Entered<'s, CallbackScope<X>> {}
|
||||
impl<'s, P> InContext for Entered<'s, ContextScope<P>> {}
|
||||
impl<'s, P> InContext for Entered<'s, HandleScope<P>> where P: InContext {}
|
||||
impl<'s, P> InContext for Entered<'s, EscapableHandleScope<P>> where P: InContext
|
||||
impl<'s, P> InContext for Entered<'s, ContextScope, P> {}
|
||||
impl<'s, P> InContext for Entered<'s, HandleScope, P> where P: InContext {}
|
||||
impl<'s, P> InContext for Entered<'s, EscapableHandleScope, P> where P: InContext
|
||||
{}
|
||||
|
||||
/// When scope implements this trait, this means that it Local handles can be
|
||||
/// When scope implements this trait, this means that Local handles can be
|
||||
/// created inside it.
|
||||
pub trait ToLocal<'s>: InIsolate {
|
||||
unsafe fn to_local<T>(&mut self, ptr: *mut T) -> Option<Local<'s, T>> {
|
||||
|
@ -188,10 +183,64 @@ pub trait ToLocal<'s>: InIsolate {
|
|||
|
||||
impl<'s> ToLocal<'s> for Entered<'s, FunctionCallbackInfo> {}
|
||||
impl<'s> ToLocal<'s> for Entered<'s, PropertyCallbackInfo> {}
|
||||
impl<'s, P> ToLocal<'s> for Entered<'s, HandleScope<P>> {}
|
||||
impl<'s, P> ToLocal<'s> for Entered<'s, EscapableHandleScope<P>> {}
|
||||
impl<'s, P> ToLocal<'s> for Entered<'s, ContextScope<P>> where P: ToLocal<'s> {}
|
||||
impl<'s, P> ToLocal<'s> for Entered<'s, HandleScope, P> {}
|
||||
impl<'s, P> ToLocal<'s> for Entered<'s, EscapableHandleScope, P> {}
|
||||
impl<'s, P> ToLocal<'s> for Entered<'s, ContextScope, P> where P: ToLocal<'s> {}
|
||||
|
||||
pub trait ToLocalOrReturnsLocal<'s>: InIsolate {}
|
||||
impl<'s, E> ToLocalOrReturnsLocal<'s> for E where E: ToLocal<'s> {}
|
||||
impl<'s> ToLocalOrReturnsLocal<'s> for Entered<'s, CallbackScope<Escapable>> {}
|
||||
impl<'s, 'p: 's> ToLocalOrReturnsLocal<'p>
|
||||
for Entered<'s, CallbackScope<Escapable>>
|
||||
{
|
||||
}
|
||||
|
||||
pub trait EscapeLocal<'s, 'p: 's>: ToLocal<'s> {
|
||||
fn escape<T>(&mut self, local: Local<T>) -> Local<'p, T>;
|
||||
}
|
||||
|
||||
impl<'s, 'p: 's, P> EscapeLocal<'s, 'p> for Entered<'s, EscapableHandleScope, P>
|
||||
where
|
||||
P: ToLocalOrReturnsLocal<'p>,
|
||||
{
|
||||
fn escape<T>(&mut self, local: Local<T>) -> Local<'p, T> {
|
||||
unsafe { self.data_mut().escape(local) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, 'p: 's, P> EscapeLocal<'s, 'p> for Entered<'s, ContextScope, P>
|
||||
where
|
||||
P: EscapeLocal<'s, 'p>,
|
||||
{
|
||||
fn escape<T>(&mut self, local: Local<T>) -> Local<'p, T> {
|
||||
self.parent_mut().escape(local)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, 'p: 's, P> EscapeLocal<'s, 'p> for Entered<'s, HandleScope, P>
|
||||
where
|
||||
P: EscapeLocal<'s, 'p>,
|
||||
{
|
||||
fn escape<T>(&mut self, local: Local<T>) -> Local<'p, T> {
|
||||
self.parent_mut().escape(local)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(piscisaureus): move the impls for Entered to a more sensible spot.
|
||||
|
||||
impl<'s, S, P> Entered<'s, S, P>
|
||||
where
|
||||
Self: InIsolate,
|
||||
{
|
||||
pub fn isolate(&mut self) -> &mut Isolate {
|
||||
<Self as InIsolate>::isolate(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, 'p: 's, S, P> Entered<'s, S, P>
|
||||
where
|
||||
Self: EscapeLocal<'s, 'p>,
|
||||
{
|
||||
pub fn escape<T>(&mut self, local: Local<T>) -> Local<'p, T> {
|
||||
<Self as EscapeLocal<'s, 'p>>::escape(self, local)
|
||||
}
|
||||
}
|
||||
|
|
23
tests/compile_fail/handle_scope_escape_lifetime.rs
Normal file
23
tests/compile_fail/handle_scope_escape_lifetime.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2019-2020 the Deno authors. All rights reserved. MIT license.
|
||||
use rusty_v8 as v8;
|
||||
|
||||
pub fn main() {
|
||||
let mut locker: v8::Locker = mock();
|
||||
let mut hs0 = v8::HandleScope::new(&mut locker);
|
||||
let hs0 = hs0.enter();
|
||||
|
||||
let _fail = {
|
||||
let mut hs1 = v8::HandleScope::new(hs0);
|
||||
let hs1 = hs1.enter();
|
||||
|
||||
let mut hs2 = v8::EscapableHandleScope::new(hs1);
|
||||
let hs2 = hs2.enter();
|
||||
|
||||
let value: v8::Local<v8::Value> = v8::Integer::new(hs2, 42).into();
|
||||
hs2.escape(value)
|
||||
};
|
||||
}
|
||||
|
||||
fn mock<T>() -> T {
|
||||
unimplemented!()
|
||||
}
|
11
tests/compile_fail/handle_scope_escape_lifetime.stderr
Normal file
11
tests/compile_fail/handle_scope_escape_lifetime.stderr
Normal file
|
@ -0,0 +1,11 @@
|
|||
error[E0597]: `hs1` does not live long enough
|
||||
--> $DIR/handle_scope_escape_lifetime.rs:11:15
|
||||
|
|
||||
9 | let _fail = {
|
||||
| ----- borrow later stored here
|
||||
10 | let mut hs1 = v8::HandleScope::new(hs0);
|
||||
11 | let hs1 = hs1.enter();
|
||||
| ^^^ borrowed value does not live long enough
|
||||
...
|
||||
18 | };
|
||||
| - `hs1` dropped here while still borrowed
|
12
tests/compile_fail/handle_scope_escape_to_nowhere.rs
Normal file
12
tests/compile_fail/handle_scope_escape_to_nowhere.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
// Copyright 2019-2020 the Deno authors. All rights reserved. MIT license.
|
||||
use rusty_v8 as v8;
|
||||
|
||||
pub fn main() {
|
||||
let context: v8::Local<v8::Context> = mock();
|
||||
let mut cs = v8::CallbackScope::new(context);
|
||||
let _hs = v8::EscapableHandleScope::new(cs.enter());
|
||||
}
|
||||
|
||||
fn mock<T>() -> T {
|
||||
unimplemented!()
|
||||
}
|
18
tests/compile_fail/handle_scope_escape_to_nowhere.stderr
Normal file
18
tests/compile_fail/handle_scope_escape_to_nowhere.stderr
Normal file
|
@ -0,0 +1,18 @@
|
|||
error[E0277]: the trait bound `rusty_v8::scope::Entered<'_, rusty_v8::scope::CallbackScope>: rusty_v8::scope_traits::ToLocal<'_>` is not satisfied
|
||||
--> $DIR/handle_scope_escape_to_nowhere.rs:7:43
|
||||
|
|
||||
7 | let _hs = v8::EscapableHandleScope::new(cs.enter());
|
||||
| ^^^^^^^^^^ the trait `rusty_v8::scope_traits::ToLocal<'_>` is not implemented for `rusty_v8::scope::Entered<'_, rusty_v8::scope::CallbackScope>`
|
||||
|
|
||||
::: $WORKSPACE/src/handle_scope.rs:71:8
|
||||
|
|
||||
71 | P: ToLocalOrReturnsLocal<'p>,
|
||||
| ------------------------- required by this bound in `rusty_v8::handle_scope::EscapableHandleScope::new`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<rusty_v8::scope::Entered<'s, rusty_v8::function::FunctionCallbackInfo> as rusty_v8::scope_traits::ToLocal<'s>>
|
||||
<rusty_v8::scope::Entered<'s, rusty_v8::function::PropertyCallbackInfo> as rusty_v8::scope_traits::ToLocal<'s>>
|
||||
<rusty_v8::scope::Entered<'s, rusty_v8::handle_scope::EscapableHandleScope, P> as rusty_v8::scope_traits::ToLocal<'s>>
|
||||
<rusty_v8::scope::Entered<'s, rusty_v8::handle_scope::HandleScope, P> as rusty_v8::scope_traits::ToLocal<'s>>
|
||||
<rusty_v8::scope::Entered<'s, rusty_v8::scope::ContextScope, P> as rusty_v8::scope_traits::ToLocal<'s>>
|
||||
= note: required because of the requirements on the impl of `rusty_v8::scope_traits::ToLocalOrReturnsLocal<'_>` for `rusty_v8::scope::Entered<'_, rusty_v8::scope::CallbackScope>`
|
|
@ -1,17 +1,20 @@
|
|||
extern crate rusty_v8 as v8;
|
||||
// Copyright 2019-2020 the Deno authors. All rights reserved. MIT license.
|
||||
use rusty_v8 as v8;
|
||||
|
||||
pub fn main() {
|
||||
let mut isolate: v8::scope::Entered<v8::HandleScope<v8::Locker>> = mock();
|
||||
let mut locker: v8::Locker = mock();
|
||||
let mut root_hs = v8::HandleScope::new(&mut locker);
|
||||
let root_hs = root_hs.enter();
|
||||
|
||||
{
|
||||
let mut hs = v8::EscapableHandleScope::new(&mut isolate);
|
||||
let mut hs = v8::EscapableHandleScope::new(root_hs);
|
||||
let hs = hs.enter();
|
||||
let _fail = v8::EscapableHandleScope::new(&mut isolate);
|
||||
let _fail = v8::EscapableHandleScope::new(root_hs);
|
||||
let _local = v8::Integer::new(hs, 123);
|
||||
}
|
||||
|
||||
{
|
||||
let mut hs1 = v8::EscapableHandleScope::new(&mut isolate);
|
||||
let mut hs1 = v8::EscapableHandleScope::new(root_hs);
|
||||
let hs1 = hs1.enter();
|
||||
let _local1 = v8::Integer::new(hs1, 123);
|
||||
|
||||
|
@ -23,13 +26,13 @@ pub fn main() {
|
|||
}
|
||||
|
||||
let _leak1 = {
|
||||
let mut hs = v8::EscapableHandleScope::new(&mut isolate);
|
||||
let mut hs = v8::EscapableHandleScope::new(root_hs);
|
||||
let hs = hs.enter();
|
||||
v8::Integer::new(hs, 456)
|
||||
};
|
||||
|
||||
let _leak = {
|
||||
let mut hs = v8::EscapableHandleScope::new(&mut isolate);
|
||||
let mut hs = v8::EscapableHandleScope::new(root_hs);
|
||||
hs.enter()
|
||||
};
|
||||
}
|
||||
|
@ -37,5 +40,3 @@ pub fn main() {
|
|||
fn mock<T>() -> T {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn access<T>(_value: T) {}
|
||||
|
|
|
@ -1,44 +1,44 @@
|
|||
error[E0499]: cannot borrow `isolate` as mutable more than once at a time
|
||||
--> $DIR/handle_scope_lifetimes.rs:9:47
|
||||
error[E0499]: cannot borrow `*root_hs` as mutable more than once at a time
|
||||
--> $DIR/handle_scope_lifetimes.rs:12:47
|
||||
|
|
||||
7 | let mut hs = v8::EscapableHandleScope::new(&mut isolate);
|
||||
| ------------ first mutable borrow occurs here
|
||||
8 | let hs = hs.enter();
|
||||
9 | let _fail = v8::EscapableHandleScope::new(&mut isolate);
|
||||
| ^^^^^^^^^^^^ second mutable borrow occurs here
|
||||
10 | let _local = v8::Integer::new(hs, 123);
|
||||
10 | let mut hs = v8::EscapableHandleScope::new(root_hs);
|
||||
| ------- first mutable borrow occurs here
|
||||
11 | let hs = hs.enter();
|
||||
12 | let _fail = v8::EscapableHandleScope::new(root_hs);
|
||||
| ^^^^^^^ second mutable borrow occurs here
|
||||
13 | let _local = v8::Integer::new(hs, 123);
|
||||
| -- first borrow later used here
|
||||
|
||||
error[E0499]: cannot borrow `*hs1` as mutable more than once at a time
|
||||
--> $DIR/handle_scope_lifetimes.rs:20:34
|
||||
--> $DIR/handle_scope_lifetimes.rs:23:34
|
||||
|
|
||||
18 | let mut hs2 = v8::EscapableHandleScope::new(hs1);
|
||||
21 | let mut hs2 = v8::EscapableHandleScope::new(hs1);
|
||||
| --- first mutable borrow occurs here
|
||||
19 | let hs2 = hs2.enter();
|
||||
20 | let _fail = v8::Integer::new(hs1, 123);
|
||||
22 | let hs2 = hs2.enter();
|
||||
23 | let _fail = v8::Integer::new(hs1, 123);
|
||||
| ^^^ second mutable borrow occurs here
|
||||
21 | let _local2 = v8::Integer::new(hs2, 123);
|
||||
24 | let _local2 = v8::Integer::new(hs2, 123);
|
||||
| --- first borrow later used here
|
||||
|
||||
error[E0597]: `hs` does not live long enough
|
||||
--> $DIR/handle_scope_lifetimes.rs:27:14
|
||||
--> $DIR/handle_scope_lifetimes.rs:30:14
|
||||
|
|
||||
25 | let _leak1 = {
|
||||
28 | let _leak1 = {
|
||||
| ------ borrow later stored here
|
||||
26 | let mut hs = v8::EscapableHandleScope::new(&mut isolate);
|
||||
27 | let hs = hs.enter();
|
||||
29 | let mut hs = v8::EscapableHandleScope::new(root_hs);
|
||||
30 | let hs = hs.enter();
|
||||
| ^^ borrowed value does not live long enough
|
||||
28 | v8::Integer::new(hs, 456)
|
||||
29 | };
|
||||
31 | v8::Integer::new(hs, 456)
|
||||
32 | };
|
||||
| - `hs` dropped here while still borrowed
|
||||
|
||||
error[E0597]: `hs` does not live long enough
|
||||
--> $DIR/handle_scope_lifetimes.rs:33:5
|
||||
--> $DIR/handle_scope_lifetimes.rs:36:5
|
||||
|
|
||||
33 | hs.enter()
|
||||
36 | hs.enter()
|
||||
| ^^--------
|
||||
| |
|
||||
| borrowed value does not live long enough
|
||||
| borrow later used here
|
||||
34 | };
|
||||
37 | };
|
||||
| - `hs` dropped here while still borrowed
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
extern crate rusty_v8 as v8;
|
||||
// Copyright 2019-2020 the Deno authors. All rights reserved. MIT license.
|
||||
use rusty_v8 as v8;
|
||||
|
||||
pub fn main() {
|
||||
let mut scope: v8::Scope<v8::HandleScope<v8::Locker>> = mock();
|
||||
let mut scope: v8::Scope<v8::HandleScope, v8::Locker> = mock();
|
||||
let scope = scope.enter();
|
||||
let context: v8::Local<v8::Context> = mock();
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
error[E0597]: `try_catch` does not live long enough
|
||||
--> $DIR/try_catch_lifetimes.rs:10:14
|
||||
--> $DIR/try_catch_lifetimes.rs:11:14
|
||||
|
|
||||
8 | let _leaked = {
|
||||
9 | let _leaked = {
|
||||
| ------- borrow later stored here
|
||||
9 | let mut try_catch = v8::TryCatch::new(scope);
|
||||
10 | let tc = try_catch.enter();
|
||||
10 | let mut try_catch = v8::TryCatch::new(scope);
|
||||
11 | let tc = try_catch.enter();
|
||||
| ^^^^^^^^^ borrowed value does not live long enough
|
||||
...
|
||||
15 | };
|
||||
16 | };
|
||||
| - `try_catch` dropped here while still borrowed
|
||||
|
|
|
@ -8,7 +8,6 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
|||
use std::sync::Mutex;
|
||||
|
||||
use rusty_v8 as v8;
|
||||
use v8::InIsolate;
|
||||
// TODO(piscisaureus): Ideally there would be no need to import this trait.
|
||||
use v8::MapFnTo;
|
||||
|
||||
|
|
Loading…
Reference in a new issue