0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2024-12-23 15:50:11 -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()]
};
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() {
println!("clang_base_path {}", clang_base_path.display());
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::UniqueRef;
use crate::ArrayBuffer;
use crate::InIsolate;
use crate::HandleScope;
use crate::Isolate;
use crate::Local;
use crate::ToLocal;
extern "C" {
fn v8__ArrayBuffer__Allocator__NewDefaultAllocator() -> *mut Allocator;
@ -236,25 +235,31 @@ impl ArrayBuffer {
/// Allocated memory will be owned by a created ArrayBuffer and
/// will be deallocated when it is garbage-collected,
/// unless the object is externalized.
pub fn new<'sc>(
scope: &mut impl ToLocal<'sc>,
pub fn new<'s>(
scope: &mut HandleScope<'s>,
byte_length: usize,
) -> Local<'sc, ArrayBuffer> {
) -> Local<'s, ArrayBuffer> {
unsafe {
scope.cast_local(|scope| {
v8__ArrayBuffer__New__with_byte_length(scope.isolate(), byte_length)
scope.cast_local(|sd| {
v8__ArrayBuffer__New__with_byte_length(
sd.get_isolate_ptr(),
byte_length,
)
})
}
.unwrap()
}
pub fn with_backing_store<'sc>(
scope: &mut impl ToLocal<'sc>,
pub fn with_backing_store<'s>(
scope: &mut HandleScope<'s>,
backing_store: &SharedRef<BackingStore>,
) -> Local<'sc, ArrayBuffer> {
) -> Local<'s, ArrayBuffer> {
unsafe {
scope.cast_local(|scope| {
v8__ArrayBuffer__New__with_backing_store(scope.isolate(), backing_store)
scope.cast_local(|sd| {
v8__ArrayBuffer__New__with_backing_store(
sd.get_isolate_ptr(),
backing_store,
)
})
}
.unwrap()
@ -281,12 +286,12 @@ impl ArrayBuffer {
/// given isolate and re-try the allocation. If GCs do not help, then the
/// function will crash with an out-of-memory error.
pub fn new_backing_store(
scope: &mut impl InIsolate,
scope: &mut Isolate,
byte_length: usize,
) -> UniqueRef<BackingStore> {
unsafe {
UniqueRef::from_raw(v8__ArrayBuffer__NewBackingStore__with_byte_length(
scope.isolate(),
scope,
byte_length,
))
}

View file

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

View file

@ -1,10 +1,10 @@
// Copyright 2019-2020 the Deno authors. All rights reserved. MIT license.
use crate::isolate::Isolate;
use crate::Context;
use crate::HandleScope;
use crate::Local;
use crate::Object;
use crate::ObjectTemplate;
use crate::ToLocal;
use crate::Value;
use std::ptr::null;
@ -14,31 +14,30 @@ extern "C" {
templ: *const ObjectTemplate,
global_object: *const Value,
) -> *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;
}
impl 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;
unsafe {
scope
.cast_local(|scope| v8__Context__New(scope.isolate(), null(), null()))
.cast_local(|sd| v8__Context__New(sd.get_isolate_ptr(), null(), null()))
}
.unwrap()
}
/// Creates a new context using the object template as the template for
/// the global object.
pub fn new_from_template<'sc>(
scope: &mut impl ToLocal<'sc>,
pub fn new_from_template<'s>(
scope: &mut HandleScope<'s, ()>,
templ: Local<ObjectTemplate>,
) -> Local<'sc, Context> {
) -> Local<'s, Context> {
unsafe {
scope
.cast_local(|scope| v8__Context__New(scope.isolate(), &*templ, null()))
scope.cast_local(|sd| {
v8__Context__New(sd.get_isolate_ptr(), &*templ, null())
})
}
.unwrap()
}
@ -53,26 +52,10 @@ impl Context {
/// Please note that changes to global proxy object prototype most probably
/// would break VM---v8 expects only global object as a prototype of global
/// proxy object.
pub fn global<'sc>(
pub fn global<'s>(
&self,
scope: &mut impl ToLocal<'sc>,
) -> Local<'sc, Object> {
scope: &mut HandleScope<'s, ()>,
) -> Local<'s, Object> {
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 {
{ $source:ident for $type:ident } => {
impl<'sc> From<Local<'sc, $source>> for Local<'sc, $type> {
fn from(l: Local<'sc, $source>) -> Self {
impl<'s> From<Local<'s, $source>> for Local<'s, $type> {
fn from(l: Local<'s, $source>) -> Self {
unsafe { transmute(l) }
}
}
@ -35,9 +35,9 @@ macro_rules! impl_from {
macro_rules! impl_try_from {
{ $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;
fn try_from(l: Local<'sc, $source>) -> Result<Self, Self::Error> {
fn try_from(l: Local<'s, $source>) -> Result<Self, Self::Error> {
match l {
$value if $check => Ok(unsafe { transmute(l) }),
_ => Err(TryFromTypeError::new(stringify!($target)))
@ -49,21 +49,21 @@ macro_rules! impl_try_from {
macro_rules! impl_eq {
{ for $type:ident } => {
impl<'sc> Eq for Local<'sc, $type> {}
impl<'s> Eq for Local<'s, $type> {}
};
}
macro_rules! impl_partial_eq {
{ $rhs:ident for $type:ident use identity } => {
impl<'sc> PartialEq<Local<'sc, $rhs>> for Local<'sc, $type> {
fn eq(&self, other: &Local<'sc, $rhs>) -> bool {
impl<'s> PartialEq<Local<'s, $rhs>> for Local<'s, $type> {
fn eq(&self, other: &Local<'s, $rhs>) -> bool {
self.eq_identity((*other).into())
}
}
};
{ $rhs:ident for $type:ident use strict_equals } => {
impl<'sc> PartialEq<Local<'sc, $rhs>> for Local<'sc, $type> {
fn eq(&self, other: &Local<'sc, $rhs>) -> bool {
impl<'s> PartialEq<Local<'s, $rhs>> for Local<'s, $type> {
fn eq(&self, other: &Local<'s, $rhs>) -> bool {
self.strict_equals((*other).into())
}
}

View file

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

View file

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

View file

@ -2,11 +2,10 @@ use std::mem::transmute;
use std::ptr::NonNull;
use crate::Data;
use crate::InIsolate;
use crate::HandleScope;
use crate::Isolate;
use crate::IsolateHandle;
use crate::Local;
use crate::ToLocal;
extern "C" {
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
/// is non-empty, a new storage cell is created pointing to the same object,
/// and no flags are set.
pub fn new_from(
scope: &mut impl InIsolate,
other: impl AnyHandle<T>,
) -> Self {
let isolate = scope.isolate();
let other_value = other.read(isolate);
pub fn new_from(scope: &mut Isolate, other: impl AnyHandle<T>) -> Self {
let other_value = other.read(scope);
Self {
value: other_value
.map(|v| unsafe { transmute(v8__Global__New(isolate, transmute(v))) }),
isolate_handle: other_value.map(|_| isolate.thread_safe_handle()),
.map(|v| unsafe { transmute(v8__Global__New(scope, transmute(v))) }),
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.
pub fn get<'sc>(
pub fn get<'s>(
&self,
scope: &mut impl ToLocal<'sc>,
) -> Option<Local<'sc, T>> {
self.check_isolate(scope.isolate());
scope: &mut HandleScope<'s, ()>,
) -> Option<Local<'s, T>> {
self.check_isolate(scope);
self
.value
.map(|g| g.as_ptr() as *const Data)
.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
/// 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>) {
let isolate = scope.isolate();
self.check_isolate(isolate);
let other_value = other.read(isolate);
pub fn set(&mut self, scope: &mut Isolate, other: impl AnyHandle<T>) {
self.check_isolate(scope);
let other_value = other.read(scope);
match (&mut self.value, &other_value) {
(None, None) => {}
(target, None) => unsafe {
@ -99,17 +94,17 @@ impl<T> Global<T> {
(target, source) => unsafe {
v8__Global__Reset__2(
&mut *(target as *mut Option<NonNull<T>> as *mut *const Data),
isolate,
scope,
&*(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
/// 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);
}
@ -164,19 +159,19 @@ pub trait AnyHandle<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>> {
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>> {
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>> {
self.check_isolate(isolate);
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/denoland/deno/blob/v0.38.0/cli/inspector.rs
use crate::scope_traits::InIsolate;
use crate::support::int;
use crate::support::CxxVTable;
use crate::support::FieldOffset;
@ -834,7 +833,7 @@ pub struct V8Inspector(Opaque);
impl V8Inspector {
pub fn create<T>(
isolate: &mut impl InIsolate,
isolate: &mut Isolate,
client: &mut T,
) -> UniqueRef<V8Inspector>
where
@ -842,7 +841,7 @@ impl V8Inspector {
{
unsafe {
UniqueRef::from_raw(v8_inspector__V8Inspector__create(
isolate.isolate(),
isolate,
client.as_client_mut(),
))
}

View file

@ -2,10 +2,10 @@
use crate::isolate_create_params::raw;
use crate::isolate_create_params::CreateParams;
use crate::promise::PromiseRejectMessage;
use crate::scope::data::ScopeData;
use crate::support::Opaque;
use crate::Context;
use crate::Function;
use crate::InIsolate;
use crate::Local;
use crate::Message;
use crate::Module;
@ -103,10 +103,6 @@ extern "C" {
callback: InterruptCallback,
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__IsExecutionTerminating(isolate: *const Isolate) -> bool;
fn v8__Isolate__CancelTerminateExecution(isolate: *const Isolate);
@ -133,6 +129,10 @@ extern "C" {
pub struct Isolate(Opaque);
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
/// isolate.
///
@ -146,6 +146,7 @@ impl Isolate {
let (raw_create_params, create_param_allocations) = params.finalize();
let cxx_isolate = unsafe { v8__Isolate__New(&raw_create_params) };
let mut owned_isolate = OwnedIsolate::new(cxx_isolate);
ScopeData::new_root(&mut owned_isolate);
owned_isolate.create_annex(create_param_allocations);
owned_isolate
}
@ -165,18 +166,23 @@ impl Isolate {
) {
let annex_arc = Arc::new(IsolateAnnex::new(self, create_param_allocations));
let annex_ptr = Arc::into_raw(annex_arc);
unsafe { assert!(v8__Isolate__GetData(self, 0).is_null()) };
unsafe { v8__Isolate__SetData(self, 0, annex_ptr as *mut c_void) };
unsafe {
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 {
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 {
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> {
@ -186,22 +192,45 @@ impl Isolate {
annex_arc
}
/// Associate embedder-specific data with the isolate. |slot| has to be
/// between 0 and GetNumberOfDataSlots() - 1.
/// Associate embedder-specific data with the isolate. `slot` has to be
/// between 0 and `Isolate::get_number_of_data_slots()`.
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.
/// 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 {
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
/// 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 {
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.
@ -247,7 +276,7 @@ impl Isolate {
/// Sets this isolate as the entered one for the current thread.
/// Saves the previously entered one (if any), so that it can be
/// 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) }
}
@ -256,7 +285,7 @@ impl Isolate {
/// entered more than once.
///
/// Requires: self == Isolate::GetCurrent().
pub(crate) fn exit(&mut self) {
pub(crate) fn exit_isolate(&mut 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.
/// Any exceptions thrown by microtask callbacks are swallowed.
pub fn run_microtasks(&mut self) {
@ -348,11 +359,13 @@ impl Isolate {
/// Disposes the isolate. The isolate must not be entered by any
/// thread to be disposable.
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
// IsolateHandle that outlives the isolate will know that it can't call
// methods on the isolate.
let annex = self.get_annex_mut();
{
let _lock = annex.isolate_mutex.lock().unwrap();
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 {
fn drop(&mut self) {
unsafe { self.cxx_isolate.as_mut().dispose() }

View file

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

View file

@ -9,14 +9,11 @@
//! v8::V8::initialize_platform(platform);
//! v8::V8::initialize();
//!
//! let mut isolate = v8::Isolate::new(Default::default());
//!
//! let mut handle_scope = v8::HandleScope::new(&mut isolate);
//! let scope = handle_scope.enter();
//! let isolate = &mut v8::Isolate::new(Default::default());
//!
//! let scope = &mut v8::HandleScope::new(isolate);
//! let context = v8::Context::new(scope);
//! let mut context_scope = v8::ContextScope::new(scope, context);
//! let scope = context_scope.enter();
//! let scope = &mut v8::ContextScope::new(scope, context);
//!
//! let code = v8::String::new(scope, "'Hello' + ' World!'").unwrap();
//! println!("javascript code: {}", code.to_rust_string_lossy(scope));
@ -26,44 +23,6 @@
//! let result = result.to_string(scope).unwrap();
//! 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(dead_code)]
@ -82,7 +41,6 @@ mod exception;
mod external_references;
mod function;
mod global;
mod handle_scope;
mod isolate;
mod isolate_create_params;
mod local;
@ -95,7 +53,7 @@ mod primitives;
mod promise;
mod property_attribute;
mod proxy;
mod scope_traits;
mod scope;
mod script;
mod script_or_module;
mod shared_array_buffer;
@ -109,7 +67,6 @@ mod value;
pub mod inspector;
pub mod json;
pub mod scope;
pub mod script_compiler;
// This module is intentionally named "V8" rather than "v8" to match the
// C++ namespace "v8::V8".
@ -123,8 +80,6 @@ pub use external_references::ExternalReference;
pub use external_references::ExternalReferences;
pub use function::*;
pub use global::Global;
pub use handle_scope::EscapableHandleScope;
pub use handle_scope::HandleScope;
pub use isolate::HostImportModuleDynamicallyCallback;
pub use isolate::HostInitializeImportMetaObjectCallback;
pub use isolate::Isolate;
@ -148,10 +103,8 @@ pub use property_attribute::*;
pub use proxy::*;
pub use scope::CallbackScope;
pub use scope::ContextScope;
pub use scope::FunctionCallbackScope;
pub use scope::PropertyCallbackScope;
pub use scope::Scope;
pub use scope_traits::*;
pub use scope::EscapableHandleScope;
pub use scope::HandleScope;
pub use script::ScriptOrigin;
pub use snapshot::FunctionCodeHandling;
pub use snapshot::SnapshotCreator;

View file

@ -38,51 +38,51 @@ use std::ptr::NonNull;
/// never empty. In situations where empty handles are needed, use
/// Option<Local>.
#[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 {
*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.
/// 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
Local<'sc, A>: From<Self>,
Local<'s, A>: From<Self>,
{
transmute(other)
}
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> {
self.0
}
pub(crate) fn as_ptr(self) -> *const T {
self.0.as_ptr()
}
pub(crate) fn slice_into_raw(slice: &[Self]) -> &[*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;
fn deref(&self) -> &T {
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 {
unsafe { self.0.as_mut() }
}

View file

@ -9,10 +9,10 @@ use crate::support::MaybeBool;
use crate::support::ToCFn;
use crate::support::UnitType;
use crate::Context;
use crate::HandleScope;
use crate::Local;
use crate::Module;
use crate::String;
use crate::ToLocal;
use crate::Value;
/// 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
/// via |GetException|).
#[must_use]
pub fn evaluate<'sc>(
pub fn evaluate<'s>(
&self,
scope: &mut impl ToLocal<'sc>,
scope: &mut HandleScope<'s>,
context: Local<Context>,
) -> Option<Local<'sc, Value>> {
) -> Option<Local<'s, Value>> {
unsafe { scope.cast_local(|_| v8__Module__Evaluate(&*self, &*context)) }
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -1,8 +1,8 @@
use crate::Context;
use crate::HandleScope;
use crate::Local;
use crate::Object;
use crate::Proxy;
use crate::ToLocal;
use crate::Value;
extern "C" {
@ -18,28 +18,28 @@ extern "C" {
}
impl Proxy {
pub fn new<'sc>(
scope: &mut impl ToLocal<'sc>,
pub fn new<'s>(
scope: &mut HandleScope<'s>,
context: Local<Context>,
target: Local<Object>,
handler: Local<Object>,
) -> Option<Local<'sc, Proxy>> {
) -> Option<Local<'s, Proxy>> {
unsafe {
scope.cast_local(|_| v8__Proxy__New(&*context, &*target, &*handler))
}
}
pub fn get_handler<'sc>(
pub fn get_handler<'s>(
&mut self,
scope: &mut impl ToLocal<'sc>,
) -> Local<'sc, Value> {
scope: &mut HandleScope<'s>,
) -> Local<'s, Value> {
unsafe { scope.cast_local(|_| v8__Proxy__GetHandler(&*self)) }.unwrap()
}
pub fn get_target<'sc>(
pub fn get_target<'s>(
&mut self,
scope: &mut impl ToLocal<'sc>,
) -> Local<'sc, Value> {
scope: &mut HandleScope<'s>,
) -> Local<'s, Value> {
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::Context;
use crate::HandleScope;
use crate::Integer;
use crate::Local;
use crate::Script;
use crate::String;
use crate::ToLocal;
use crate::Value;
/// The origin, within a file, of a script.
#[repr(C)]
pub struct ScriptOrigin<'sc>([usize; 7], PhantomData<&'sc ()>);
pub struct ScriptOrigin<'s>([usize; 7], PhantomData<&'s ()>);
extern "C" {
fn v8__Script__Compile(
@ -42,18 +42,18 @@ extern "C" {
impl Script {
/// A shorthand for ScriptCompiler::Compile().
pub fn compile<'sc>(
scope: &mut impl ToLocal<'sc>,
pub fn compile<'s>(
scope: &mut HandleScope<'s>,
context: Local<Context>,
source: Local<String>,
origin: Option<&ScriptOrigin>,
) -> Option<Local<'sc, Script>> {
) -> Option<Local<'s, Script>> {
unsafe {
scope.cast_local(|_| {
v8__Script__Compile(
&*context,
&*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
/// context in which it was created (ScriptCompiler::CompileBound or
/// UnboundScript::BindToCurrentContext()).
pub fn run<'sc>(
pub fn run<'s>(
&mut self,
scope: &mut impl ToLocal<'sc>,
scope: &mut HandleScope<'s>,
context: Local<Context>,
) -> Option<Local<'sc, Value>> {
) -> Option<Local<'s, Value>> {
unsafe { scope.cast_local(|_| v8__Script__Run(self, &*context)) }
}
}
/// The origin, within a file, of a script.
impl<'sc> ScriptOrigin<'sc> {
impl<'s> ScriptOrigin<'s> {
#[allow(clippy::too_many_arguments)]
pub fn new(
resource_name: Local<'sc, Value>,
resource_line_offset: Local<'sc, Integer>,
resource_column_offset: Local<'sc, Integer>,
resource_is_shared_cross_origin: Local<'sc, Boolean>,
script_id: Local<'sc, Integer>,
source_map_url: Local<'sc, Value>,
resource_is_opaque: Local<'sc, Boolean>,
is_wasm: Local<'sc, Boolean>,
is_module: Local<'sc, Boolean>,
resource_name: Local<'s, Value>,
resource_line_offset: Local<'s, Integer>,
resource_column_offset: Local<'s, Integer>,
resource_is_shared_cross_origin: Local<'s, Boolean>,
script_id: Local<'s, Integer>,
source_map_url: Local<'s, Value>,
resource_is_opaque: Local<'s, Boolean>,
is_wasm: Local<'s, Boolean>,
is_module: Local<'s, Boolean>,
) -> Self {
unsafe {
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.
use std::mem::MaybeUninit;
use crate::HandleScope;
use crate::Isolate;
use crate::Local;
use crate::Module;
use crate::ScriptOrigin;
use crate::String;
use crate::ToLocal;
extern "C" {
fn v8__ScriptCompiler__Source__CONSTRUCT(
@ -77,10 +77,10 @@ pub enum NoCacheReason {
///
/// Corresponds to the ParseModule abstract operation in the ECMAScript
/// specification.
pub fn compile_module<'sc>(
scope: &mut impl ToLocal<'sc>,
pub fn compile_module<'s>(
scope: &mut HandleScope<'s>,
source: Source,
) -> Option<Local<'sc, Module>> {
) -> Option<Local<'s, Module>> {
compile_module2(
scope,
source,
@ -90,16 +90,16 @@ pub fn compile_module<'sc>(
}
/// Same as compile_module with more options.
pub fn compile_module2<'sc>(
scope: &mut impl ToLocal<'sc>,
pub fn compile_module2<'s>(
scope: &mut HandleScope<'s>,
mut source: Source,
options: CompileOptions,
no_cache_reason: NoCacheReason,
) -> Option<Local<'sc, Module>> {
) -> Option<Local<'s, Module>> {
unsafe {
scope.cast_local(|scope| {
scope.cast_local(|sd| {
v8__ScriptCompiler__CompileModule(
scope.isolate(),
sd.get_isolate_ptr(),
&mut source,
options,
no_cache_reason,

View file

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

View file

@ -1,4 +1,5 @@
use crate::external_references::ExternalReferences;
use crate::scope::data::ScopeData;
use crate::support::char;
use crate::support::int;
use crate::support::intptr_t;
@ -105,7 +106,7 @@ impl SnapshotCreator {
/// 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
/// 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) };
}
@ -115,6 +116,10 @@ impl SnapshotCreator {
&mut self,
function_code_handling: FunctionCodeHandling,
) -> Option<StartupData> {
{
let isolate = unsafe { &mut *v8__SnapshotCreator__GetIsolate(self) };
ScopeData::get_root_mut(isolate);
}
let blob =
unsafe { v8__SnapshotCreator__CreateBlob(self, function_code_handling) };
if blob.data.is_null() {
@ -134,6 +139,7 @@ impl SnapshotCreator {
pub unsafe fn get_owned_isolate(&mut self) -> OwnedIsolate {
let isolate_ptr = v8__SnapshotCreator__GetIsolate(self);
let mut owned_isolate = OwnedIsolate::new(isolate_ptr);
ScopeData::new_root(&mut owned_isolate);
owned_isolate.create_annex(Box::new(()));
owned_isolate
}

View file

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

View file

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

View file

@ -5,11 +5,10 @@ use std::mem::take;
use std::mem::MaybeUninit;
use crate::Context;
use crate::InIsolate;
use crate::HandleScope;
use crate::Isolate;
use crate::Local;
use crate::Message;
use crate::ToLocal;
use crate::Value;
extern "C" {
@ -72,10 +71,8 @@ impl<'tc> TryCatch<'tc> {
/// stack allocated because the memory location itself is compared against
/// JavaScript try/catch blocks.
#[allow(clippy::new_ret_no_self)]
pub fn new(scope: &mut impl InIsolate) -> TryCatchScope<'tc> {
TryCatchScope(TryCatchState::New {
isolate: scope.isolate(),
})
pub fn new(scope: &mut Isolate) -> TryCatchScope<'tc> {
TryCatchScope(TryCatchState::New { isolate: scope })
}
/// 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
/// 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.
pub fn exception<'sc>(
pub fn exception<'s>(
&self,
scope: &mut impl ToLocal<'sc>,
) -> Option<Local<'sc, Value>> {
scope: &mut HandleScope<'s>,
) -> Option<Local<'s, Value>> {
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
/// applies here too.
pub fn message<'sc>(
pub fn message<'s>(
&self,
scope: &mut impl ToLocal<'sc>,
) -> Option<Local<'sc, Message>> {
scope: &mut HandleScope<'s>,
) -> Option<Local<'s, Message>> {
unsafe { scope.cast_local(|_| v8__TryCatch__Message(&self.0)) }
}
/// Returns the .stack property of the thrown object. If no .stack
/// property is present an empty handle is returned.
pub fn stack_trace<'sc>(
pub fn stack_trace<'s>(
&self,
scope: &mut impl ToLocal<'sc>,
scope: &mut HandleScope<'s>,
context: Local<Context>,
) -> Option<Local<'sc, Value>> {
) -> Option<Local<'s, Value>> {
unsafe {
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.
use crate::ArrayBuffer;
use crate::HandleScope;
use crate::Local;
use crate::ToLocal;
use crate::Uint8Array;
extern "C" {
@ -13,12 +13,12 @@ extern "C" {
}
impl Uint8Array {
pub fn new<'sc>(
scope: &mut impl ToLocal<'sc>,
pub fn new<'s>(
scope: &mut HandleScope<'s>,
buf: Local<ArrayBuffer>,
byte_offset: usize,
length: usize,
) -> Option<Local<'sc, Uint8Array>> {
) -> Option<Local<'s, Uint8Array>> {
unsafe {
scope.cast_local(|_| v8__Uint8Array__New(&*buf, byte_offset, length))
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -3,13 +3,17 @@ use rusty_v8 as v8;
pub fn main() {
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 _exception = {
let mut hs = v8::HandleScope::new(&mut isolate);
let hs = hs.enter();
try_catch.message(hs).unwrap()
let _message = {
let mut scope3 = v8::HandleScope::new(&mut scope2);
let mut scope4 = v8::HandleScope::new(&mut scope3);
try_catch.message(&mut scope4).unwrap()
};
}

View file

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

View file

@ -39,11 +39,9 @@ impl CoreIsolate {
// Returns false if there was an error.
fn execute(&mut self, code: &str) -> bool {
let mut hs = v8::HandleScope::new(&mut self.0);
let scope = hs.enter();
let scope = &mut v8::HandleScope::new(&mut self.0);
let context = v8::Context::new(scope);
let mut cs = v8::ContextScope::new(scope, context);
let scope = cs.enter();
let scope = &mut v8::ContextScope::new(scope, context);
let source = v8::String::new(scope, code).unwrap();
let mut script = v8::Script::compile(scope, context, source, None).unwrap();
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");
let t = trybuild::TestCases::new();
t.compile_fail("tests/compile_fail/boxed_local.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");
}
t.compile_fail("tests/compile_fail/*.rs");
}