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

Rewrite the scope system from scratch (#406)

This commit is contained in:
Bert Belder 2020-06-03 07:38:34 +02:00
parent 8a4dc30445
commit 3b6ed67f5e
No known key found for this signature in database
GPG key ID: 7A77887B2E2ED461
56 changed files with 2285 additions and 1889 deletions

View file

@ -61,6 +61,10 @@ fn build_v8() {
vec!["is_debug=false".to_string()] vec!["is_debug=false".to_string()]
}; };
if !cargo_gn::is_debug() {
gn_args.push("v8_enable_handle_zapping=false".to_string());
}
if let Some(clang_base_path) = find_compatible_system_clang() { if let Some(clang_base_path) = find_compatible_system_clang() {
println!("clang_base_path {}", clang_base_path.display()); println!("clang_base_path {}", clang_base_path.display());
gn_args.push(format!("clang_base_path={:?}", clang_base_path)); gn_args.push(format!("clang_base_path={:?}", clang_base_path));

View file

@ -14,10 +14,9 @@ use crate::support::SharedRef;
use crate::support::UniquePtr; use crate::support::UniquePtr;
use crate::support::UniqueRef; use crate::support::UniqueRef;
use crate::ArrayBuffer; use crate::ArrayBuffer;
use crate::InIsolate; use crate::HandleScope;
use crate::Isolate; use crate::Isolate;
use crate::Local; use crate::Local;
use crate::ToLocal;
extern "C" { extern "C" {
fn v8__ArrayBuffer__Allocator__NewDefaultAllocator() -> *mut Allocator; fn v8__ArrayBuffer__Allocator__NewDefaultAllocator() -> *mut Allocator;
@ -236,25 +235,31 @@ impl ArrayBuffer {
/// Allocated memory will be owned by a created ArrayBuffer and /// Allocated memory will be owned by a created ArrayBuffer and
/// will be deallocated when it is garbage-collected, /// will be deallocated when it is garbage-collected,
/// unless the object is externalized. /// unless the object is externalized.
pub fn new<'sc>( pub fn new<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
byte_length: usize, byte_length: usize,
) -> Local<'sc, ArrayBuffer> { ) -> Local<'s, ArrayBuffer> {
unsafe { unsafe {
scope.cast_local(|scope| { scope.cast_local(|sd| {
v8__ArrayBuffer__New__with_byte_length(scope.isolate(), byte_length) v8__ArrayBuffer__New__with_byte_length(
sd.get_isolate_ptr(),
byte_length,
)
}) })
} }
.unwrap() .unwrap()
} }
pub fn with_backing_store<'sc>( pub fn with_backing_store<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
backing_store: &SharedRef<BackingStore>, backing_store: &SharedRef<BackingStore>,
) -> Local<'sc, ArrayBuffer> { ) -> Local<'s, ArrayBuffer> {
unsafe { unsafe {
scope.cast_local(|scope| { scope.cast_local(|sd| {
v8__ArrayBuffer__New__with_backing_store(scope.isolate(), backing_store) v8__ArrayBuffer__New__with_backing_store(
sd.get_isolate_ptr(),
backing_store,
)
}) })
} }
.unwrap() .unwrap()
@ -281,12 +286,12 @@ impl ArrayBuffer {
/// given isolate and re-try the allocation. If GCs do not help, then the /// given isolate and re-try the allocation. If GCs do not help, then the
/// function will crash with an out-of-memory error. /// function will crash with an out-of-memory error.
pub fn new_backing_store( pub fn new_backing_store(
scope: &mut impl InIsolate, scope: &mut Isolate,
byte_length: usize, byte_length: usize,
) -> UniqueRef<BackingStore> { ) -> UniqueRef<BackingStore> {
unsafe { unsafe {
UniqueRef::from_raw(v8__ArrayBuffer__NewBackingStore__with_byte_length( UniqueRef::from_raw(v8__ArrayBuffer__NewBackingStore__with_byte_length(
scope.isolate(), scope,
byte_length, byte_length,
)) ))
} }

View file

@ -4,8 +4,8 @@ use std::ffi::c_void;
use crate::support::int; use crate::support::int;
use crate::ArrayBuffer; use crate::ArrayBuffer;
use crate::ArrayBufferView; use crate::ArrayBufferView;
use crate::HandleScope;
use crate::Local; use crate::Local;
use crate::ToLocal;
extern "C" { extern "C" {
fn v8__ArrayBufferView__Buffer( fn v8__ArrayBufferView__Buffer(
@ -22,10 +22,10 @@ extern "C" {
impl ArrayBufferView { impl ArrayBufferView {
/// Returns underlying ArrayBuffer. /// Returns underlying ArrayBuffer.
pub fn buffer<'sc>( pub fn buffer<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
) -> Option<Local<'sc, ArrayBuffer>> { ) -> Option<Local<'s, ArrayBuffer>> {
unsafe { scope.cast_local(|_| v8__ArrayBufferView__Buffer(self)) } unsafe { scope.cast_local(|_| v8__ArrayBufferView__Buffer(self)) }
} }

View file

@ -209,29 +209,6 @@ void v8__HandleScope__CONSTRUCT(uninit_t<v8::HandleScope>* buf,
void v8__HandleScope__DESTRUCT(v8::HandleScope* self) { self->~HandleScope(); } void v8__HandleScope__DESTRUCT(v8::HandleScope* self) { self->~HandleScope(); }
v8::Isolate* v8__HandleScope__GetIsolate(const v8::HandleScope& self) {
return self.GetIsolate();
}
void v8__EscapableHandleScope__CONSTRUCT(
uninit_t<v8::EscapableHandleScope>* buf, v8::Isolate* isolate) {
construct_in_place<v8::EscapableHandleScope>(buf, isolate);
}
void v8__EscapableHandleScope__DESTRUCT(v8::EscapableHandleScope* self) {
self->~EscapableHandleScope();
}
const v8::Data* v8__EscapableHandleScope__Escape(v8::EscapableHandleScope* self,
const v8::Data& value) {
return local_to_ptr(self->Escape(ptr_to_local(&value)));
}
v8::Isolate* v8__EscapableHandleScope__GetIsolate(
const v8::EscapableHandleScope& self) {
return self.GetIsolate();
}
const v8::Data* v8__Local__New(v8::Isolate* isolate, const v8::Data& other) { const v8::Data* v8__Local__New(v8::Isolate* isolate, const v8::Data& other) {
return local_to_ptr(v8::Local<v8::Data>::New(isolate, ptr_to_local(&other))); return local_to_ptr(v8::Local<v8::Data>::New(isolate, ptr_to_local(&other)));
} }
@ -889,6 +866,10 @@ const v8::Context* v8__Context__New(v8::Isolate* isolate,
DeserializeInternalFields, nullptr))); DeserializeInternalFields, nullptr)));
} }
bool v8__Context__EQ(const v8::Context& self, const v8::Context& other) {
return ptr_to_local(&self) == ptr_to_local(&other);
}
void v8__Context__Enter(const v8::Context& self) { void v8__Context__Enter(const v8::Context& self) {
ptr_to_local(&self)->Enter(); ptr_to_local(&self)->Enter();
} }

View file

@ -1,10 +1,10 @@
// Copyright 2019-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2019-2020 the Deno authors. All rights reserved. MIT license.
use crate::isolate::Isolate; use crate::isolate::Isolate;
use crate::Context; use crate::Context;
use crate::HandleScope;
use crate::Local; use crate::Local;
use crate::Object; use crate::Object;
use crate::ObjectTemplate; use crate::ObjectTemplate;
use crate::ToLocal;
use crate::Value; use crate::Value;
use std::ptr::null; use std::ptr::null;
@ -14,31 +14,30 @@ extern "C" {
templ: *const ObjectTemplate, templ: *const ObjectTemplate,
global_object: *const Value, global_object: *const Value,
) -> *const Context; ) -> *const Context;
fn v8__Context__Enter(this: *const Context);
fn v8__Context__Exit(this: *const Context);
fn v8__Context__Global(this: *const Context) -> *const Object; fn v8__Context__Global(this: *const Context) -> *const Object;
} }
impl Context { impl Context {
/// Creates a new context. /// Creates a new context.
pub fn new<'sc>(scope: &mut impl ToLocal<'sc>) -> Local<'sc, Context> { pub fn new<'s>(scope: &mut HandleScope<'s, ()>) -> Local<'s, Context> {
// TODO: optional arguments; // TODO: optional arguments;
unsafe { unsafe {
scope scope
.cast_local(|scope| v8__Context__New(scope.isolate(), null(), null())) .cast_local(|sd| v8__Context__New(sd.get_isolate_ptr(), null(), null()))
} }
.unwrap() .unwrap()
} }
/// Creates a new context using the object template as the template for /// Creates a new context using the object template as the template for
/// the global object. /// the global object.
pub fn new_from_template<'sc>( pub fn new_from_template<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s, ()>,
templ: Local<ObjectTemplate>, templ: Local<ObjectTemplate>,
) -> Local<'sc, Context> { ) -> Local<'s, Context> {
unsafe { unsafe {
scope scope.cast_local(|sd| {
.cast_local(|scope| v8__Context__New(scope.isolate(), &*templ, null())) v8__Context__New(sd.get_isolate_ptr(), &*templ, null())
})
} }
.unwrap() .unwrap()
} }
@ -53,26 +52,10 @@ impl Context {
/// Please note that changes to global proxy object prototype most probably /// Please note that changes to global proxy object prototype most probably
/// would break VM---v8 expects only global object as a prototype of global /// would break VM---v8 expects only global object as a prototype of global
/// proxy object. /// proxy object.
pub fn global<'sc>( pub fn global<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s, ()>,
) -> Local<'sc, Object> { ) -> Local<'s, Object> {
unsafe { scope.cast_local(|_| v8__Context__Global(self)) }.unwrap() unsafe { scope.cast_local(|_| v8__Context__Global(self)) }.unwrap()
} }
/// Enter this context. After entering a context, all code compiled
/// and run is compiled and run in this context. If another context
/// is already entered, this old context is saved so it can be
/// restored when the new context is exited.
pub(crate) fn enter(&self) {
// TODO: enter/exit should be controlled by a scope.
unsafe { v8__Context__Enter(self) };
}
/// Exit this context. Exiting the current context restores the
/// context that was in place when entering the current context.
pub(crate) fn exit(&self) {
// TODO: enter/exit should be controlled by a scope.
unsafe { v8__Context__Exit(self) };
}
} }

View file

@ -25,8 +25,8 @@ macro_rules! impl_deref {
macro_rules! impl_from { macro_rules! impl_from {
{ $source:ident for $type:ident } => { { $source:ident for $type:ident } => {
impl<'sc> From<Local<'sc, $source>> for Local<'sc, $type> { impl<'s> From<Local<'s, $source>> for Local<'s, $type> {
fn from(l: Local<'sc, $source>) -> Self { fn from(l: Local<'s, $source>) -> Self {
unsafe { transmute(l) } unsafe { transmute(l) }
} }
} }
@ -35,9 +35,9 @@ macro_rules! impl_from {
macro_rules! impl_try_from { macro_rules! impl_try_from {
{ $source:ident for $target:ident if $value:pat => $check:expr } => { { $source:ident for $target:ident if $value:pat => $check:expr } => {
impl<'sc> TryFrom<Local<'sc, $source>> for Local<'sc, $target> { impl<'s> TryFrom<Local<'s, $source>> for Local<'s, $target> {
type Error = TryFromTypeError; type Error = TryFromTypeError;
fn try_from(l: Local<'sc, $source>) -> Result<Self, Self::Error> { fn try_from(l: Local<'s, $source>) -> Result<Self, Self::Error> {
match l { match l {
$value if $check => Ok(unsafe { transmute(l) }), $value if $check => Ok(unsafe { transmute(l) }),
_ => Err(TryFromTypeError::new(stringify!($target))) _ => Err(TryFromTypeError::new(stringify!($target)))
@ -49,21 +49,21 @@ macro_rules! impl_try_from {
macro_rules! impl_eq { macro_rules! impl_eq {
{ for $type:ident } => { { for $type:ident } => {
impl<'sc> Eq for Local<'sc, $type> {} impl<'s> Eq for Local<'s, $type> {}
}; };
} }
macro_rules! impl_partial_eq { macro_rules! impl_partial_eq {
{ $rhs:ident for $type:ident use identity } => { { $rhs:ident for $type:ident use identity } => {
impl<'sc> PartialEq<Local<'sc, $rhs>> for Local<'sc, $type> { impl<'s> PartialEq<Local<'s, $rhs>> for Local<'s, $type> {
fn eq(&self, other: &Local<'sc, $rhs>) -> bool { fn eq(&self, other: &Local<'s, $rhs>) -> bool {
self.eq_identity((*other).into()) self.eq_identity((*other).into())
} }
} }
}; };
{ $rhs:ident for $type:ident use strict_equals } => { { $rhs:ident for $type:ident use strict_equals } => {
impl<'sc> PartialEq<Local<'sc, $rhs>> for Local<'sc, $type> { impl<'s> PartialEq<Local<'s, $rhs>> for Local<'s, $type> {
fn eq(&self, other: &Local<'sc, $rhs>) -> bool { fn eq(&self, other: &Local<'s, $rhs>) -> bool {
self.strict_equals((*other).into()) self.strict_equals((*other).into())
} }
} }

View file

@ -3,12 +3,12 @@
use crate::isolate::Isolate; use crate::isolate::Isolate;
use crate::support::int; use crate::support::int;
use crate::Context; use crate::Context;
use crate::HandleScope;
use crate::Local; use crate::Local;
use crate::Message; use crate::Message;
use crate::StackFrame; use crate::StackFrame;
use crate::StackTrace; use crate::StackTrace;
use crate::String; use crate::String;
use crate::ToLocal;
use crate::Value; use crate::Value;
extern "C" { extern "C" {
@ -73,14 +73,14 @@ impl StackTrace {
} }
/// Returns a StackFrame at a particular index. /// Returns a StackFrame at a particular index.
pub fn get_frame<'sc>( pub fn get_frame<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
index: usize, index: usize,
) -> Option<Local<'sc, StackFrame>> { ) -> Option<Local<'s, StackFrame>> {
unsafe { unsafe {
scope.cast_local(|scope| { scope.cast_local(|sd| {
v8__StackTrace__GetFrame(self, scope.isolate(), index as u32) v8__StackTrace__GetFrame(self, sd.get_isolate_ptr(), index as u32)
}) })
} }
} }
@ -114,10 +114,10 @@ impl StackFrame {
/// Returns the name of the resource that contains the script for the /// Returns the name of the resource that contains the script for the
/// function for this StackFrame. /// function for this StackFrame.
pub fn get_script_name<'sc>( pub fn get_script_name<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
) -> Option<Local<'sc, String>> { ) -> Option<Local<'s, String>> {
unsafe { scope.cast_local(|_| v8__StackFrame__GetScriptName(self)) } unsafe { scope.cast_local(|_| v8__StackFrame__GetScriptName(self)) }
} }
@ -125,20 +125,20 @@ impl StackFrame {
/// function for this StackFrame or sourceURL value if the script name /// function for this StackFrame or sourceURL value if the script name
/// is undefined and its source ends with //# sourceURL=... string or /// is undefined and its source ends with //# sourceURL=... string or
/// deprecated //@ sourceURL=... string. /// deprecated //@ sourceURL=... string.
pub fn get_script_name_or_source_url<'sc>( pub fn get_script_name_or_source_url<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
) -> Option<Local<'sc, String>> { ) -> Option<Local<'s, String>> {
unsafe { unsafe {
scope.cast_local(|_| v8__StackFrame__GetScriptNameOrSourceURL(self)) scope.cast_local(|_| v8__StackFrame__GetScriptNameOrSourceURL(self))
} }
} }
/// Returns the name of the function associated with this stack frame. /// Returns the name of the function associated with this stack frame.
pub fn get_function_name<'sc>( pub fn get_function_name<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
) -> Option<Local<'sc, String>> { ) -> Option<Local<'s, String>> {
unsafe { scope.cast_local(|_| v8__StackFrame__GetFunctionName(self)) } unsafe { scope.cast_local(|_| v8__StackFrame__GetFunctionName(self)) }
} }
@ -166,23 +166,23 @@ impl StackFrame {
} }
impl Message { impl Message {
pub fn get<'sc>(&self, scope: &mut impl ToLocal<'sc>) -> Local<'sc, String> { pub fn get<'s>(&self, scope: &mut HandleScope<'s>) -> Local<'s, String> {
unsafe { scope.cast_local(|_| v8__Message__Get(self)) }.unwrap() unsafe { scope.cast_local(|_| v8__Message__Get(self)) }.unwrap()
} }
/// Exception stack trace. By default stack traces are not captured for /// Exception stack trace. By default stack traces are not captured for
/// uncaught exceptions. SetCaptureStackTraceForUncaughtExceptions allows /// uncaught exceptions. SetCaptureStackTraceForUncaughtExceptions allows
/// to change this option. /// to change this option.
pub fn get_stack_trace<'sc>( pub fn get_stack_trace<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
) -> Option<Local<'sc, StackTrace>> { ) -> Option<Local<'s, StackTrace>> {
unsafe { scope.cast_local(|_| v8__Message__GetStackTrace(self)) } unsafe { scope.cast_local(|_| v8__Message__GetStackTrace(self)) }
} }
pub fn get_source_line<'s>( pub fn get_source_line<'s>(
&self, &self,
scope: &mut impl ToLocal<'s>, scope: &mut HandleScope<'s>,
context: Local<Context>, context: Local<Context>,
) -> Option<Local<'s, String>> { ) -> Option<Local<'s, String>> {
unsafe { scope.cast_local(|_| v8__Message__GetSourceLine(self, &*context)) } unsafe { scope.cast_local(|_| v8__Message__GetSourceLine(self, &*context)) }
@ -192,7 +192,7 @@ impl Message {
/// the error originates. /// the error originates.
pub fn get_script_resource_name<'s>( pub fn get_script_resource_name<'s>(
&self, &self,
scope: &mut impl ToLocal<'s>, scope: &mut HandleScope<'s>,
) -> Option<Local<'s, Value>> { ) -> Option<Local<'s, Value>> {
unsafe { scope.cast_local(|_| v8__Message__GetScriptResourceName(self)) } unsafe { scope.cast_local(|_| v8__Message__GetScriptResourceName(self)) }
} }
@ -258,64 +258,64 @@ impl Message {
pub struct Exception; pub struct Exception;
impl Exception { impl Exception {
pub fn error<'sc>( pub fn error<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
message: Local<String>, message: Local<String>,
) -> Local<'sc, Value> { ) -> Local<'s, Value> {
Self::new_error_with(scope, message, v8__Exception__Error) Self::new_error_with(scope, message, v8__Exception__Error)
} }
pub fn range_error<'sc>( pub fn range_error<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
message: Local<String>, message: Local<String>,
) -> Local<'sc, Value> { ) -> Local<'s, Value> {
Self::new_error_with(scope, message, v8__Exception__RangeError) Self::new_error_with(scope, message, v8__Exception__RangeError)
} }
pub fn reference_error<'sc>( pub fn reference_error<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
message: Local<String>, message: Local<String>,
) -> Local<'sc, Value> { ) -> Local<'s, Value> {
Self::new_error_with(scope, message, v8__Exception__ReferenceError) Self::new_error_with(scope, message, v8__Exception__ReferenceError)
} }
pub fn syntax_error<'sc>( pub fn syntax_error<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
message: Local<String>, message: Local<String>,
) -> Local<'sc, Value> { ) -> Local<'s, Value> {
Self::new_error_with(scope, message, v8__Exception__SyntaxError) Self::new_error_with(scope, message, v8__Exception__SyntaxError)
} }
pub fn type_error<'sc>( pub fn type_error<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
message: Local<String>, message: Local<String>,
) -> Local<'sc, Value> { ) -> Local<'s, Value> {
Self::new_error_with(scope, message, v8__Exception__TypeError) Self::new_error_with(scope, message, v8__Exception__TypeError)
} }
/// Internal helper to make the above error constructors less repetitive. /// Internal helper to make the above error constructors less repetitive.
fn new_error_with<'sc>( fn new_error_with<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
message: Local<String>, message: Local<String>,
contructor: unsafe extern "C" fn(*const String) -> *const Value, contructor: unsafe extern "C" fn(*const String) -> *const Value,
) -> Local<'sc, Value> { ) -> Local<'s, Value> {
scope.isolate().enter(); scope.enter_isolate();
let error = let error =
unsafe { scope.cast_local(|_| (contructor)(&*message)) }.unwrap(); unsafe { scope.cast_local(|_| (contructor)(&*message)) }.unwrap();
scope.isolate().exit(); scope.exit_isolate();
error error
} }
/// Creates an error message for the given exception. /// Creates an error message for the given exception.
/// Will try to reconstruct the original stack trace from the exception value, /// Will try to reconstruct the original stack trace from the exception value,
/// or capture the current stack trace if not available. /// or capture the current stack trace if not available.
pub fn create_message<'sc>( pub fn create_message<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
exception: Local<Value>, exception: Local<Value>,
) -> Local<'sc, Message> { ) -> Local<'s, Message> {
unsafe { unsafe {
scope.cast_local(|scope| { scope.cast_local(|sd| {
v8__Exception__CreateMessage(scope.isolate(), &*exception) v8__Exception__CreateMessage(sd.get_isolate_ptr(), &*exception)
}) })
} }
.unwrap() .unwrap()
@ -323,10 +323,10 @@ impl Exception {
/// Returns the original stack trace that was captured at the creation time /// Returns the original stack trace that was captured at the creation time
/// of a given exception, or an empty handle if not available. /// of a given exception, or an empty handle if not available.
pub fn get_stack_trace<'sc>( pub fn get_stack_trace<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
exception: Local<Value>, exception: Local<Value>,
) -> Option<Local<'sc, StackTrace>> { ) -> Option<Local<'s, StackTrace>> {
unsafe { scope.cast_local(|_| v8__Exception__GetStackTrace(&*exception)) } unsafe { scope.cast_local(|_| v8__Exception__GetStackTrace(&*exception)) }
} }
} }

View file

@ -1,20 +1,18 @@
use std::convert::TryFrom; use std::convert::TryFrom;
use std::marker::PhantomData; use std::marker::PhantomData;
use crate::scope::ScopeDefinition;
use crate::support::MapFnFrom; use crate::support::MapFnFrom;
use crate::support::MapFnTo; use crate::support::MapFnTo;
use crate::support::ToCFn; use crate::support::ToCFn;
use crate::support::UnitType; use crate::support::UnitType;
use crate::support::{int, Opaque}; use crate::support::{int, Opaque};
use crate::CallbackScope;
use crate::Context; use crate::Context;
use crate::Function; use crate::Function;
use crate::FunctionCallbackScope; use crate::HandleScope;
use crate::Local; use crate::Local;
use crate::Name; use crate::Name;
use crate::Object; use crate::Object;
use crate::PropertyCallbackScope;
use crate::ToLocal;
use crate::Value; use crate::Value;
extern "C" { extern "C" {
@ -92,10 +90,7 @@ impl<'cb> ReturnValue<'cb> {
/// Getter. Creates a new Local<> so it comes with a certain performance /// Getter. Creates a new Local<> so it comes with a certain performance
/// hit. If the ReturnValue was not yet set, this will return the undefined /// hit. If the ReturnValue was not yet set, this will return the undefined
/// value. /// value.
pub fn get<'sc>( pub fn get<'s>(&mut self, scope: &mut HandleScope<'s>) -> Local<'s, Value> {
&mut self,
scope: &mut impl ToLocal<'sc>,
) -> Local<'sc, Value> {
unsafe { scope.cast_local(|_| v8__ReturnValue__Get(self)) }.unwrap() unsafe { scope.cast_local(|_| v8__ReturnValue__Get(self)) }.unwrap()
} }
} }
@ -113,11 +108,6 @@ pub struct FunctionCallbackInfo {
length: int, length: int,
} }
unsafe impl<'s> ScopeDefinition<'s> for FunctionCallbackInfo {
type Args = ();
unsafe fn enter_scope(_: *mut Self, _: Self::Args) {}
}
/// The information passed to a property callback about the context /// The information passed to a property callback about the context
/// of the property access. /// of the property access.
#[repr(C)] #[repr(C)]
@ -127,11 +117,6 @@ pub struct PropertyCallbackInfo {
args: *mut Opaque, args: *mut Opaque,
} }
unsafe impl<'s> ScopeDefinition<'s> for PropertyCallbackInfo {
type Args = ();
unsafe fn enter_scope(_: *mut Self, _: Self::Args) {}
}
pub struct FunctionCallbackArguments<'s> { pub struct FunctionCallbackArguments<'s> {
info: *const FunctionCallbackInfo, info: *const FunctionCallbackInfo,
phantom: PhantomData<&'s ()>, phantom: PhantomData<&'s ()>,
@ -239,13 +224,11 @@ pub type FunctionCallback = extern "C" fn(*const FunctionCallbackInfo);
impl<F> MapFnFrom<F> for FunctionCallback impl<F> MapFnFrom<F> for FunctionCallback
where where
F: UnitType F: UnitType + Fn(&mut HandleScope, FunctionCallbackArguments, ReturnValue),
+ Fn(FunctionCallbackScope, FunctionCallbackArguments, ReturnValue),
{ {
fn mapping() -> Self { fn mapping() -> Self {
let f = |info: *const FunctionCallbackInfo| { let f = |info: *const FunctionCallbackInfo| {
let scope: FunctionCallbackScope = let scope = &mut unsafe { CallbackScope::new(&*info) };
&mut crate::scope::Entered::new_root(info as *mut FunctionCallbackInfo);
let args = FunctionCallbackArguments::from_function_callback_info(info); let args = FunctionCallbackArguments::from_function_callback_info(info);
let rv = ReturnValue::from_function_callback_info(info); let rv = ReturnValue::from_function_callback_info(info);
(F::get())(scope, args, rv); (F::get())(scope, args, rv);
@ -262,17 +245,11 @@ pub type AccessorNameGetterCallback<'s> =
impl<F> MapFnFrom<F> for AccessorNameGetterCallback<'_> impl<F> MapFnFrom<F> for AccessorNameGetterCallback<'_>
where where
F: UnitType F: UnitType
+ Fn( + Fn(&mut HandleScope, Local<Name>, PropertyCallbackArguments, ReturnValue),
PropertyCallbackScope,
Local<Name>,
PropertyCallbackArguments,
ReturnValue,
),
{ {
fn mapping() -> Self { fn mapping() -> Self {
let f = |key: Local<Name>, info: *const PropertyCallbackInfo| { let f = |key: Local<Name>, info: *const PropertyCallbackInfo| {
let scope: PropertyCallbackScope = let scope = &mut unsafe { CallbackScope::new(&*info) };
&mut crate::scope::Entered::new_root(info as *mut PropertyCallbackInfo);
let args = PropertyCallbackArguments::from_property_callback_info(info); let args = PropertyCallbackArguments::from_property_callback_info(info);
let rv = ReturnValue::from_property_callback_info(info); let rv = ReturnValue::from_property_callback_info(info);
(F::get())(scope, key, args, rv); (F::get())(scope, key, args, rv);
@ -285,11 +262,11 @@ impl Function {
// TODO: add remaining arguments from C++ // TODO: add remaining arguments from C++
/// Create a function in the current execution context /// Create a function in the current execution context
/// for a given FunctionCallback. /// for a given FunctionCallback.
pub fn new<'sc>( pub fn new<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
context: Local<Context>, context: Local<Context>,
callback: impl MapFnTo<FunctionCallback>, callback: impl MapFnTo<FunctionCallback>,
) -> Option<Local<'sc, Function>> { ) -> Option<Local<'s, Function>> {
unsafe { unsafe {
scope.cast_local(|_| v8__Function__New(&*context, callback.map_fn_to())) scope.cast_local(|_| v8__Function__New(&*context, callback.map_fn_to()))
} }
@ -297,12 +274,12 @@ impl Function {
/// Create a function in the current execution context /// Create a function in the current execution context
/// for a given FunctionCallback and associated data. /// for a given FunctionCallback and associated data.
pub fn new_with_data<'sc>( pub fn new_with_data<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
context: Local<Context>, context: Local<Context>,
data: Local<Value>, data: Local<Value>,
callback: impl MapFnTo<FunctionCallback>, callback: impl MapFnTo<FunctionCallback>,
) -> Option<Local<'sc, Function>> { ) -> Option<Local<'s, Function>> {
unsafe { unsafe {
scope.cast_local(|_| { scope.cast_local(|_| {
v8__Function__NewWithData(&*context, callback.map_fn_to(), &*data) v8__Function__NewWithData(&*context, callback.map_fn_to(), &*data)
@ -310,13 +287,13 @@ impl Function {
} }
} }
pub fn call<'sc>( pub fn call<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
context: Local<Context>, context: Local<Context>,
recv: Local<Value>, recv: Local<Value>,
args: &[Local<Value>], args: &[Local<Value>],
) -> Option<Local<'sc, Value>> { ) -> Option<Local<'s, Value>> {
let args = Local::slice_into_raw(args); let args = Local::slice_into_raw(args);
let argc = int::try_from(args.len()).unwrap(); let argc = int::try_from(args.len()).unwrap();
let argv = args.as_ptr(); let argv = args.as_ptr();

View file

@ -2,11 +2,10 @@ use std::mem::transmute;
use std::ptr::NonNull; use std::ptr::NonNull;
use crate::Data; use crate::Data;
use crate::InIsolate; use crate::HandleScope;
use crate::Isolate; use crate::Isolate;
use crate::IsolateHandle; use crate::IsolateHandle;
use crate::Local; use crate::Local;
use crate::ToLocal;
extern "C" { extern "C" {
fn v8__Local__New(isolate: *mut Isolate, other: *const Data) -> *const Data; fn v8__Local__New(isolate: *mut Isolate, other: *const Data) -> *const Data;
@ -50,16 +49,12 @@ impl<T> Global<T> {
/// Construct a new Global from an existing handle. When the existing handle /// Construct a new Global from an existing handle. When the existing handle
/// is non-empty, a new storage cell is created pointing to the same object, /// is non-empty, a new storage cell is created pointing to the same object,
/// and no flags are set. /// and no flags are set.
pub fn new_from( pub fn new_from(scope: &mut Isolate, other: impl AnyHandle<T>) -> Self {
scope: &mut impl InIsolate, let other_value = other.read(scope);
other: impl AnyHandle<T>,
) -> Self {
let isolate = scope.isolate();
let other_value = other.read(isolate);
Self { Self {
value: other_value value: other_value
.map(|v| unsafe { transmute(v8__Global__New(isolate, transmute(v))) }), .map(|v| unsafe { transmute(v8__Global__New(scope, transmute(v))) }),
isolate_handle: other_value.map(|_| isolate.thread_safe_handle()), isolate_handle: other_value.map(|_| scope.thread_safe_handle()),
} }
} }
@ -70,25 +65,25 @@ impl<T> Global<T> {
} }
/// Construct a Local<T> from this global handle. /// Construct a Local<T> from this global handle.
pub fn get<'sc>( pub fn get<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s, ()>,
) -> Option<Local<'sc, T>> { ) -> Option<Local<'s, T>> {
self.check_isolate(scope.isolate()); self.check_isolate(scope);
self self
.value .value
.map(|g| g.as_ptr() as *const Data) .map(|g| g.as_ptr() as *const Data)
.and_then(|g| unsafe { .and_then(|g| unsafe {
scope.cast_local(|scope| v8__Local__New(scope.isolate(), g) as *const T) scope
.cast_local(|sd| v8__Local__New(sd.get_isolate_ptr(), g) as *const T)
}) })
} }
/// If non-empty, destroy the underlying storage cell /// If non-empty, destroy the underlying storage cell
/// and create a new one with the contents of other if other is non empty. /// and create a new one with the contents of other if other is non empty.
pub fn set(&mut self, scope: &mut impl InIsolate, other: impl AnyHandle<T>) { pub fn set(&mut self, scope: &mut Isolate, other: impl AnyHandle<T>) {
let isolate = scope.isolate(); self.check_isolate(scope);
self.check_isolate(isolate); let other_value = other.read(scope);
let other_value = other.read(isolate);
match (&mut self.value, &other_value) { match (&mut self.value, &other_value) {
(None, None) => {} (None, None) => {}
(target, None) => unsafe { (target, None) => unsafe {
@ -99,17 +94,17 @@ impl<T> Global<T> {
(target, source) => unsafe { (target, source) => unsafe {
v8__Global__Reset__2( v8__Global__Reset__2(
&mut *(target as *mut Option<NonNull<T>> as *mut *const Data), &mut *(target as *mut Option<NonNull<T>> as *mut *const Data),
isolate, scope,
&*(source as *const Option<NonNull<T>> as *const *const Data), &*(source as *const Option<NonNull<T>> as *const *const Data),
) )
}, },
} }
self.isolate_handle = other_value.map(|_| isolate.thread_safe_handle()); self.isolate_handle = other_value.map(|_| scope.thread_safe_handle());
} }
/// If non-empty, destroy the underlying storage cell /// If non-empty, destroy the underlying storage cell
/// IsEmpty() will return true after this call. /// IsEmpty() will return true after this call.
pub fn reset(&mut self, scope: &mut impl InIsolate) { pub fn reset(&mut self, scope: &mut Isolate) {
self.set(scope, None); self.set(scope, None);
} }
@ -164,19 +159,19 @@ pub trait AnyHandle<T> {
fn read(self, isolate: &mut Isolate) -> Option<NonNull<T>>; fn read(self, isolate: &mut Isolate) -> Option<NonNull<T>>;
} }
impl<'sc, T> AnyHandle<T> for Local<'sc, T> { impl<'s, T> AnyHandle<T> for Local<'s, T> {
fn read(self, _isolate: &mut Isolate) -> Option<NonNull<T>> { fn read(self, _isolate: &mut Isolate) -> Option<NonNull<T>> {
Some(self.as_non_null()) Some(self.as_non_null())
} }
} }
impl<'sc, T> AnyHandle<T> for Option<Local<'sc, T>> { impl<'s, T> AnyHandle<T> for Option<Local<'s, T>> {
fn read(self, _isolate: &mut Isolate) -> Option<NonNull<T>> { fn read(self, _isolate: &mut Isolate) -> Option<NonNull<T>> {
self.map(|local| local.as_non_null()) self.map(|local| local.as_non_null())
} }
} }
impl<'sc, T> AnyHandle<T> for &Global<T> { impl<'s, T> AnyHandle<T> for &Global<T> {
fn read(self, isolate: &mut Isolate) -> Option<NonNull<T>> { fn read(self, isolate: &mut Isolate) -> Option<NonNull<T>> {
self.check_isolate(isolate); self.check_isolate(isolate);
self.value self.value

View file

@ -1,102 +0,0 @@
// Copyright 2019-2020 the Deno authors. All rights reserved. MIT license.
use crate::isolate::Isolate;
use crate::scope::Scope;
use crate::scope::ScopeDefinition;
use crate::scope_traits::ToLocalOrReturnsLocal;
use crate::Data;
use crate::InIsolate;
use crate::Local;
extern "C" {
fn v8__HandleScope__CONSTRUCT(buf: *mut HandleScope, isolate: *mut Isolate);
fn v8__HandleScope__DESTRUCT(this: *mut HandleScope);
fn v8__EscapableHandleScope__CONSTRUCT(
buf: *mut EscapableHandleScope,
isolate: *mut Isolate,
);
fn v8__EscapableHandleScope__DESTRUCT(this: *mut EscapableHandleScope);
fn v8__EscapableHandleScope__Escape(
this: *mut EscapableHandleScope,
value: *const Data,
) -> *const Data;
}
/// A stack-allocated class that governs a number of local handles.
/// After a handle scope has been created, all local handles will be
/// allocated within that handle scope until either the handle scope is
/// deleted or another handle scope is created. If there is already a
/// handle scope and a new one is created, all allocations will take
/// place in the new handle scope until it is deleted. After that,
/// new handles will again be allocated in the original handle scope.
///
/// After the handle scope of a local handle has been deleted the
/// 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.
#[repr(C)]
pub struct HandleScope([usize; 3]);
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)
}
}
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);
}
}
impl Drop for HandleScope {
fn drop(&mut self) {
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.
#[repr(C)]
pub struct EscapableHandleScope([usize; 4]);
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)
}
/// Pushes the value into the previous scope and returns a handle to it.
/// Cannot be called twice.
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 *const Data,
) as *const T)
.unwrap()
}
}
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);
}
}
impl Drop for EscapableHandleScope {
fn drop(&mut self) {
unsafe { v8__EscapableHandleScope__DESTRUCT(self) }
}
}

View file

@ -13,7 +13,6 @@
//! https://github.com/nodejs/node/tree/v13.7.0/src/inspector //! https://github.com/nodejs/node/tree/v13.7.0/src/inspector
//! https://github.com/denoland/deno/blob/v0.38.0/cli/inspector.rs //! https://github.com/denoland/deno/blob/v0.38.0/cli/inspector.rs
use crate::scope_traits::InIsolate;
use crate::support::int; use crate::support::int;
use crate::support::CxxVTable; use crate::support::CxxVTable;
use crate::support::FieldOffset; use crate::support::FieldOffset;
@ -834,7 +833,7 @@ pub struct V8Inspector(Opaque);
impl V8Inspector { impl V8Inspector {
pub fn create<T>( pub fn create<T>(
isolate: &mut impl InIsolate, isolate: &mut Isolate,
client: &mut T, client: &mut T,
) -> UniqueRef<V8Inspector> ) -> UniqueRef<V8Inspector>
where where
@ -842,7 +841,7 @@ impl V8Inspector {
{ {
unsafe { unsafe {
UniqueRef::from_raw(v8_inspector__V8Inspector__create( UniqueRef::from_raw(v8_inspector__V8Inspector__create(
isolate.isolate(), isolate,
client.as_client_mut(), client.as_client_mut(),
)) ))
} }

View file

@ -2,10 +2,10 @@
use crate::isolate_create_params::raw; use crate::isolate_create_params::raw;
use crate::isolate_create_params::CreateParams; use crate::isolate_create_params::CreateParams;
use crate::promise::PromiseRejectMessage; use crate::promise::PromiseRejectMessage;
use crate::scope::data::ScopeData;
use crate::support::Opaque; use crate::support::Opaque;
use crate::Context; use crate::Context;
use crate::Function; use crate::Function;
use crate::InIsolate;
use crate::Local; use crate::Local;
use crate::Message; use crate::Message;
use crate::Module; use crate::Module;
@ -103,10 +103,6 @@ extern "C" {
callback: InterruptCallback, callback: InterruptCallback,
data: *mut c_void, data: *mut c_void,
); );
fn v8__Isolate__ThrowException(
isolate: *mut Isolate,
exception: *const Value,
) -> *const Value;
fn v8__Isolate__TerminateExecution(isolate: *const Isolate); fn v8__Isolate__TerminateExecution(isolate: *const Isolate);
fn v8__Isolate__IsExecutionTerminating(isolate: *const Isolate) -> bool; fn v8__Isolate__IsExecutionTerminating(isolate: *const Isolate) -> bool;
fn v8__Isolate__CancelTerminateExecution(isolate: *const Isolate); fn v8__Isolate__CancelTerminateExecution(isolate: *const Isolate);
@ -133,6 +129,10 @@ extern "C" {
pub struct Isolate(Opaque); pub struct Isolate(Opaque);
impl Isolate { impl Isolate {
const ANNEX_SLOT: u32 = 0;
const CURRENT_SCOPE_DATA_SLOT: u32 = 1;
const INTERNAL_SLOT_COUNT: u32 = 2;
/// Creates a new isolate. Does not change the currently entered /// Creates a new isolate. Does not change the currently entered
/// isolate. /// isolate.
/// ///
@ -146,6 +146,7 @@ impl Isolate {
let (raw_create_params, create_param_allocations) = params.finalize(); let (raw_create_params, create_param_allocations) = params.finalize();
let cxx_isolate = unsafe { v8__Isolate__New(&raw_create_params) }; let cxx_isolate = unsafe { v8__Isolate__New(&raw_create_params) };
let mut owned_isolate = OwnedIsolate::new(cxx_isolate); let mut owned_isolate = OwnedIsolate::new(cxx_isolate);
ScopeData::new_root(&mut owned_isolate);
owned_isolate.create_annex(create_param_allocations); owned_isolate.create_annex(create_param_allocations);
owned_isolate owned_isolate
} }
@ -165,18 +166,23 @@ impl Isolate {
) { ) {
let annex_arc = Arc::new(IsolateAnnex::new(self, create_param_allocations)); let annex_arc = Arc::new(IsolateAnnex::new(self, create_param_allocations));
let annex_ptr = Arc::into_raw(annex_arc); let annex_ptr = Arc::into_raw(annex_arc);
unsafe { assert!(v8__Isolate__GetData(self, 0).is_null()) }; unsafe {
unsafe { v8__Isolate__SetData(self, 0, annex_ptr as *mut c_void) }; assert!(v8__Isolate__GetData(self, Self::ANNEX_SLOT).is_null());
v8__Isolate__SetData(self, Self::ANNEX_SLOT, annex_ptr as *mut c_void);
};
} }
fn get_annex(&self) -> &IsolateAnnex { fn get_annex(&self) -> &IsolateAnnex {
unsafe { unsafe {
&*(v8__Isolate__GetData(self, 0) as *const _ as *const IsolateAnnex) &*(v8__Isolate__GetData(self, Self::ANNEX_SLOT) as *const _
as *const IsolateAnnex)
} }
} }
fn get_annex_mut(&mut self) -> &mut IsolateAnnex { fn get_annex_mut(&mut self) -> &mut IsolateAnnex {
unsafe { &mut *(v8__Isolate__GetData(self, 0) as *mut IsolateAnnex) } unsafe {
&mut *(v8__Isolate__GetData(self, Self::ANNEX_SLOT) as *mut IsolateAnnex)
}
} }
fn get_annex_arc(&self) -> Arc<IsolateAnnex> { fn get_annex_arc(&self) -> Arc<IsolateAnnex> {
@ -186,22 +192,45 @@ impl Isolate {
annex_arc annex_arc
} }
/// Associate embedder-specific data with the isolate. |slot| has to be /// Associate embedder-specific data with the isolate. `slot` has to be
/// between 0 and GetNumberOfDataSlots() - 1. /// between 0 and `Isolate::get_number_of_data_slots()`.
unsafe fn set_data(&mut self, slot: u32, ptr: *mut c_void) { unsafe fn set_data(&mut self, slot: u32, ptr: *mut c_void) {
v8__Isolate__SetData(self, slot + 1, ptr) v8__Isolate__SetData(self, slot + Self::INTERNAL_SLOT_COUNT, ptr)
} }
/// Retrieve embedder-specific data from the isolate. /// Retrieve embedder-specific data from the isolate.
/// Returns NULL if SetData has never been called for the given |slot|. /// Returns NULL if SetData has never been called for the given `slot`.
fn get_data(&self, slot: u32) -> *mut c_void { fn get_data(&self, slot: u32) -> *mut c_void {
unsafe { v8__Isolate__GetData(self, slot + 1) } unsafe { v8__Isolate__GetData(self, slot + Self::INTERNAL_SLOT_COUNT) }
} }
/// Returns the maximum number of available embedder data slots. Valid slots /// Returns the maximum number of available embedder data slots. Valid slots
/// are in the range of 0 - GetNumberOfDataSlots() - 1. /// are in the range of 0 - `Isolate::get_number_of_data_slots() - 1`.
fn get_number_of_data_slots(&self) -> u32 { fn get_number_of_data_slots(&self) -> u32 {
unsafe { v8__Isolate__GetNumberOfDataSlots(self) - 1 } unsafe {
v8__Isolate__GetNumberOfDataSlots(self) - Self::INTERNAL_SLOT_COUNT
}
}
/// Returns a pointer to the `ScopeData` struct for the current scope.
pub(crate) fn get_current_scope_data(&self) -> Option<NonNull<ScopeData>> {
let scope_data_ptr =
unsafe { v8__Isolate__GetData(self, Self::CURRENT_SCOPE_DATA_SLOT) };
NonNull::new(scope_data_ptr).map(NonNull::cast)
}
/// Updates the slot that stores a `ScopeData` pointer for the current scope.
pub(crate) fn set_current_scope_data(
&mut self,
scope_data: Option<NonNull<ScopeData>>,
) {
let scope_data_ptr = scope_data
.map(NonNull::cast)
.map(NonNull::as_ptr)
.unwrap_or_else(null_mut);
unsafe {
v8__Isolate__SetData(self, Self::CURRENT_SCOPE_DATA_SLOT, scope_data_ptr)
};
} }
/// Get mutable reference to embedder data. /// Get mutable reference to embedder data.
@ -247,7 +276,7 @@ impl Isolate {
/// Sets this isolate as the entered one for the current thread. /// Sets this isolate as the entered one for the current thread.
/// Saves the previously entered one (if any), so that it can be /// Saves the previously entered one (if any), so that it can be
/// restored when exiting. Re-entering an isolate is allowed. /// restored when exiting. Re-entering an isolate is allowed.
pub(crate) fn enter(&mut self) { pub(crate) fn enter_isolate(&mut self) {
unsafe { v8__Isolate__Enter(self) } unsafe { v8__Isolate__Enter(self) }
} }
@ -256,7 +285,7 @@ impl Isolate {
/// entered more than once. /// entered more than once.
/// ///
/// Requires: self == Isolate::GetCurrent(). /// Requires: self == Isolate::GetCurrent().
pub(crate) fn exit(&mut self) { pub(crate) fn exit_isolate(&mut self) {
unsafe { v8__Isolate__Exit(self) } unsafe { v8__Isolate__Exit(self) }
} }
@ -316,24 +345,6 @@ impl Isolate {
} }
} }
/// Schedules an exception to be thrown when returning to JavaScript. When an
/// exception has been scheduled it is illegal to invoke any JavaScript
/// operation; the caller must return immediately and only after the exception
/// has been handled does it become legal to invoke JavaScript operations.
///
/// This function always returns the `undefined` value.
pub fn throw_exception(
&mut self,
exception: Local<Value>,
) -> Local<'_, Value> {
let result = unsafe {
Local::from_raw(v8__Isolate__ThrowException(self, &*exception))
}
.unwrap();
debug_assert!(result.is_undefined());
result
}
/// Runs the default MicrotaskQueue until it gets empty. /// Runs the default MicrotaskQueue until it gets empty.
/// Any exceptions thrown by microtask callbacks are swallowed. /// Any exceptions thrown by microtask callbacks are swallowed.
pub fn run_microtasks(&mut self) { pub fn run_microtasks(&mut self) {
@ -348,11 +359,13 @@ impl Isolate {
/// Disposes the isolate. The isolate must not be entered by any /// Disposes the isolate. The isolate must not be entered by any
/// thread to be disposable. /// thread to be disposable.
unsafe fn dispose(&mut self) { unsafe fn dispose(&mut self) {
let annex = self.get_annex_mut(); // Drop the scope stack.
ScopeData::drop_root(self);
// Set the `isolate` pointer inside the annex struct to null, so any // Set the `isolate` pointer inside the annex struct to null, so any
// IsolateHandle that outlives the isolate will know that it can't call // IsolateHandle that outlives the isolate will know that it can't call
// methods on the isolate. // methods on the isolate.
let annex = self.get_annex_mut();
{ {
let _lock = annex.isolate_mutex.lock().unwrap(); let _lock = annex.isolate_mutex.lock().unwrap();
annex.isolate = null_mut(); annex.isolate = null_mut();
@ -548,12 +561,6 @@ impl OwnedIsolate {
} }
} }
impl InIsolate for OwnedIsolate {
fn isolate(&mut self) -> &mut Isolate {
self.deref_mut()
}
}
impl Drop for OwnedIsolate { impl Drop for OwnedIsolate {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { self.cxx_isolate.as_mut().dispose() } unsafe { self.cxx_isolate.as_mut().dispose() }

View file

@ -1,9 +1,9 @@
// Copyright 2019-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2019-2020 the Deno authors. All rights reserved. MIT license.
//! A JSON Parser and Stringifier. //! A JSON Parser and Stringifier.
use crate::Context; use crate::Context;
use crate::HandleScope;
use crate::Local; use crate::Local;
use crate::String; use crate::String;
use crate::ToLocal;
use crate::Value; use crate::Value;
extern "C" { extern "C" {
@ -19,20 +19,20 @@ extern "C" {
/// Tries to parse the string `json_string` and returns it as value if /// Tries to parse the string `json_string` and returns it as value if
/// successful. /// successful.
pub fn parse<'sc>( pub fn parse<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
context: Local<'_, Context>, context: Local<'_, Context>,
json_string: Local<'_, String>, json_string: Local<'_, String>,
) -> Option<Local<'sc, Value>> { ) -> Option<Local<'s, Value>> {
unsafe { scope.cast_local(|_| v8__JSON__Parse(&*context, &*json_string)) } unsafe { scope.cast_local(|_| v8__JSON__Parse(&*context, &*json_string)) }
} }
/// Tries to stringify the JSON-serializable object `json_object` and returns /// Tries to stringify the JSON-serializable object `json_object` and returns
/// it as string if successful. /// it as string if successful.
pub fn stringify<'sc>( pub fn stringify<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
context: Local<'sc, Context>, context: Local<'s, Context>,
json_object: Local<'sc, Value>, json_object: Local<'s, Value>,
) -> Option<Local<'sc, String>> { ) -> Option<Local<'s, String>> {
unsafe { scope.cast_local(|_| v8__JSON__Stringify(&*context, &*json_object)) } unsafe { scope.cast_local(|_| v8__JSON__Stringify(&*context, &*json_object)) }
} }

View file

@ -9,14 +9,11 @@
//! v8::V8::initialize_platform(platform); //! v8::V8::initialize_platform(platform);
//! v8::V8::initialize(); //! v8::V8::initialize();
//! //!
//! let mut isolate = v8::Isolate::new(Default::default()); //! let isolate = &mut v8::Isolate::new(Default::default());
//!
//! let mut handle_scope = v8::HandleScope::new(&mut isolate);
//! let scope = handle_scope.enter();
//! //!
//! let scope = &mut v8::HandleScope::new(isolate);
//! let context = v8::Context::new(scope); //! let context = v8::Context::new(scope);
//! let mut context_scope = v8::ContextScope::new(scope, context); //! let scope = &mut v8::ContextScope::new(scope, context);
//! let scope = context_scope.enter();
//! //!
//! let code = v8::String::new(scope, "'Hello' + ' World!'").unwrap(); //! let code = v8::String::new(scope, "'Hello' + ' World!'").unwrap();
//! println!("javascript code: {}", code.to_rust_string_lossy(scope)); //! println!("javascript code: {}", code.to_rust_string_lossy(scope));
@ -26,44 +23,6 @@
//! let result = result.to_string(scope).unwrap(); //! let result = result.to_string(scope).unwrap();
//! println!("result: {}", result.to_rust_string_lossy(scope)); //! println!("result: {}", result.to_rust_string_lossy(scope));
//! ``` //! ```
//!
//! # Design of Scopes
//!
//! Although the end is in sight, the design is still a bit in flux.
//!
//! The general idea is that the various scope classes mediate access to the v8
//! Isolate and the various items on its heap (Local/Global handles,
//! return/escape slots, etc.). At any point in time there exists only one scope
//! object that is directly accessible, which guarantees that all interactions
//! with the Isolate are safe.
//!
//! A Scope as such is not a trait (there is currently an internal
//! ScopeDefinition trait but that's only there to make implementation easier).
//!
//! Rather, there are a number of traits that are implemented for the scopes
//! they're applicable to, you've probably seen most of them already. The
//! InIsolate which gives access to &mut Isolate is implemented for all scopes,
//! ToLocal (I might rename that) is implemented for all Scopes in which new
//! Local handles can be created and it sets the appropriate lifetime on them.
//!
//! Furthermore, many callbacks will receive receive an appropriate Scope object
//! as their first argument, which 'encodes' the the state the isolate is in
//! when the callback is called. E.g. a FunctionCallbackScope implements
//! InIsolate + and ToLocal (it acts as a HandleScope).
//! HostImportModuleDynamicallyScope would also implement InIsolate plus
//! EscapeLocal (it doesn't act like a HandleScope, but it lets you safely
//! escape one MaybeLocal which is returned to the caller).
//!
//! In a nutshell, that's it.
//!
//! Open TODOs are:
//! - Add these automatic scopes to more callbacks (in progress) and get rid of
//! the necessity to import the MapFnTo trait.
//! - Fully integrate TryCatch blocks into the scope system (currently a
//! TryCatch works like a scope internally but it's not integrated).
//! - Add methods to some on some of the scopes like get_context() for
//! ContextScope.
//! - Rename/reorganize/document.
#![allow(clippy::missing_safety_doc)] #![allow(clippy::missing_safety_doc)]
#![allow(dead_code)] #![allow(dead_code)]
@ -82,7 +41,6 @@ mod exception;
mod external_references; mod external_references;
mod function; mod function;
mod global; mod global;
mod handle_scope;
mod isolate; mod isolate;
mod isolate_create_params; mod isolate_create_params;
mod local; mod local;
@ -95,7 +53,7 @@ mod primitives;
mod promise; mod promise;
mod property_attribute; mod property_attribute;
mod proxy; mod proxy;
mod scope_traits; mod scope;
mod script; mod script;
mod script_or_module; mod script_or_module;
mod shared_array_buffer; mod shared_array_buffer;
@ -109,7 +67,6 @@ mod value;
pub mod inspector; pub mod inspector;
pub mod json; pub mod json;
pub mod scope;
pub mod script_compiler; pub mod script_compiler;
// This module is intentionally named "V8" rather than "v8" to match the // This module is intentionally named "V8" rather than "v8" to match the
// C++ namespace "v8::V8". // C++ namespace "v8::V8".
@ -123,8 +80,6 @@ pub use external_references::ExternalReference;
pub use external_references::ExternalReferences; pub use external_references::ExternalReferences;
pub use function::*; pub use function::*;
pub use global::Global; pub use global::Global;
pub use handle_scope::EscapableHandleScope;
pub use handle_scope::HandleScope;
pub use isolate::HostImportModuleDynamicallyCallback; pub use isolate::HostImportModuleDynamicallyCallback;
pub use isolate::HostInitializeImportMetaObjectCallback; pub use isolate::HostInitializeImportMetaObjectCallback;
pub use isolate::Isolate; pub use isolate::Isolate;
@ -148,10 +103,8 @@ pub use property_attribute::*;
pub use proxy::*; pub use proxy::*;
pub use scope::CallbackScope; pub use scope::CallbackScope;
pub use scope::ContextScope; pub use scope::ContextScope;
pub use scope::FunctionCallbackScope; pub use scope::EscapableHandleScope;
pub use scope::PropertyCallbackScope; pub use scope::HandleScope;
pub use scope::Scope;
pub use scope_traits::*;
pub use script::ScriptOrigin; pub use script::ScriptOrigin;
pub use snapshot::FunctionCodeHandling; pub use snapshot::FunctionCodeHandling;
pub use snapshot::SnapshotCreator; pub use snapshot::SnapshotCreator;

View file

@ -38,51 +38,51 @@ use std::ptr::NonNull;
/// never empty. In situations where empty handles are needed, use /// never empty. In situations where empty handles are needed, use
/// Option<Local>. /// Option<Local>.
#[repr(C)] #[repr(C)]
pub struct Local<'sc, T>(NonNull<T>, PhantomData<&'sc ()>); pub struct Local<'s, T>(NonNull<T>, PhantomData<&'s ()>);
impl<'sc, T> Copy for Local<'sc, T> {} impl<'s, T> Copy for Local<'s, T> {}
impl<'sc, T> Clone for Local<'sc, T> { impl<'s, T> Clone for Local<'s, T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
*self *self
} }
} }
impl<'sc, T> Local<'sc, T> { impl<'s, T> Local<'s, T> {
/// Create a local handle by downcasting from one of its super types. /// Create a local handle by downcasting from one of its super types.
/// This function is unsafe because the cast is unchecked. /// This function is unsafe because the cast is unchecked.
pub unsafe fn cast<A>(other: Local<'sc, A>) -> Self pub unsafe fn cast<A>(other: Local<'s, A>) -> Self
where where
Local<'sc, A>: From<Self>, Local<'s, A>: From<Self>,
{ {
transmute(other) transmute(other)
} }
pub(crate) unsafe fn from_raw(ptr: *const T) -> Option<Self> { pub(crate) unsafe fn from_raw(ptr: *const T) -> Option<Self> {
Some(Self(NonNull::new(ptr as *mut _)?, PhantomData)) NonNull::new(ptr as *mut _).map(|nn| Self::from_non_null(nn))
}
pub(crate) unsafe fn from_non_null(nn: NonNull<T>) -> Self {
Self(nn, PhantomData)
} }
pub(crate) fn as_non_null(self) -> NonNull<T> { pub(crate) fn as_non_null(self) -> NonNull<T> {
self.0 self.0
} }
pub(crate) fn as_ptr(self) -> *const T {
self.0.as_ptr()
}
pub(crate) fn slice_into_raw(slice: &[Self]) -> &[*const T] { pub(crate) fn slice_into_raw(slice: &[Self]) -> &[*const T] {
unsafe { &*(slice as *const [Self] as *const [*const T]) } unsafe { &*(slice as *const [Self] as *const [*const T]) }
} }
} }
impl<'sc, T> Deref for Local<'sc, T> { impl<'s, T> Deref for Local<'s, T> {
type Target = T; type Target = T;
fn deref(&self) -> &T { fn deref(&self) -> &T {
unsafe { self.0.as_ref() } unsafe { self.0.as_ref() }
} }
} }
impl<'sc, T> DerefMut for Local<'sc, T> { impl<'s, T> DerefMut for Local<'s, T> {
fn deref_mut(&mut self) -> &mut T { fn deref_mut(&mut self) -> &mut T {
unsafe { self.0.as_mut() } unsafe { self.0.as_mut() }
} }

View file

@ -9,10 +9,10 @@ use crate::support::MaybeBool;
use crate::support::ToCFn; use crate::support::ToCFn;
use crate::support::UnitType; use crate::support::UnitType;
use crate::Context; use crate::Context;
use crate::HandleScope;
use crate::Local; use crate::Local;
use crate::Module; use crate::Module;
use crate::String; use crate::String;
use crate::ToLocal;
use crate::Value; use crate::Value;
/// Called during Module::instantiate_module. Provided with arguments: /// Called during Module::instantiate_module. Provided with arguments:
@ -221,11 +221,11 @@ impl Module {
/// kErrored and propagate the thrown exception (which is then also available /// kErrored and propagate the thrown exception (which is then also available
/// via |GetException|). /// via |GetException|).
#[must_use] #[must_use]
pub fn evaluate<'sc>( pub fn evaluate<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
context: Local<Context>, context: Local<Context>,
) -> Option<Local<'sc, Value>> { ) -> Option<Local<'s, Value>> {
unsafe { scope.cast_local(|_| v8__Module__Evaluate(&*self, &*context)) } unsafe { scope.cast_local(|_| v8__Module__Evaluate(&*self, &*context)) }
} }
} }

View file

@ -1,8 +1,8 @@
use crate::isolate::Isolate; use crate::isolate::Isolate;
use crate::HandleScope;
use crate::Integer; use crate::Integer;
use crate::Local; use crate::Local;
use crate::Number; use crate::Number;
use crate::ToLocal;
extern "C" { extern "C" {
fn v8__Number__New(isolate: *mut Isolate, value: f64) -> *const Number; fn v8__Number__New(isolate: *mut Isolate, value: f64) -> *const Number;
@ -16,12 +16,14 @@ extern "C" {
} }
impl Number { impl Number {
pub fn new<'sc>( pub fn new<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s, ()>,
value: f64, value: f64,
) -> Local<'sc, Number> { ) -> Local<'s, Number> {
unsafe { scope.cast_local(|scope| v8__Number__New(scope.isolate(), value)) } unsafe {
.unwrap() scope.cast_local(|sd| v8__Number__New(sd.get_isolate_ptr(), value))
}
.unwrap()
} }
pub fn value(&self) -> f64 { pub fn value(&self) -> f64 {
@ -30,23 +32,23 @@ impl Number {
} }
impl Integer { impl Integer {
pub fn new<'sc>( pub fn new<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s, ()>,
value: i32, value: i32,
) -> Local<'sc, Integer> { ) -> Local<'s, Integer> {
unsafe { unsafe {
scope.cast_local(|scope| v8__Integer__New(scope.isolate(), value)) scope.cast_local(|sd| v8__Integer__New(sd.get_isolate_ptr(), value))
} }
.unwrap() .unwrap()
} }
pub fn new_from_unsigned<'sc>( pub fn new_from_unsigned<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s, ()>,
value: u32, value: u32,
) -> Local<'sc, Integer> { ) -> Local<'s, Integer> {
unsafe { unsafe {
scope.cast_local(|scope| { scope.cast_local(|sd| {
v8__Integer__NewFromUnsigned(scope.isolate(), value) v8__Integer__NewFromUnsigned(sd.get_isolate_ptr(), value)
}) })
} }
.unwrap() .unwrap()

View file

@ -5,12 +5,12 @@ use crate::support::MaybeBool;
use crate::AccessorNameGetterCallback; use crate::AccessorNameGetterCallback;
use crate::Array; use crate::Array;
use crate::Context; use crate::Context;
use crate::HandleScope;
use crate::Local; use crate::Local;
use crate::Map; use crate::Map;
use crate::Name; use crate::Name;
use crate::Object; use crate::Object;
use crate::PropertyAttribute; use crate::PropertyAttribute;
use crate::ToLocal;
use crate::Value; use crate::Value;
extern "C" { extern "C" {
@ -93,8 +93,8 @@ extern "C" {
impl Object { impl Object {
/// Creates an empty object. /// Creates an empty object.
pub fn new<'sc>(scope: &mut impl ToLocal<'sc>) -> Local<'sc, Object> { pub fn new<'s>(scope: &mut HandleScope<'s>) -> Local<'s, Object> {
unsafe { scope.cast_local(|scope| v8__Object__New(scope.isolate())) } unsafe { scope.cast_local(|sd| v8__Object__New(sd.get_isolate_ptr())) }
.unwrap() .unwrap()
} }
@ -103,19 +103,19 @@ impl Object {
/// the newly created object won't have a prototype at all). This is similar /// the newly created object won't have a prototype at all). This is similar
/// to Object.create(). All properties will be created as enumerable, /// to Object.create(). All properties will be created as enumerable,
/// configurable and writable properties. /// configurable and writable properties.
pub fn with_prototype_and_properties<'sc>( pub fn with_prototype_and_properties<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
prototype_or_null: Local<'sc, Value>, prototype_or_null: Local<'s, Value>,
names: &[Local<Name>], names: &[Local<Name>],
values: &[Local<Value>], values: &[Local<Value>],
) -> Local<'sc, Object> { ) -> Local<'s, Object> {
assert_eq!(names.len(), values.len()); assert_eq!(names.len(), values.len());
let names = Local::slice_into_raw(names); let names = Local::slice_into_raw(names);
let values = Local::slice_into_raw(values); let values = Local::slice_into_raw(values);
unsafe { unsafe {
scope.cast_local(|scope| { scope.cast_local(|sd| {
v8__Object__New__with_prototype_and_properties( v8__Object__New__with_prototype_and_properties(
scope.isolate(), sd.get_isolate_ptr(),
&*prototype_or_null, &*prototype_or_null,
names.as_ptr(), names.as_ptr(),
values.as_ptr(), values.as_ptr(),
@ -194,21 +194,21 @@ impl Object {
.into() .into()
} }
pub fn get<'a>( pub fn get<'s>(
&self, &self,
scope: &mut impl ToLocal<'a>, scope: &mut HandleScope<'s>,
context: Local<Context>, context: Local<Context>,
key: Local<Value>, key: Local<Value>,
) -> Option<Local<'a, Value>> { ) -> Option<Local<'s, Value>> {
unsafe { scope.cast_local(|_| v8__Object__Get(self, &*context, &*key)) } unsafe { scope.cast_local(|_| v8__Object__Get(self, &*context, &*key)) }
} }
pub fn get_index<'a>( pub fn get_index<'s>(
&self, &self,
scope: &mut impl ToLocal<'a>, scope: &mut HandleScope<'s>,
context: Local<Context>, context: Local<Context>,
index: u32, index: u32,
) -> Option<Local<'a, Value>> { ) -> Option<Local<'s, Value>> {
unsafe { unsafe {
scope.cast_local(|_| v8__Object__GetIndex(self, &*context, index)) scope.cast_local(|_| v8__Object__GetIndex(self, &*context, index))
} }
@ -216,10 +216,10 @@ impl Object {
/// Get the prototype object. This does not skip objects marked to be /// Get the prototype object. This does not skip objects marked to be
/// skipped by proto and it does not consult the security handler. /// skipped by proto and it does not consult the security handler.
pub fn get_prototype<'a>( pub fn get_prototype<'s>(
&self, &self,
scope: &mut impl ToLocal<'a>, scope: &mut HandleScope<'s>,
) -> Option<Local<'a, Value>> { ) -> Option<Local<'s, Value>> {
unsafe { scope.cast_local(|_| v8__Object__GetPrototype(self)) } unsafe { scope.cast_local(|_| v8__Object__GetPrototype(self)) }
} }
@ -246,21 +246,21 @@ impl Object {
} }
/// Returns the context in which the object was created. /// Returns the context in which the object was created.
pub fn creation_context<'a>( pub fn creation_context<'s>(
&self, &self,
scope: &mut impl ToLocal<'a>, scope: &mut HandleScope<'s>,
) -> Local<'a, Context> { ) -> Local<'s, Context> {
unsafe { scope.cast_local(|_| v8__Object__CreationContext(self)) }.unwrap() unsafe { scope.cast_local(|_| v8__Object__CreationContext(self)) }.unwrap()
} }
/// This function has the same functionality as GetPropertyNames but the /// This function has the same functionality as GetPropertyNames but the
/// returned array doesn't contain the names of properties from prototype /// returned array doesn't contain the names of properties from prototype
/// objects. /// objects.
pub fn get_own_property_names<'sc>( pub fn get_own_property_names<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
context: Local<Context>, context: Local<Context>,
) -> Option<Local<'sc, Array>> { ) -> Option<Local<'s, Array>> {
unsafe { unsafe {
scope.cast_local(|_| v8__Object__GetOwnPropertyNames(self, &*context)) scope.cast_local(|_| v8__Object__GetOwnPropertyNames(self, &*context))
} }
@ -270,11 +270,11 @@ impl Object {
/// object, including properties from prototype objects. The array returned by /// object, including properties from prototype objects. The array returned by
/// this method contains the same values as would be enumerated by a for-in /// this method contains the same values as would be enumerated by a for-in
/// statement over this object. /// statement over this object.
pub fn get_property_names<'sc>( pub fn get_property_names<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
context: Local<Context>, context: Local<Context>,
) -> Option<Local<'sc, Array>> { ) -> Option<Local<'s, Array>> {
unsafe { unsafe {
scope.cast_local(|_| v8__Object__GetPropertyNames(self, &*context)) scope.cast_local(|_| v8__Object__GetPropertyNames(self, &*context))
} }
@ -284,28 +284,27 @@ impl Object {
impl Array { impl Array {
/// Creates a JavaScript array with the given length. If the length /// Creates a JavaScript array with the given length. If the length
/// is negative the returned array will have length 0. /// is negative the returned array will have length 0.
pub fn new<'sc>( pub fn new<'s>(scope: &mut HandleScope<'s>, length: i32) -> Local<'s, Array> {
scope: &mut impl ToLocal<'sc>, unsafe {
length: i32, scope.cast_local(|sd| v8__Array__New(sd.get_isolate_ptr(), length))
) -> Local<'sc, Array> { }
unsafe { scope.cast_local(|scope| v8__Array__New(scope.isolate(), length)) } .unwrap()
.unwrap()
} }
/// Creates a JavaScript array out of a Local<Value> array with a known /// Creates a JavaScript array out of a Local<Value> array with a known
/// length. /// length.
pub fn new_with_elements<'sc>( pub fn new_with_elements<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
elements: &[Local<Value>], elements: &[Local<Value>],
) -> Local<'sc, Array> { ) -> Local<'s, Array> {
if elements.is_empty() { if elements.is_empty() {
return Self::new(scope, 0); return Self::new(scope, 0);
} }
let elements = Local::slice_into_raw(elements); let elements = Local::slice_into_raw(elements);
unsafe { unsafe {
scope.cast_local(|scope| { scope.cast_local(|sd| {
v8__Array__New_with_elements( v8__Array__New_with_elements(
scope.isolate(), sd.get_isolate_ptr(),
elements.as_ptr(), elements.as_ptr(),
elements.len(), elements.len(),
) )
@ -325,10 +324,7 @@ impl Map {
} }
/// Returns an array of length size() * 2, where index N is the Nth key and /// Returns an array of length size() * 2, where index N is the Nth key and
/// index N + 1 is the Nth value. /// index N + 1 is the Nth value.
pub fn as_array<'sc>( pub fn as_array<'s>(&self, scope: &mut HandleScope<'s>) -> Local<'s, Array> {
&self,
scope: &mut impl ToLocal<'sc>,
) -> Local<'sc, Array> {
unsafe { scope.cast_local(|_| v8__Map__As__Array(self)) }.unwrap() unsafe { scope.cast_local(|_| v8__Map__As__Array(self)) }.unwrap()
} }
} }

View file

@ -1,10 +1,10 @@
// Copyright 2019-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2019-2020 the Deno authors. All rights reserved. MIT license.
use crate::support::int; use crate::support::int;
use crate::HandleScope;
use crate::Isolate; use crate::Isolate;
use crate::Local; use crate::Local;
use crate::Primitive; use crate::Primitive;
use crate::PrimitiveArray; use crate::PrimitiveArray;
use crate::ToLocal;
extern "C" { extern "C" {
fn v8__PrimitiveArray__New( fn v8__PrimitiveArray__New(
@ -29,13 +29,13 @@ extern "C" {
} }
impl PrimitiveArray { impl PrimitiveArray {
pub fn new<'sc>( pub fn new<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
length: usize, length: usize,
) -> Local<'sc, PrimitiveArray> { ) -> Local<'s, PrimitiveArray> {
unsafe { unsafe {
scope.cast_local(|scope| { scope.cast_local(|sd| {
v8__PrimitiveArray__New(scope.isolate(), length as int) v8__PrimitiveArray__New(sd.get_isolate_ptr(), length as int)
}) })
} }
.unwrap() .unwrap()
@ -45,25 +45,30 @@ impl PrimitiveArray {
unsafe { v8__PrimitiveArray__Length(self) as usize } unsafe { v8__PrimitiveArray__Length(self) as usize }
} }
pub fn set<'sc>( pub fn set<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
index: usize, index: usize,
item: Local<'_, Primitive>, item: Local<'_, Primitive>,
) { ) {
unsafe { unsafe {
v8__PrimitiveArray__Set(self, scope.isolate(), index as int, &*item) v8__PrimitiveArray__Set(
self,
scope.get_isolate_ptr(),
index as int,
&*item,
)
} }
} }
pub fn get<'sc>( pub fn get<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
index: usize, index: usize,
) -> Local<'sc, Primitive> { ) -> Local<'s, Primitive> {
unsafe { unsafe {
scope.cast_local(|scope| { scope.cast_local(|sd| {
v8__PrimitiveArray__Get(self, scope.isolate(), index as int) v8__PrimitiveArray__Get(self, sd.get_isolate_ptr(), index as int)
}) })
} }
.unwrap() .unwrap()

View file

@ -1,8 +1,8 @@
use crate::isolate::Isolate; use crate::isolate::Isolate;
use crate::Boolean; use crate::Boolean;
use crate::HandleScope;
use crate::Local; use crate::Local;
use crate::Primitive; use crate::Primitive;
use crate::ToLocal;
extern "C" { extern "C" {
fn v8__Null(isolate: *mut Isolate) -> *const Primitive; fn v8__Null(isolate: *mut Isolate) -> *const Primitive;
@ -11,21 +11,21 @@ extern "C" {
fn v8__Boolean__New(isolate: *mut Isolate, value: bool) -> *const Boolean; fn v8__Boolean__New(isolate: *mut Isolate, value: bool) -> *const Boolean;
} }
pub fn null<'sc>(scope: &mut impl ToLocal<'sc>) -> Local<'sc, Primitive> { pub fn null<'s>(scope: &mut HandleScope<'s, ()>) -> Local<'s, Primitive> {
unsafe { scope.cast_local(|scope| v8__Null(scope.isolate())) }.unwrap() unsafe { scope.cast_local(|sd| v8__Null(sd.get_isolate_ptr())) }.unwrap()
} }
pub fn undefined<'sc>(scope: &mut impl ToLocal<'sc>) -> Local<'sc, Primitive> { pub fn undefined<'s>(scope: &mut HandleScope<'s, ()>) -> Local<'s, Primitive> {
unsafe { scope.cast_local(|scope| v8__Undefined(scope.isolate())) }.unwrap() unsafe { scope.cast_local(|sd| v8__Undefined(sd.get_isolate_ptr())) }.unwrap()
} }
impl Boolean { impl Boolean {
pub fn new<'sc>( pub fn new<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s, ()>,
value: bool, value: bool,
) -> Local<'sc, Boolean> { ) -> Local<'s, Boolean> {
unsafe { unsafe {
scope.cast_local(|scope| v8__Boolean__New(scope.isolate(), value)) scope.cast_local(|sd| v8__Boolean__New(sd.get_isolate_ptr(), value))
} }
.unwrap() .unwrap()
} }

View file

@ -3,10 +3,10 @@ use std::marker::PhantomData;
use crate::support::MaybeBool; use crate::support::MaybeBool;
use crate::Context; use crate::Context;
use crate::Function; use crate::Function;
use crate::HandleScope;
use crate::Local; use crate::Local;
use crate::Promise; use crate::Promise;
use crate::PromiseResolver; use crate::PromiseResolver;
use crate::ToLocal;
use crate::Value; use crate::Value;
extern "C" { extern "C" {
@ -79,22 +79,19 @@ impl Promise {
/// Returns the content of the [[PromiseResult]] field. The Promise must not /// Returns the content of the [[PromiseResult]] field. The Promise must not
/// be pending. /// be pending.
pub fn result<'sc>( pub fn result<'s>(&self, scope: &mut HandleScope<'s>) -> Local<'s, Value> {
&self,
scope: &mut impl ToLocal<'sc>,
) -> Local<'sc, Value> {
unsafe { scope.cast_local(|_| v8__Promise__Result(&*self)) }.unwrap() unsafe { scope.cast_local(|_| v8__Promise__Result(&*self)) }.unwrap()
} }
/// Register a rejection handler with a promise. /// Register a rejection handler with a promise.
/// ///
/// See `Self::then2`. /// See `Self::then2`.
pub fn catch<'sc>( pub fn catch<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
context: Local<Context>, context: Local<Context>,
handler: Local<Function>, handler: Local<Function>,
) -> Option<Local<'sc, Promise>> { ) -> Option<Local<'s, Promise>> {
unsafe { unsafe {
scope.cast_local(|_| v8__Promise__Catch(&*self, &*context, &*handler)) scope.cast_local(|_| v8__Promise__Catch(&*self, &*context, &*handler))
} }
@ -103,12 +100,12 @@ impl Promise {
/// Register a resolution handler with a promise. /// Register a resolution handler with a promise.
/// ///
/// See `Self::then2`. /// See `Self::then2`.
pub fn then<'sc>( pub fn then<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
context: Local<Context>, context: Local<Context>,
handler: Local<Function>, handler: Local<Function>,
) -> Option<Local<'sc, Promise>> { ) -> Option<Local<'s, Promise>> {
unsafe { unsafe {
scope.cast_local(|_| v8__Promise__Then(&*self, &*context, &*handler)) scope.cast_local(|_| v8__Promise__Then(&*self, &*context, &*handler))
} }
@ -118,13 +115,13 @@ impl Promise {
/// The handler is given the respective resolution/rejection value as /// The handler is given the respective resolution/rejection value as
/// an argument. If the promise is already resolved/rejected, the handler is /// an argument. If the promise is already resolved/rejected, the handler is
/// invoked at the end of turn. /// invoked at the end of turn.
pub fn then2<'sc>( pub fn then2<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
context: Local<Context>, context: Local<Context>,
on_fulfilled: Local<Function>, on_fulfilled: Local<Function>,
on_rejected: Local<Function>, on_rejected: Local<Function>,
) -> Option<Local<'sc, Promise>> { ) -> Option<Local<'s, Promise>> {
unsafe { unsafe {
scope.cast_local(|_| { scope.cast_local(|_| {
v8__Promise__Then2(&*self, &*context, &*on_fulfilled, &*on_rejected) v8__Promise__Then2(&*self, &*context, &*on_fulfilled, &*on_rejected)
@ -135,38 +132,38 @@ impl Promise {
impl PromiseResolver { impl PromiseResolver {
/// Create a new resolver, along with an associated promise in pending state. /// Create a new resolver, along with an associated promise in pending state.
pub fn new<'sc>( pub fn new<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
context: Local<'sc, Context>, context: Local<'s, Context>,
) -> Option<Local<'sc, PromiseResolver>> { ) -> Option<Local<'s, PromiseResolver>> {
unsafe { scope.cast_local(|_| v8__Promise__Resolver__New(&*context)) } unsafe { scope.cast_local(|_| v8__Promise__Resolver__New(&*context)) }
} }
/// Extract the associated promise. /// Extract the associated promise.
pub fn get_promise<'sc>( pub fn get_promise<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
) -> Local<'sc, Promise> { ) -> Local<'s, Promise> {
unsafe { scope.cast_local(|_| v8__Promise__Resolver__GetPromise(&*self)) } unsafe { scope.cast_local(|_| v8__Promise__Resolver__GetPromise(&*self)) }
.unwrap() .unwrap()
} }
/// Resolve the associated promise with a given value. /// Resolve the associated promise with a given value.
/// Ignored if the promise is no longer pending. /// Ignored if the promise is no longer pending.
pub fn resolve<'sc>( pub fn resolve<'s>(
&self, &self,
context: Local<'sc, Context>, context: Local<'s, Context>,
value: Local<'sc, Value>, value: Local<'s, Value>,
) -> Option<bool> { ) -> Option<bool> {
unsafe { v8__Promise__Resolver__Resolve(&*self, &*context, &*value).into() } unsafe { v8__Promise__Resolver__Resolve(&*self, &*context, &*value).into() }
} }
/// Reject the associated promise with a given value. /// Reject the associated promise with a given value.
/// Ignored if the promise is no longer pending. /// Ignored if the promise is no longer pending.
pub fn reject<'sc>( pub fn reject<'s>(
&self, &self,
context: Local<'sc, Context>, context: Local<'s, Context>,
value: Local<'sc, Value>, value: Local<'s, Value>,
) -> Option<bool> { ) -> Option<bool> {
unsafe { v8__Promise__Resolver__Reject(&*self, &*context, &*value).into() } unsafe { v8__Promise__Resolver__Reject(&*self, &*context, &*value).into() }
} }

View file

@ -1,8 +1,8 @@
use crate::Context; use crate::Context;
use crate::HandleScope;
use crate::Local; use crate::Local;
use crate::Object; use crate::Object;
use crate::Proxy; use crate::Proxy;
use crate::ToLocal;
use crate::Value; use crate::Value;
extern "C" { extern "C" {
@ -18,28 +18,28 @@ extern "C" {
} }
impl Proxy { impl Proxy {
pub fn new<'sc>( pub fn new<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
context: Local<Context>, context: Local<Context>,
target: Local<Object>, target: Local<Object>,
handler: Local<Object>, handler: Local<Object>,
) -> Option<Local<'sc, Proxy>> { ) -> Option<Local<'s, Proxy>> {
unsafe { unsafe {
scope.cast_local(|_| v8__Proxy__New(&*context, &*target, &*handler)) scope.cast_local(|_| v8__Proxy__New(&*context, &*target, &*handler))
} }
} }
pub fn get_handler<'sc>( pub fn get_handler<'s>(
&mut self, &mut self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
) -> Local<'sc, Value> { ) -> Local<'s, Value> {
unsafe { scope.cast_local(|_| v8__Proxy__GetHandler(&*self)) }.unwrap() unsafe { scope.cast_local(|_| v8__Proxy__GetHandler(&*self)) }.unwrap()
} }
pub fn get_target<'sc>( pub fn get_target<'s>(
&mut self, &mut self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
) -> Local<'sc, Value> { ) -> Local<'s, Value> {
unsafe { scope.cast_local(|_| v8__Proxy__GetTarget(&*self)) }.unwrap() unsafe { scope.cast_local(|_| v8__Proxy__GetTarget(&*self)) }.unwrap()
} }

File diff suppressed because it is too large Load diff

View file

@ -1,264 +0,0 @@
// Copyright 2019-2020 the Deno authors. All rights reserved. MIT license.
use crate::scope::Entered;
use crate::scope::Escapable;
use crate::CallbackScope;
use crate::Context;
use crate::ContextScope;
use crate::EscapableHandleScope;
use crate::FunctionCallbackInfo;
use crate::HandleScope;
use crate::Isolate;
use crate::Local;
use crate::Message;
use crate::Object;
use crate::PropertyCallbackInfo;
pub(crate) mod internal {
use super::*;
extern "C" {
fn v8__Context__GetIsolate(this: *const Context) -> *mut Isolate;
fn v8__EscapableHandleScope__GetIsolate(
this: &EscapableHandleScope,
) -> *mut Isolate;
fn v8__FunctionCallbackInfo__GetIsolate(
this: &FunctionCallbackInfo,
) -> *mut Isolate;
fn v8__HandleScope__GetIsolate(this: &HandleScope) -> *mut Isolate;
fn v8__Message__GetIsolate(this: *const Message) -> *mut Isolate;
fn v8__Object__GetIsolate(this: *const Object) -> *mut Isolate;
fn v8__PropertyCallbackInfo__GetIsolate(
this: &PropertyCallbackInfo,
) -> *mut Isolate;
}
/// Internal trait for retrieving a raw Isolate pointer from various V8
/// API objects.
pub trait GetRawIsolate {
fn get_raw_isolate(&self) -> *mut Isolate;
}
impl<'s, T> GetRawIsolate for Local<'s, T>
where
Local<'s, Object>: From<Local<'s, T>>,
{
fn get_raw_isolate(&self) -> *mut Isolate {
let local = Local::<'s, Object>::from(*self);
(&*local).get_raw_isolate()
}
}
impl<'s> GetRawIsolate for Local<'s, Context> {
fn get_raw_isolate(&self) -> *mut Isolate {
(&**self).get_raw_isolate()
}
}
impl<'s> GetRawIsolate for Local<'s, Message> {
fn get_raw_isolate(&self) -> *mut Isolate {
(&**self).get_raw_isolate()
}
}
impl<'s, S> GetRawIsolate for Entered<'_, S>
where
S: GetRawIsolate,
{
fn get_raw_isolate(&self) -> *mut Isolate {
self.data().get_raw_isolate()
}
}
impl<X> GetRawIsolate for CallbackScope<X> {
fn get_raw_isolate(&self) -> *mut Isolate {
self.get_raw_isolate_()
}
}
impl<'s> GetRawIsolate for ContextScope {
fn get_raw_isolate(&self) -> *mut Isolate {
unsafe { self.get_captured_context() }.get_raw_isolate()
}
}
impl GetRawIsolate for Context {
fn get_raw_isolate(&self) -> *mut Isolate {
unsafe { v8__Context__GetIsolate(self) }
}
}
impl GetRawIsolate for EscapableHandleScope {
fn get_raw_isolate(&self) -> *mut Isolate {
unsafe { v8__EscapableHandleScope__GetIsolate(self) }
}
}
impl GetRawIsolate for FunctionCallbackInfo {
fn get_raw_isolate(&self) -> *mut Isolate {
unsafe { v8__FunctionCallbackInfo__GetIsolate(self) }
}
}
impl GetRawIsolate for HandleScope {
fn get_raw_isolate(&self) -> *mut Isolate {
unsafe { v8__HandleScope__GetIsolate(self) }
}
}
impl GetRawIsolate for Message {
fn get_raw_isolate(&self) -> *mut Isolate {
unsafe { v8__Message__GetIsolate(self) }
}
}
impl GetRawIsolate for Object {
fn get_raw_isolate(&self) -> *mut Isolate {
unsafe { v8__Object__GetIsolate(self) }
}
}
impl GetRawIsolate for PropertyCallbackInfo {
fn get_raw_isolate(&self) -> *mut Isolate {
unsafe { v8__PropertyCallbackInfo__GetIsolate(self) }
}
}
}
/// Trait for retrieving the current isolate from a scope object.
pub trait InIsolate {
// Do not implement this trait on unscoped Isolate references
// (e.g. OwnedIsolate) or on shared references *e.g. &Isolate).
fn isolate(&mut self) -> &mut Isolate;
}
impl<'s, S, P> InIsolate for Entered<'s, S, P>
where
S: internal::GetRawIsolate,
{
fn isolate(&mut self) -> &mut Isolate {
unsafe { &mut *(self.data().get_raw_isolate()) }
}
}
extern "C" {
fn v8__Isolate__GetCurrentContext(isolate: *mut Isolate) -> *const Context;
fn v8__Isolate__GetEnteredOrMicrotaskContext(
isolate: *mut Isolate,
) -> *const Context;
}
/// When scope implements this trait, this means that Local handles can be
/// created inside it.
pub trait ToLocal<'s>: InIsolate {
unsafe fn cast_local<T, F: FnOnce(&mut Self) -> *const T>(
&mut self,
f: F,
) -> Option<Local<'s, T>> {
Local::from_raw(f(self))
}
fn get_current_context(&mut self) -> Option<Local<'s, Context>> {
unsafe {
self.cast_local(|scope| v8__Isolate__GetCurrentContext(scope.isolate()))
}
}
fn get_entered_or_microtask_context(&mut self) -> Option<Local<'s, Context>> {
unsafe {
self.cast_local(|scope| {
v8__Isolate__GetEnteredOrMicrotaskContext(scope.isolate())
})
}
}
}
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: 's, P> ToLocal<'p> for Entered<'s, ContextScope, P> where
P: ToLocal<'p>
{
}
pub trait ToLocalOrReturnsLocal<'s>: InIsolate {}
impl<'s, E> ToLocalOrReturnsLocal<'s> for E where E: ToLocal<'s> {}
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: ToLocal<'p>,
{
/// Returns the context of the currently running JavaScript, or the context
/// on the top of the stack if no JavaScript is running.
pub fn get_current_context(&mut self) -> Option<Local<'p, Context>> {
<Self as ToLocal<'p>>::get_current_context(self)
}
/// Returns either the last context entered through V8's C++ API, or the
/// context of the currently running microtask while processing microtasks.
/// If a context is entered while executing a microtask, that context is
/// returned.
pub fn get_entered_or_microtask_context(
&mut self,
) -> Option<Local<'p, Context>> {
<Self as ToLocal<'p>>::get_entered_or_microtask_context(self)
}
}
impl<'s, 'p: 's, S, P> Entered<'s, S, P>
where
Self: EscapeLocal<'s, 'p>,
{
/// Pushes the value into the previous scope and returns a handle to it.
/// Cannot be called twice.
pub fn escape<T>(&mut self, local: Local<T>) -> Local<'p, T> {
<Self as EscapeLocal<'s, 'p>>::escape(self, local)
}
}

View file

@ -4,16 +4,16 @@ use std::ptr::null;
use crate::Boolean; use crate::Boolean;
use crate::Context; use crate::Context;
use crate::HandleScope;
use crate::Integer; use crate::Integer;
use crate::Local; use crate::Local;
use crate::Script; use crate::Script;
use crate::String; use crate::String;
use crate::ToLocal;
use crate::Value; use crate::Value;
/// The origin, within a file, of a script. /// The origin, within a file, of a script.
#[repr(C)] #[repr(C)]
pub struct ScriptOrigin<'sc>([usize; 7], PhantomData<&'sc ()>); pub struct ScriptOrigin<'s>([usize; 7], PhantomData<&'s ()>);
extern "C" { extern "C" {
fn v8__Script__Compile( fn v8__Script__Compile(
@ -42,18 +42,18 @@ extern "C" {
impl Script { impl Script {
/// A shorthand for ScriptCompiler::Compile(). /// A shorthand for ScriptCompiler::Compile().
pub fn compile<'sc>( pub fn compile<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
context: Local<Context>, context: Local<Context>,
source: Local<String>, source: Local<String>,
origin: Option<&ScriptOrigin>, origin: Option<&ScriptOrigin>,
) -> Option<Local<'sc, Script>> { ) -> Option<Local<'s, Script>> {
unsafe { unsafe {
scope.cast_local(|_| { scope.cast_local(|_| {
v8__Script__Compile( v8__Script__Compile(
&*context, &*context,
&*source, &*source,
origin.map(|r| r as *const _).unwrap_or(null()), origin.map(|r| r as *const _).unwrap_or_else(null),
) )
}) })
} }
@ -62,28 +62,28 @@ impl Script {
/// Runs the script returning the resulting value. It will be run in the /// Runs the script returning the resulting value. It will be run in the
/// context in which it was created (ScriptCompiler::CompileBound or /// context in which it was created (ScriptCompiler::CompileBound or
/// UnboundScript::BindToCurrentContext()). /// UnboundScript::BindToCurrentContext()).
pub fn run<'sc>( pub fn run<'s>(
&mut self, &mut self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
context: Local<Context>, context: Local<Context>,
) -> Option<Local<'sc, Value>> { ) -> Option<Local<'s, Value>> {
unsafe { scope.cast_local(|_| v8__Script__Run(self, &*context)) } unsafe { scope.cast_local(|_| v8__Script__Run(self, &*context)) }
} }
} }
/// The origin, within a file, of a script. /// The origin, within a file, of a script.
impl<'sc> ScriptOrigin<'sc> { impl<'s> ScriptOrigin<'s> {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
resource_name: Local<'sc, Value>, resource_name: Local<'s, Value>,
resource_line_offset: Local<'sc, Integer>, resource_line_offset: Local<'s, Integer>,
resource_column_offset: Local<'sc, Integer>, resource_column_offset: Local<'s, Integer>,
resource_is_shared_cross_origin: Local<'sc, Boolean>, resource_is_shared_cross_origin: Local<'s, Boolean>,
script_id: Local<'sc, Integer>, script_id: Local<'s, Integer>,
source_map_url: Local<'sc, Value>, source_map_url: Local<'s, Value>,
resource_is_opaque: Local<'sc, Boolean>, resource_is_opaque: Local<'s, Boolean>,
is_wasm: Local<'sc, Boolean>, is_wasm: Local<'s, Boolean>,
is_module: Local<'sc, Boolean>, is_module: Local<'s, Boolean>,
) -> Self { ) -> Self {
unsafe { unsafe {
let mut buf = std::mem::MaybeUninit::<ScriptOrigin>::uninit(); let mut buf = std::mem::MaybeUninit::<ScriptOrigin>::uninit();

View file

@ -1,12 +1,12 @@
// Copyright 2019-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2019-2020 the Deno authors. All rights reserved. MIT license.
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use crate::HandleScope;
use crate::Isolate; use crate::Isolate;
use crate::Local; use crate::Local;
use crate::Module; use crate::Module;
use crate::ScriptOrigin; use crate::ScriptOrigin;
use crate::String; use crate::String;
use crate::ToLocal;
extern "C" { extern "C" {
fn v8__ScriptCompiler__Source__CONSTRUCT( fn v8__ScriptCompiler__Source__CONSTRUCT(
@ -77,10 +77,10 @@ pub enum NoCacheReason {
/// ///
/// Corresponds to the ParseModule abstract operation in the ECMAScript /// Corresponds to the ParseModule abstract operation in the ECMAScript
/// specification. /// specification.
pub fn compile_module<'sc>( pub fn compile_module<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
source: Source, source: Source,
) -> Option<Local<'sc, Module>> { ) -> Option<Local<'s, Module>> {
compile_module2( compile_module2(
scope, scope,
source, source,
@ -90,16 +90,16 @@ pub fn compile_module<'sc>(
} }
/// Same as compile_module with more options. /// Same as compile_module with more options.
pub fn compile_module2<'sc>( pub fn compile_module2<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
mut source: Source, mut source: Source,
options: CompileOptions, options: CompileOptions,
no_cache_reason: NoCacheReason, no_cache_reason: NoCacheReason,
) -> Option<Local<'sc, Module>> { ) -> Option<Local<'s, Module>> {
unsafe { unsafe {
scope.cast_local(|scope| { scope.cast_local(|sd| {
v8__ScriptCompiler__CompileModule( v8__ScriptCompiler__CompileModule(
scope.isolate(), sd.get_isolate_ptr(),
&mut source, &mut source,
options, options,
no_cache_reason, no_cache_reason,

View file

@ -8,11 +8,10 @@ use crate::support::SharedRef;
use crate::support::UniqueRef; use crate::support::UniqueRef;
use crate::BackingStore; use crate::BackingStore;
use crate::BackingStoreDeleterCallback; use crate::BackingStoreDeleterCallback;
use crate::InIsolate; use crate::HandleScope;
use crate::Isolate; use crate::Isolate;
use crate::Local; use crate::Local;
use crate::SharedArrayBuffer; use crate::SharedArrayBuffer;
use crate::ToLocal;
extern "C" { extern "C" {
fn v8__SharedArrayBuffer__New__with_byte_length( fn v8__SharedArrayBuffer__New__with_byte_length(
@ -45,28 +44,28 @@ impl SharedArrayBuffer {
/// Allocated memory will be owned by a created SharedArrayBuffer and /// Allocated memory will be owned by a created SharedArrayBuffer and
/// will be deallocated when it is garbage-collected, /// will be deallocated when it is garbage-collected,
/// unless the object is externalized. /// unless the object is externalized.
pub fn new<'sc>( pub fn new<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
byte_length: usize, byte_length: usize,
) -> Option<Local<'sc, SharedArrayBuffer>> { ) -> Option<Local<'s, SharedArrayBuffer>> {
unsafe { unsafe {
scope.cast_local(|scope| { scope.cast_local(|sd| {
v8__SharedArrayBuffer__New__with_byte_length( v8__SharedArrayBuffer__New__with_byte_length(
scope.isolate(), sd.get_isolate_ptr(),
byte_length, byte_length,
) )
}) })
} }
} }
pub fn with_backing_store<'sc>( pub fn with_backing_store<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
backing_store: &SharedRef<BackingStore>, backing_store: &SharedRef<BackingStore>,
) -> Local<'sc, SharedArrayBuffer> { ) -> Local<'s, SharedArrayBuffer> {
unsafe { unsafe {
scope.cast_local(|scope| { scope.cast_local(|sd| {
v8__SharedArrayBuffer__New__with_backing_store( v8__SharedArrayBuffer__New__with_backing_store(
scope.isolate(), sd.get_isolate_ptr(),
backing_store, backing_store,
) )
}) })
@ -95,13 +94,13 @@ impl SharedArrayBuffer {
/// given isolate and re-try the allocation. If GCs do not help, then the /// given isolate and re-try the allocation. If GCs do not help, then the
/// function will crash with an out-of-memory error. /// function will crash with an out-of-memory error.
pub fn new_backing_store( pub fn new_backing_store(
scope: &mut impl InIsolate, scope: &mut Isolate,
byte_length: usize, byte_length: usize,
) -> UniqueRef<BackingStore> { ) -> UniqueRef<BackingStore> {
unsafe { unsafe {
UniqueRef::from_raw( UniqueRef::from_raw(
v8__SharedArrayBuffer__NewBackingStore__with_byte_length( v8__SharedArrayBuffer__NewBackingStore__with_byte_length(
scope.isolate(), scope,
byte_length, byte_length,
), ),
) )

View file

@ -1,4 +1,5 @@
use crate::external_references::ExternalReferences; use crate::external_references::ExternalReferences;
use crate::scope::data::ScopeData;
use crate::support::char; use crate::support::char;
use crate::support::int; use crate::support::int;
use crate::support::intptr_t; use crate::support::intptr_t;
@ -105,7 +106,7 @@ impl SnapshotCreator {
/// Set the default context to be included in the snapshot blob. /// Set the default context to be included in the snapshot blob.
/// The snapshot will not contain the global proxy, and we expect one or a /// The snapshot will not contain the global proxy, and we expect one or a
/// global object template to create one, to be provided upon deserialization. /// global object template to create one, to be provided upon deserialization.
pub fn set_default_context<'sc>(&mut self, context: Local<'sc, Context>) { pub fn set_default_context<'s>(&mut self, context: Local<'s, Context>) {
unsafe { v8__SnapshotCreator__SetDefaultContext(self, &*context) }; unsafe { v8__SnapshotCreator__SetDefaultContext(self, &*context) };
} }
@ -115,6 +116,10 @@ impl SnapshotCreator {
&mut self, &mut self,
function_code_handling: FunctionCodeHandling, function_code_handling: FunctionCodeHandling,
) -> Option<StartupData> { ) -> Option<StartupData> {
{
let isolate = unsafe { &mut *v8__SnapshotCreator__GetIsolate(self) };
ScopeData::get_root_mut(isolate);
}
let blob = let blob =
unsafe { v8__SnapshotCreator__CreateBlob(self, function_code_handling) }; unsafe { v8__SnapshotCreator__CreateBlob(self, function_code_handling) };
if blob.data.is_null() { if blob.data.is_null() {
@ -134,6 +139,7 @@ impl SnapshotCreator {
pub unsafe fn get_owned_isolate(&mut self) -> OwnedIsolate { pub unsafe fn get_owned_isolate(&mut self) -> OwnedIsolate {
let isolate_ptr = v8__SnapshotCreator__GetIsolate(self); let isolate_ptr = v8__SnapshotCreator__GetIsolate(self);
let mut owned_isolate = OwnedIsolate::new(isolate_ptr); let mut owned_isolate = OwnedIsolate::new(isolate_ptr);
ScopeData::new_root(&mut owned_isolate);
owned_isolate.create_annex(Box::new(())); owned_isolate.create_annex(Box::new(()));
owned_isolate owned_isolate
} }

View file

@ -5,11 +5,10 @@ use std::slice;
use crate::support::char; use crate::support::char;
use crate::support::int; use crate::support::int;
use crate::InIsolate; use crate::HandleScope;
use crate::Isolate; use crate::Isolate;
use crate::Local; use crate::Local;
use crate::String; use crate::String;
use crate::ToLocal;
extern "C" { extern "C" {
fn v8__String__Empty(isolate: *mut Isolate) -> *const String; fn v8__String__Empty(isolate: *mut Isolate) -> *const String;
@ -63,26 +62,26 @@ bitflags! {
} }
impl String { impl String {
pub fn empty<'sc>(scope: &mut impl ToLocal<'sc>) -> Local<'sc, String> { pub fn empty<'s>(scope: &mut HandleScope<'s, ()>) -> Local<'s, String> {
// FIXME(bnoordhuis) v8__String__Empty() is infallible so there // FIXME(bnoordhuis) v8__String__Empty() is infallible so there
// is no need to box up the result, only to unwrap it again. // is no need to box up the result, only to unwrap it again.
unsafe { scope.cast_local(|scope| v8__String__Empty(scope.isolate())) } unsafe { scope.cast_local(|sd| v8__String__Empty(sd.get_isolate_ptr())) }
.unwrap() .unwrap()
} }
pub fn new_from_utf8<'sc>( pub fn new_from_utf8<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s, ()>,
buffer: &[u8], buffer: &[u8],
new_type: NewStringType, new_type: NewStringType,
) -> Option<Local<'sc, String>> { ) -> Option<Local<'s, String>> {
if buffer.is_empty() { if buffer.is_empty() {
return Some(Self::empty(scope)); return Some(Self::empty(scope));
} }
let buffer_len = buffer.len().try_into().ok()?; let buffer_len = buffer.len().try_into().ok()?;
unsafe { unsafe {
scope.cast_local(|scope| { scope.cast_local(|sd| {
v8__String__NewFromUtf8( v8__String__NewFromUtf8(
scope.isolate(), sd.get_isolate_ptr(),
buffer.as_ptr() as *const char, buffer.as_ptr() as *const char,
new_type, new_type,
buffer_len, buffer_len,
@ -98,13 +97,13 @@ impl String {
/// Returns the number of bytes in the UTF-8 encoded representation of this /// Returns the number of bytes in the UTF-8 encoded representation of this
/// string. /// string.
pub fn utf8_length(&self, scope: &mut impl InIsolate) -> usize { pub fn utf8_length(&self, scope: &mut Isolate) -> usize {
unsafe { v8__String__Utf8Length(self, scope.isolate()) as usize } unsafe { v8__String__Utf8Length(self, scope) as usize }
} }
pub fn write_utf8( pub fn write_utf8(
&self, &self,
scope: &mut impl InIsolate, scope: &mut Isolate,
buffer: &mut [u8], buffer: &mut [u8],
nchars_ref: Option<&mut usize>, nchars_ref: Option<&mut usize>,
options: WriteOptions, options: WriteOptions,
@ -113,7 +112,7 @@ impl String {
let bytes = unsafe { let bytes = unsafe {
v8__String__WriteUtf8( v8__String__WriteUtf8(
self, self,
scope.isolate(), scope,
buffer.as_mut_ptr() as *mut char, buffer.as_mut_ptr() as *mut char,
buffer.len().try_into().unwrap_or(int::max_value()), buffer.len().try_into().unwrap_or(int::max_value()),
&mut nchars_ref_int, &mut nchars_ref_int,
@ -127,17 +126,17 @@ impl String {
} }
// Convenience function not present in the original V8 API. // Convenience function not present in the original V8 API.
pub fn new<'sc>( pub fn new<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s, ()>,
value: &str, value: &str,
) -> Option<Local<'sc, String>> { ) -> Option<Local<'s, String>> {
Self::new_from_utf8(scope, value.as_ref(), NewStringType::Normal) Self::new_from_utf8(scope, value.as_ref(), NewStringType::Normal)
} }
// Convenience function not present in the original V8 API. // Convenience function not present in the original V8 API.
pub fn to_rust_string_lossy( pub fn to_rust_string_lossy(
&self, &self,
scope: &mut impl InIsolate, scope: &mut Isolate,
) -> std::string::String { ) -> std::string::String {
let capacity = self.utf8_length(scope); let capacity = self.utf8_length(scope);
let mut string = std::string::String::with_capacity(capacity); let mut string = std::string::String::with_capacity(capacity);

View file

@ -8,11 +8,11 @@ use crate::support::MapFnTo;
use crate::Context; use crate::Context;
use crate::Function; use crate::Function;
use crate::FunctionCallback; use crate::FunctionCallback;
use crate::HandleScope;
use crate::Local; use crate::Local;
use crate::Object; use crate::Object;
use crate::PropertyAttribute; use crate::PropertyAttribute;
use crate::String; use crate::String;
use crate::ToLocal;
use crate::NONE; use crate::NONE;
extern "C" { extern "C" {
@ -66,24 +66,24 @@ impl Template {
impl FunctionTemplate { impl FunctionTemplate {
/// Creates a function template. /// Creates a function template.
pub fn new<'sc>( pub fn new<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s, ()>,
callback: impl MapFnTo<FunctionCallback>, callback: impl MapFnTo<FunctionCallback>,
) -> Local<'sc, FunctionTemplate> { ) -> Local<'s, FunctionTemplate> {
unsafe { unsafe {
scope.cast_local(|scope| { scope.cast_local(|sd| {
v8__FunctionTemplate__New(scope.isolate(), callback.map_fn_to()) v8__FunctionTemplate__New(sd.get_isolate_ptr(), callback.map_fn_to())
}) })
} }
.unwrap() .unwrap()
} }
/// Returns the unique function instance in the current execution context. /// Returns the unique function instance in the current execution context.
pub fn get_function<'sc>( pub fn get_function<'s>(
&mut self, &mut self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s, ()>,
context: Local<Context>, context: Local<Context>,
) -> Option<Local<'sc, Function>> { ) -> Option<Local<'s, Function>> {
unsafe { unsafe {
scope.cast_local(|_| v8__FunctionTemplate__GetFunction(&*self, &*context)) scope.cast_local(|_| v8__FunctionTemplate__GetFunction(&*self, &*context))
} }
@ -99,33 +99,33 @@ impl FunctionTemplate {
impl ObjectTemplate { impl ObjectTemplate {
/// Creates an object template. /// Creates an object template.
pub fn new<'sc>(scope: &mut impl ToLocal<'sc>) -> Local<'sc, ObjectTemplate> { pub fn new<'s>(scope: &mut HandleScope<'s, ()>) -> Local<'s, ObjectTemplate> {
unsafe { unsafe {
scope.cast_local(|scope| { scope.cast_local(|sd| {
v8__ObjectTemplate__New(scope.isolate(), std::ptr::null()) v8__ObjectTemplate__New(sd.get_isolate_ptr(), std::ptr::null())
}) })
} }
.unwrap() .unwrap()
} }
/// Creates an object template from a function template. /// Creates an object template from a function template.
pub fn new_from_template<'sc>( pub fn new_from_template<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s, ()>,
templ: Local<FunctionTemplate>, templ: Local<FunctionTemplate>,
) -> Local<'sc, ObjectTemplate> { ) -> Local<'s, ObjectTemplate> {
unsafe { unsafe {
scope scope
.cast_local(|scope| v8__ObjectTemplate__New(scope.isolate(), &*templ)) .cast_local(|sd| v8__ObjectTemplate__New(sd.get_isolate_ptr(), &*templ))
} }
.unwrap() .unwrap()
} }
/// Creates a new instance of this object template. /// Creates a new instance of this object template.
pub fn new_instance<'a>( pub fn new_instance<'s>(
&self, &self,
scope: &mut impl ToLocal<'a>, scope: &mut HandleScope<'s>,
context: Local<Context>, context: Local<Context>,
) -> Option<Local<'a, Object>> { ) -> Option<Local<'s, Object>> {
unsafe { unsafe {
scope.cast_local(|_| v8__ObjectTemplate__NewInstance(self, &*context)) scope.cast_local(|_| v8__ObjectTemplate__NewInstance(self, &*context))
} }

View file

@ -5,11 +5,10 @@ use std::mem::take;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use crate::Context; use crate::Context;
use crate::InIsolate; use crate::HandleScope;
use crate::Isolate; use crate::Isolate;
use crate::Local; use crate::Local;
use crate::Message; use crate::Message;
use crate::ToLocal;
use crate::Value; use crate::Value;
extern "C" { extern "C" {
@ -72,10 +71,8 @@ impl<'tc> TryCatch<'tc> {
/// stack allocated because the memory location itself is compared against /// stack allocated because the memory location itself is compared against
/// JavaScript try/catch blocks. /// JavaScript try/catch blocks.
#[allow(clippy::new_ret_no_self)] #[allow(clippy::new_ret_no_self)]
pub fn new(scope: &mut impl InIsolate) -> TryCatchScope<'tc> { pub fn new(scope: &mut Isolate) -> TryCatchScope<'tc> {
TryCatchScope(TryCatchState::New { TryCatchScope(TryCatchState::New { isolate: scope })
isolate: scope.isolate(),
})
} }
/// Returns true if an exception has been caught by this try/catch block. /// Returns true if an exception has been caught by this try/catch block.
@ -115,10 +112,10 @@ impl<'tc> TryCatch<'tc> {
/// no longer and no shorter than the active HandleScope at the time this /// no longer and no shorter than the active HandleScope at the time this
/// method is called. An issue has been opened about this in the V8 bug /// method is called. An issue has been opened about this in the V8 bug
/// tracker: https://bugs.chromium.org/p/v8/issues/detail?id=10537. /// tracker: https://bugs.chromium.org/p/v8/issues/detail?id=10537.
pub fn exception<'sc>( pub fn exception<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
) -> Option<Local<'sc, Value>> { ) -> Option<Local<'s, Value>> {
unsafe { scope.cast_local(|_| v8__TryCatch__Exception(&self.0)) } unsafe { scope.cast_local(|_| v8__TryCatch__Exception(&self.0)) }
} }
@ -127,20 +124,20 @@ impl<'tc> TryCatch<'tc> {
/// ///
/// Note: the remark about the lifetime for the `exception()` return value /// Note: the remark about the lifetime for the `exception()` return value
/// applies here too. /// applies here too.
pub fn message<'sc>( pub fn message<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
) -> Option<Local<'sc, Message>> { ) -> Option<Local<'s, Message>> {
unsafe { scope.cast_local(|_| v8__TryCatch__Message(&self.0)) } unsafe { scope.cast_local(|_| v8__TryCatch__Message(&self.0)) }
} }
/// Returns the .stack property of the thrown object. If no .stack /// Returns the .stack property of the thrown object. If no .stack
/// property is present an empty handle is returned. /// property is present an empty handle is returned.
pub fn stack_trace<'sc>( pub fn stack_trace<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
context: Local<Context>, context: Local<Context>,
) -> Option<Local<'sc, Value>> { ) -> Option<Local<'s, Value>> {
unsafe { unsafe {
scope.cast_local(|_| v8__TryCatch__StackTrace(&self.0, &*context)) scope.cast_local(|_| v8__TryCatch__StackTrace(&self.0, &*context))
} }

View file

@ -1,7 +1,7 @@
// Copyright 2019-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2019-2020 the Deno authors. All rights reserved. MIT license.
use crate::ArrayBuffer; use crate::ArrayBuffer;
use crate::HandleScope;
use crate::Local; use crate::Local;
use crate::ToLocal;
use crate::Uint8Array; use crate::Uint8Array;
extern "C" { extern "C" {
@ -13,12 +13,12 @@ extern "C" {
} }
impl Uint8Array { impl Uint8Array {
pub fn new<'sc>( pub fn new<'s>(
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
buf: Local<ArrayBuffer>, buf: Local<ArrayBuffer>,
byte_offset: usize, byte_offset: usize,
length: usize, length: usize,
) -> Option<Local<'sc, Uint8Array>> { ) -> Option<Local<'s, Uint8Array>> {
unsafe { unsafe {
scope.cast_local(|_| v8__Uint8Array__New(&*buf, byte_offset, length)) scope.cast_local(|_| v8__Uint8Array__New(&*buf, byte_offset, length))
} }

View file

@ -1,13 +1,13 @@
use crate::support::Maybe; use crate::support::Maybe;
use crate::BigInt; use crate::BigInt;
use crate::Context; use crate::Context;
use crate::HandleScope;
use crate::Int32; use crate::Int32;
use crate::Integer; use crate::Integer;
use crate::Local; use crate::Local;
use crate::Number; use crate::Number;
use crate::Object; use crate::Object;
use crate::String; use crate::String;
use crate::ToLocal;
use crate::Uint32; use crate::Uint32;
use crate::Value; use crate::Value;
@ -411,124 +411,124 @@ impl Value {
unsafe { v8__Value__IsModuleNamespaceObject(self) } unsafe { v8__Value__IsModuleNamespaceObject(self) }
} }
pub fn strict_equals<'sc>(&self, that: Local<'sc, Value>) -> bool { pub fn strict_equals<'s>(&self, that: Local<'s, Value>) -> bool {
unsafe { v8__Value__StrictEquals(self, &*that) } unsafe { v8__Value__StrictEquals(self, &*that) }
} }
pub fn same_value<'sc>(&self, that: Local<'sc, Value>) -> bool { pub fn same_value<'s>(&self, that: Local<'s, Value>) -> bool {
unsafe { v8__Value__SameValue(self, &*that) } unsafe { v8__Value__SameValue(self, &*that) }
} }
pub fn to_big_int<'sc>( pub fn to_big_int<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
) -> Option<Local<'sc, BigInt>> { ) -> Option<Local<'s, BigInt>> {
scope.get_current_context().and_then(|context| unsafe { unsafe {
scope.cast_local(|_| v8__Value__ToBigInt(self, &*context)) scope
}) .cast_local(|sd| v8__Value__ToBigInt(self, &*sd.get_current_context()))
}
} }
pub fn to_number<'sc>( pub fn to_number<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
) -> Option<Local<'sc, Number>> { ) -> Option<Local<'s, Number>> {
scope.get_current_context().and_then(|context| unsafe { unsafe {
scope.cast_local(|_| v8__Value__ToNumber(self, &*context)) scope
}) .cast_local(|sd| v8__Value__ToNumber(self, &*sd.get_current_context()))
}
} }
pub fn to_string<'sc>( pub fn to_string<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
) -> Option<Local<'sc, String>> { ) -> Option<Local<'s, String>> {
scope.get_current_context().and_then(|context| unsafe { unsafe {
scope.cast_local(|_| v8__Value__ToString(self, &*context)) scope
}) .cast_local(|sd| v8__Value__ToString(self, &*sd.get_current_context()))
}
} }
pub fn to_detail_string<'sc>( pub fn to_detail_string<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
) -> Option<Local<'sc, String>> { ) -> Option<Local<'s, String>> {
scope.get_current_context().and_then(|context| unsafe { unsafe {
scope.cast_local(|_| v8__Value__ToDetailString(self, &*context)) scope.cast_local(|sd| {
}) v8__Value__ToDetailString(self, &*sd.get_current_context())
})
}
} }
pub fn to_object<'sc>( pub fn to_object<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
) -> Option<Local<'sc, Object>> { ) -> Option<Local<'s, Object>> {
scope.get_current_context().and_then(|context| unsafe { unsafe {
scope.cast_local(|_| v8__Value__ToObject(self, &*context)) scope
}) .cast_local(|sd| v8__Value__ToObject(self, &*sd.get_current_context()))
}
} }
pub fn to_integer<'sc>( pub fn to_integer<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
) -> Option<Local<'sc, Integer>> { ) -> Option<Local<'s, Integer>> {
scope.get_current_context().and_then(|context| unsafe { unsafe {
scope.cast_local(|_| v8__Value__ToInteger(self, &*context)) scope
}) .cast_local(|sd| v8__Value__ToInteger(self, &*sd.get_current_context()))
}
} }
pub fn to_uint32<'sc>( pub fn to_uint32<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
) -> Option<Local<'sc, Uint32>> { ) -> Option<Local<'s, Uint32>> {
scope.get_current_context().and_then(|context| unsafe { unsafe {
scope.cast_local(|_| v8__Value__ToUint32(self, &*context)) scope
}) .cast_local(|sd| v8__Value__ToUint32(self, &*sd.get_current_context()))
}
} }
pub fn to_int32<'sc>( pub fn to_int32<'s>(
&self, &self,
scope: &mut impl ToLocal<'sc>, scope: &mut HandleScope<'s>,
) -> Option<Local<'sc, Int32>> { ) -> Option<Local<'s, Int32>> {
scope.get_current_context().and_then(|context| unsafe { unsafe {
scope.cast_local(|_| v8__Value__ToInt32(self, &*context)) scope
}) .cast_local(|sd| v8__Value__ToInt32(self, &*sd.get_current_context()))
}
} }
pub fn number_value<'sc>( pub fn number_value<'s>(&self, scope: &mut HandleScope<'s>) -> Option<f64> {
&self, let mut out = Maybe::<f64>::default();
scope: &mut impl ToLocal<'sc>, unsafe {
) -> Option<f64> { v8__Value__NumberValue(self, &*scope.get_current_context(), &mut out)
scope.get_current_context().and_then(|context| unsafe { };
let mut out = Maybe::<f64>::default(); out.into()
v8__Value__NumberValue(self, &*context, &mut out);
out.into()
})
} }
pub fn integer_value<'sc>( pub fn integer_value<'s>(&self, scope: &mut HandleScope<'s>) -> Option<i64> {
&self, let mut out = Maybe::<i64>::default();
scope: &mut impl ToLocal<'sc>, unsafe {
) -> Option<i64> { v8__Value__IntegerValue(self, &*scope.get_current_context(), &mut out)
scope.get_current_context().and_then(|context| unsafe { };
let mut out = Maybe::<i64>::default(); out.into()
v8__Value__IntegerValue(self, &*context, &mut out);
out.into()
})
} }
pub fn uint32_value<'sc>( pub fn uint32_value<'s>(&self, scope: &mut HandleScope<'s>) -> Option<u32> {
&self, let mut out = Maybe::<u32>::default();
scope: &mut impl ToLocal<'sc>, unsafe {
) -> Option<u32> { v8__Value__Uint32Value(self, &*scope.get_current_context(), &mut out)
scope.get_current_context().and_then(|context| unsafe { };
let mut out = Maybe::<u32>::default(); out.into()
v8__Value__Uint32Value(self, &*context, &mut out);
out.into()
})
} }
pub fn int32_value<'sc>(&self, scope: &mut impl ToLocal<'sc>) -> Option<i32> { pub fn int32_value<'s>(&self, scope: &mut HandleScope<'s>) -> Option<i32> {
scope.get_current_context().and_then(|context| unsafe { let mut out = Maybe::<i32>::default();
let mut out = Maybe::<i32>::default(); unsafe {
v8__Value__Int32Value(self, &*context, &mut out); v8__Value__Int32Value(self, &*scope.get_current_context(), &mut out)
out.into() };
}) out.into()
} }
} }

View file

@ -3,11 +3,12 @@ use rusty_v8 as v8;
pub fn main() { pub fn main() {
let mut isolate = v8::Isolate::new(mock()); let mut isolate = v8::Isolate::new(mock());
let mut scope1 = v8::HandleScope::new(&mut isolate);
let _boxed_local = { let _boxed_local = {
let mut hs = v8::HandleScope::new(&mut isolate); let mut scope2 = v8::HandleScope::new(&mut scope1);
let hs = hs.enter(); let mut scope3 = v8::HandleScope::new(&mut scope2);
Box::new(v8::Integer::new(hs, 123)) Box::new(v8::Integer::new(&mut scope3, 123))
}; };
} }

View file

@ -1,11 +1,11 @@
error[E0597]: `hs` does not live long enough error[E0597]: `scope2` does not live long enough
--> $DIR/boxed_local.rs:9:14 --> $DIR/boxed_local.rs:10:43
| |
7 | let _boxed_local = { 8 | let _boxed_local = {
| ------------ borrow later stored here | ------------ borrow later stored here
8 | let mut hs = v8::HandleScope::new(&mut isolate); 9 | let mut scope2 = v8::HandleScope::new(&mut scope1);
9 | let hs = hs.enter(); 10 | let mut scope3 = v8::HandleScope::new(&mut scope2);
| ^^ borrowed value does not live long enough | ^^^^^^^^^^^ borrowed value does not live long enough
10 | Box::new(v8::Integer::new(hs, 123)) 11 | Box::new(v8::Integer::new(&mut scope3, 123))
11 | }; 12 | };
| - `hs` dropped here while still borrowed | - `scope2` dropped here while still borrowed

View file

@ -3,18 +3,14 @@ use rusty_v8 as v8;
pub fn main() { pub fn main() {
let mut isolate = v8::Isolate::new(mock()); let mut isolate = v8::Isolate::new(mock());
let mut hs1 = v8::HandleScope::new(&mut isolate); let mut scope1 = v8::HandleScope::new(&mut isolate);
let hs1 = hs1.enter();
let _local = { let _local = {
let mut hs2 = v8::HandleScope::new(hs1); let mut scope2 = v8::HandleScope::new(&mut scope1);
let hs2 = hs2.enter(); let mut scope3 = v8::HandleScope::new(&mut scope2);
let mut scope4 = v8::EscapableHandleScope::new(&mut scope3);
let mut hs3 = v8::EscapableHandleScope::new(hs2); let value = v8::Integer::new(&mut scope4, 42);
let hs3 = hs3.enter(); scope4.escape(value)
let value: v8::Local<v8::Value> = v8::Integer::new(hs3, 42).into();
hs3.escape(value)
}; };
} }

View file

@ -1,11 +1,11 @@
error[E0597]: `hs2` does not live long enough error[E0597]: `scope2` does not live long enough
--> $DIR/handle_scope_escape_lifetime.rs:11:15 --> $DIR/handle_scope_escape_lifetime.rs:10:43
| |
9 | let _local = { 8 | let _local = {
| ------ borrow later stored here | ------ borrow later stored here
10 | let mut hs2 = v8::HandleScope::new(hs1); 9 | let mut scope2 = v8::HandleScope::new(&mut scope1);
11 | let hs2 = hs2.enter(); 10 | let mut scope3 = v8::HandleScope::new(&mut scope2);
| ^^^ borrowed value does not live long enough | ^^^^^^^^^^^ borrowed value does not live long enough
... ...
18 | }; 14 | };
| - `hs2` dropped here while still borrowed | - `scope2` dropped here while still borrowed

View file

@ -2,9 +2,8 @@
use rusty_v8 as v8; use rusty_v8 as v8;
pub fn main() { pub fn main() {
let context: v8::Local<v8::Context> = mock(); let mut isolate = v8::Isolate::new(mock());
let mut cs = v8::CallbackScope::new(context); let mut _scope = v8::EscapableHandleScope::new(&mut isolate);
let _hs = v8::EscapableHandleScope::new(cs.enter());
} }
fn mock<T>() -> T { fn mock<T>() -> T {

View file

@ -1,18 +1,13 @@
error[E0277]: the trait bound `rusty_v8::scope::Entered<'_, rusty_v8::scope::CallbackScope>: rusty_v8::scope_traits::ToLocal<'_>` is not satisfied error[E0277]: the trait bound `rusty_v8::isolate::OwnedIsolate: rusty_v8::scope::param::NewEscapableHandleScope<'_, '_>` is not satisfied
--> $DIR/handle_scope_escape_to_nowhere.rs:7:43 --> $DIR/handle_scope_escape_to_nowhere.rs:6:50
| |
7 | let _hs = v8::EscapableHandleScope::new(cs.enter()); 6 | let mut _scope = v8::EscapableHandleScope::new(&mut isolate);
| ^^^^^^^^^^ the trait `rusty_v8::scope_traits::ToLocal<'_>` is not implemented for `rusty_v8::scope::Entered<'_, rusty_v8::scope::CallbackScope>` | ^^^^^^^^^^^^ the trait `rusty_v8::scope::param::NewEscapableHandleScope<'_, '_>` is not implemented for `rusty_v8::isolate::OwnedIsolate`
| |
::: $WORKSPACE/src/handle_scope.rs:71:8 = note: required by `rusty_v8::scope::EscapableHandleScope::<'s, 'e>::new`
|
71 | P: ToLocalOrReturnsLocal<'p>, error[E0277]: the trait bound `rusty_v8::isolate::OwnedIsolate: rusty_v8::scope::param::NewEscapableHandleScope<'_, '_>` is not satisfied
| ------------------------- required by this bound in `rusty_v8::handle_scope::EscapableHandleScope::new` --> $DIR/handle_scope_escape_to_nowhere.rs:6:20
| |
= help: the following implementations were found: 6 | let mut _scope = v8::EscapableHandleScope::new(&mut isolate);
<rusty_v8::scope::Entered<'s, rusty_v8::function::FunctionCallbackInfo> as rusty_v8::scope_traits::ToLocal<'s>> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `rusty_v8::scope::param::NewEscapableHandleScope<'_, '_>` is not implemented for `rusty_v8::isolate::OwnedIsolate`
<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<'p>>
= 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

@ -3,14 +3,9 @@ use rusty_v8 as v8;
pub fn main() { pub fn main() {
let mut isolate = v8::Isolate::new(mock()); let mut isolate = v8::Isolate::new(mock());
let mut hs1 = v8::HandleScope::new(&mut isolate); let mut scope1 = v8::HandleScope::new(&mut isolate);
let hs1 = hs1.enter(); let mut _scope2 = v8::EscapableHandleScope::new(&mut scope1);
let _local = v8::Integer::new(&mut scope1, 123);
let mut hs2 = v8::EscapableHandleScope::new(hs1);
let hs2 = hs2.enter();
let _hs3 = v8::EscapableHandleScope::new(hs1);
let _local = v8::Integer::new(hs2, 123);
} }
fn mock<T>() -> T { fn mock<T>() -> T {

View file

@ -1,10 +1,9 @@
error[E0499]: cannot borrow `*hs1` as mutable more than once at a time error[E0499]: cannot borrow `scope1` as mutable more than once at a time
--> $DIR/handle_scope_lifetime_1.rs:12:44 --> $DIR/handle_scope_lifetime_1.rs:8:33
| |
9 | let mut hs2 = v8::EscapableHandleScope::new(hs1); 7 | let mut _scope2 = v8::EscapableHandleScope::new(&mut scope1);
| --- first mutable borrow occurs here | ----------- first mutable borrow occurs here
... 8 | let _local = v8::Integer::new(&mut scope1, 123);
12 | let _hs3 = v8::EscapableHandleScope::new(hs1); | ^^^^^^^^^^^ second mutable borrow occurs here
| ^^^ second mutable borrow occurs here 9 | }
13 | let _local = v8::Integer::new(hs2, 123); | - first borrow might be used here, when `_scope2` is dropped and runs the `Drop` code for type `rusty_v8::scope::EscapableHandleScope`
| --- first borrow later used here

View file

@ -3,16 +3,10 @@ use rusty_v8 as v8;
pub fn main() { pub fn main() {
let mut isolate = v8::Isolate::new(mock()); let mut isolate = v8::Isolate::new(mock());
let mut hs1 = v8::HandleScope::new(&mut isolate); let mut scope1 = v8::HandleScope::new(&mut isolate);
let hs1 = hs1.enter(); let mut scope2 = v8::EscapableHandleScope::new(&mut scope1);
let _local1 = v8::Integer::new(&mut scope1, 123);
let _local1 = v8::Integer::new(hs1, 123); let _local2 = v8::Integer::new(&mut scope2, 123);
let mut hs2 = v8::EscapableHandleScope::new(hs1);
let hs2 = hs2.enter();
let _local2 = v8::Integer::new(hs1, 123);
let _local3 = v8::Integer::new(hs2, 123);
} }
fn mock<T>() -> T { fn mock<T>() -> T {

View file

@ -1,10 +1,9 @@
error[E0499]: cannot borrow `*hs1` as mutable more than once at a time error[E0499]: cannot borrow `scope1` as mutable more than once at a time
--> $DIR/handle_scope_lifetime_2.rs:14:34 --> $DIR/handle_scope_lifetime_2.rs:8:34
| |
11 | let mut hs2 = v8::EscapableHandleScope::new(hs1); 7 | let mut scope2 = v8::EscapableHandleScope::new(&mut scope1);
| --- first mutable borrow occurs here | ----------- first mutable borrow occurs here
... 8 | let _local1 = v8::Integer::new(&mut scope1, 123);
14 | let _local2 = v8::Integer::new(hs1, 123); | ^^^^^^^^^^^ second mutable borrow occurs here
| ^^^ second mutable borrow occurs here 9 | let _local2 = v8::Integer::new(&mut scope2, 123);
15 | let _local3 = v8::Integer::new(hs2, 123); | ----------- first borrow later used here
| --- first borrow later used here

View file

@ -3,13 +3,11 @@ use rusty_v8 as v8;
pub fn main() { pub fn main() {
let mut isolate = v8::Isolate::new(mock()); let mut isolate = v8::Isolate::new(mock());
let mut hs1 = v8::HandleScope::new(&mut isolate); let mut scope1 = v8::HandleScope::new(&mut isolate);
let hs1 = hs1.enter();
let _local = { let _local = {
let mut hs2 = v8::EscapableHandleScope::new(hs1); let mut _scope2 = v8::EscapableHandleScope::new(&mut scope1);
let hs2 = hs2.enter(); v8::Integer::new(&mut scope1, 123)
v8::Integer::new(hs2, 456)
}; };
} }

View file

@ -1,11 +1,9 @@
error[E0597]: `hs2` does not live long enough error[E0499]: cannot borrow `scope1` as mutable more than once at a time
--> $DIR/handle_scope_lifetime_3.rs:11:15 --> $DIR/handle_scope_lifetime_3.rs:10:22
| |
9 | let _local = { 9 | let mut _scope2 = v8::EscapableHandleScope::new(&mut scope1);
| ------ borrow later stored here | ----------- first mutable borrow occurs here
10 | let mut hs2 = v8::EscapableHandleScope::new(hs1); 10 | v8::Integer::new(&mut scope1, 123)
11 | let hs2 = hs2.enter(); | ^^^^^^^^^^^ second mutable borrow occurs here
| ^^^ borrowed value does not live long enough 11 | };
12 | v8::Integer::new(hs2, 456) | - first borrow might be used here, when `_scope2` is dropped and runs the `Drop` code for type `rusty_v8::scope::EscapableHandleScope`
13 | };
| - `hs2` dropped here while still borrowed

View file

@ -3,12 +3,11 @@ use rusty_v8 as v8;
pub fn main() { pub fn main() {
let mut isolate = v8::Isolate::new(mock()); let mut isolate = v8::Isolate::new(mock());
let mut hs1 = v8::HandleScope::new(&mut isolate); let mut scope1 = v8::HandleScope::new(&mut isolate);
let hs1 = hs1.enter();
let _hs2 = { let mut _scope3 = {
let mut hs2 = v8::EscapableHandleScope::new(hs1); let mut scope2 = v8::HandleScope::new(&mut scope1);
hs2.enter() v8::EscapableHandleScope::new(&mut scope2)
}; };
} }

View file

@ -1,10 +1,10 @@
error[E0597]: `hs2` does not live long enough error[E0597]: `scope2` does not live long enough
--> $DIR/handle_scope_lifetime_4.rs:11:5 --> $DIR/handle_scope_lifetime_4.rs:10:35
| |
11 | hs2.enter() 8 | let mut _scope3 = {
| ^^^-------- | ----------- borrow later stored here
| | 9 | let mut scope2 = v8::HandleScope::new(&mut scope1);
| borrowed value does not live long enough 10 | v8::EscapableHandleScope::new(&mut scope2)
| borrow later used here | ^^^^^^^^^^^ borrowed value does not live long enough
12 | }; 11 | };
| - `hs2` dropped here while still borrowed | - `scope2` 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 mut isolate = v8::Isolate::new(mock());
let mut scope = v8::HandleScope::new(&mut isolate);
let _object = v8::Object::new(&mut scope);
}
fn mock<T>() -> T {
unimplemented!()
}

View file

@ -0,0 +1,8 @@
error[E0308]: mismatched types
--> $DIR/object_without_context_scope.rs:7:33
|
7 | let _object = v8::Object::new(&mut scope);
| ^^^^^^^^^^ expected struct `rusty_v8::data::Context`, found `()`
|
= note: expected mutable reference `&mut rusty_v8::scope::HandleScope<'_>`
found mutable reference `&mut rusty_v8::scope::HandleScope<'_, ()>`

View file

@ -3,13 +3,17 @@ use rusty_v8 as v8;
pub fn main() { pub fn main() {
let mut isolate = v8::Isolate::new(mock()); let mut isolate = v8::Isolate::new(mock());
let mut try_catch = v8::TryCatch::new(&mut isolate); let mut scope1 = v8::HandleScope::new(&mut isolate);
let context = v8::Context::new(&mut scope1);
let mut scope2 = v8::ContextScope::new(&mut scope1, context);
let mut try_catch = v8::TryCatch::new(&mut scope2);
let try_catch = try_catch.enter(); let try_catch = try_catch.enter();
let _exception = { let _exception = {
let mut hs = v8::HandleScope::new(&mut isolate); let mut scope3 = v8::HandleScope::new(&mut scope2);
let hs = hs.enter(); let mut scope4 = v8::HandleScope::new(&mut scope3);
try_catch.exception(hs).unwrap() try_catch.exception(&mut scope4).unwrap()
}; };
} }

View file

@ -1,11 +1,11 @@
error[E0597]: `hs` does not live long enough error[E0597]: `scope3` does not live long enough
--> $DIR/try_catch_exception_lifetime.rs:11:14 --> $DIR/try_catch_exception_lifetime.rs:15:43
| |
9 | let _exception = { 13 | let _exception = {
| ---------- borrow later stored here | ---------- borrow later stored here
10 | let mut hs = v8::HandleScope::new(&mut isolate); 14 | let mut scope3 = v8::HandleScope::new(&mut scope2);
11 | let hs = hs.enter(); 15 | let mut scope4 = v8::HandleScope::new(&mut scope3);
| ^^ borrowed value does not live long enough | ^^^^^^^^^^^ borrowed value does not live long enough
12 | try_catch.exception(hs).unwrap() 16 | try_catch.exception(&mut scope4).unwrap()
13 | }; 17 | };
| - `hs` dropped here while still borrowed | - `scope3` dropped here while still borrowed

View file

@ -3,13 +3,17 @@ use rusty_v8 as v8;
pub fn main() { pub fn main() {
let mut isolate = v8::Isolate::new(mock()); let mut isolate = v8::Isolate::new(mock());
let mut try_catch = v8::TryCatch::new(&mut isolate); let mut scope1 = v8::HandleScope::new(&mut isolate);
let context = v8::Context::new(&mut scope1);
let mut scope2 = v8::ContextScope::new(&mut scope1, context);
let mut try_catch = v8::TryCatch::new(&mut scope2);
let try_catch = try_catch.enter(); let try_catch = try_catch.enter();
let _exception = { let _message = {
let mut hs = v8::HandleScope::new(&mut isolate); let mut scope3 = v8::HandleScope::new(&mut scope2);
let hs = hs.enter(); let mut scope4 = v8::HandleScope::new(&mut scope3);
try_catch.message(hs).unwrap() try_catch.message(&mut scope4).unwrap()
}; };
} }

View file

@ -1,11 +1,11 @@
error[E0597]: `hs` does not live long enough error[E0597]: `scope3` does not live long enough
--> $DIR/try_catch_message_lifetime.rs:11:14 --> $DIR/try_catch_message_lifetime.rs:15:43
| |
9 | let _exception = { 13 | let _message = {
| ---------- borrow later stored here | -------- borrow later stored here
10 | let mut hs = v8::HandleScope::new(&mut isolate); 14 | let mut scope3 = v8::HandleScope::new(&mut scope2);
11 | let hs = hs.enter(); 15 | let mut scope4 = v8::HandleScope::new(&mut scope3);
| ^^ borrowed value does not live long enough | ^^^^^^^^^^^ borrowed value does not live long enough
12 | try_catch.message(hs).unwrap() 16 | try_catch.message(&mut scope4).unwrap()
13 | }; 17 | };
| - `hs` dropped here while still borrowed | - `scope3` dropped here while still borrowed

View file

@ -39,11 +39,9 @@ impl CoreIsolate {
// Returns false if there was an error. // Returns false if there was an error.
fn execute(&mut self, code: &str) -> bool { fn execute(&mut self, code: &str) -> bool {
let mut hs = v8::HandleScope::new(&mut self.0); let scope = &mut v8::HandleScope::new(&mut self.0);
let scope = hs.enter();
let context = v8::Context::new(scope); let context = v8::Context::new(scope);
let mut cs = v8::ContextScope::new(scope, context); let scope = &mut v8::ContextScope::new(scope, context);
let scope = cs.enter();
let source = v8::String::new(scope, code).unwrap(); let source = v8::String::new(scope, code).unwrap();
let mut script = v8::Script::compile(scope, context, source, None).unwrap(); let mut script = v8::Script::compile(scope, context, source, None).unwrap();
let r = script.run(scope, context); let r = script.run(scope, context);

File diff suppressed because it is too large Load diff

View file

@ -7,19 +7,5 @@ fn ui() {
env::set_var("DENO_TRYBUILD", "1"); env::set_var("DENO_TRYBUILD", "1");
let t = trybuild::TestCases::new(); let t = trybuild::TestCases::new();
t.compile_fail("tests/compile_fail/boxed_local.rs"); t.compile_fail("tests/compile_fail/*.rs");
t.compile_fail("tests/compile_fail/handle_scope_escape_lifetime.rs");
t.compile_fail("tests/compile_fail/handle_scope_lifetime_1.rs");
t.compile_fail("tests/compile_fail/handle_scope_lifetime_2.rs");
t.compile_fail("tests/compile_fail/handle_scope_lifetime_3.rs");
t.compile_fail("tests/compile_fail/handle_scope_lifetime_4.rs");
t.compile_fail("tests/compile_fail/try_catch_exception_lifetime.rs");
t.compile_fail("tests/compile_fail/try_catch_message_lifetime.rs");
// For unclear reasons rustc on Windows in Github Actions omits some
// diagnostic information, causing this test to fail. It might have something
// to do with this Rust issue: https://github.com/rust-lang/rust/issues/53081.
if cfg!(not(windows)) || env::var("GITHUB_ACTION").is_err() {
t.compile_fail("tests/compile_fail/handle_scope_escape_to_nowhere.rs");
}
} }