0
0
Fork 0
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:
Bert Belder 2020-01-20 03:16:37 +01:00
parent 6efb395fdc
commit 36a12142f2
No known key found for this signature in database
GPG key ID: 7A77887B2E2ED461
14 changed files with 320 additions and 213 deletions

View file

@ -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);

View file

@ -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) }
}
}

View file

@ -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
}

View file

@ -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()
}
}

View file

@ -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)
}
}

View 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!()
}

View 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

View 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!()
}

View 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>`

View file

@ -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) {}

View file

@ -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

View file

@ -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();

View file

@ -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

View file

@ -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;