mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-12-23 15:50:11 -05:00
Get rid of HandleScope closure, add CallbackScope (#119)
This commit is contained in:
parent
57d13f7622
commit
ae4b48eb22
30 changed files with 806 additions and 376 deletions
|
@ -1,9 +1,9 @@
|
|||
use crate::support::Delete;
|
||||
use crate::support::Opaque;
|
||||
use crate::support::UniqueRef;
|
||||
use crate::HandleScope;
|
||||
use crate::Isolate;
|
||||
use crate::Local;
|
||||
use crate::ToLocal;
|
||||
|
||||
extern "C" {
|
||||
fn v8__ArrayBuffer__Allocator__NewDefaultAllocator() -> *mut Allocator;
|
||||
|
@ -117,13 +117,12 @@ impl ArrayBuffer {
|
|||
/// will be deallocated when it is garbage-collected,
|
||||
/// unless the object is externalized.
|
||||
pub fn new<'sc>(
|
||||
scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
byte_length: usize,
|
||||
) -> Local<'sc, ArrayBuffer> {
|
||||
unsafe {
|
||||
let ptr = v8__ArrayBuffer__New(scope.as_mut(), byte_length);
|
||||
Local::from_raw(ptr).unwrap()
|
||||
}
|
||||
let isolate = scope.isolate();
|
||||
let ptr = unsafe { v8__ArrayBuffer__New(isolate, byte_length) };
|
||||
unsafe { scope.to_local(ptr) }.unwrap()
|
||||
}
|
||||
|
||||
/// Data length in bytes.
|
||||
|
@ -139,12 +138,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<'sc>(
|
||||
scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
byte_length: usize,
|
||||
) -> UniqueRef<BackingStore> {
|
||||
unsafe {
|
||||
UniqueRef::from_raw(v8__ArrayBuffer__NewBackingStore(
|
||||
scope.as_mut(),
|
||||
scope.isolate(),
|
||||
byte_length,
|
||||
))
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ pub struct ArrayBufferView(Opaque);
|
|||
impl ArrayBufferView {
|
||||
/// Returns underlying ArrayBuffer.
|
||||
pub fn buffer<'sc>(&self) -> Option<Local<'sc, ArrayBuffer>> {
|
||||
unsafe { Local::from_raw(v8__ArrayBufferView__Buffer(self)) }
|
||||
unsafe { Local::from_raw_(v8__ArrayBufferView__Buffer(self)) }
|
||||
}
|
||||
|
||||
/// Size of a view in bytes.
|
||||
|
|
52
src/callback_scope.rs
Normal file
52
src/callback_scope.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
use crate::scope::{Scope, Scoped};
|
||||
use crate::Context;
|
||||
use crate::InIsolate;
|
||||
use crate::Isolate;
|
||||
use crate::Local;
|
||||
use crate::Message;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
pub trait GetIsolate
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
fn get_isolate(&mut self) -> &mut Isolate;
|
||||
}
|
||||
|
||||
impl GetIsolate for Message {
|
||||
fn get_isolate(&mut self) -> &mut Isolate {
|
||||
self.get_isolate()
|
||||
}
|
||||
}
|
||||
|
||||
impl GetIsolate for Context {
|
||||
fn get_isolate(&mut self) -> &mut Isolate {
|
||||
self.get_isolate()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CallbackScope<'s, T> {
|
||||
local: Local<'s, T>,
|
||||
}
|
||||
|
||||
unsafe impl<'s, T> Scoped<'s> for CallbackScope<'s, T> {
|
||||
type Args = Local<'s, T>;
|
||||
fn enter_scope(buf: &mut MaybeUninit<Self>, local: Local<'s, T>) {
|
||||
*buf = MaybeUninit::new(CallbackScope { local });
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, T> CallbackScope<'s, T> {
|
||||
pub fn new(local: Local<'s, T>) -> Scope<Self> {
|
||||
Scope::new(local)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, T> InIsolate for crate::scope::Entered<'s, CallbackScope<'s, T>>
|
||||
where
|
||||
T: GetIsolate,
|
||||
{
|
||||
fn isolate(&mut self) -> &mut Isolate {
|
||||
self.local.get_isolate()
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
use crate::isolate::Isolate;
|
||||
use crate::support::Opaque;
|
||||
use crate::HandleScope;
|
||||
use crate::Local;
|
||||
use crate::Object;
|
||||
use crate::ToLocal;
|
||||
|
||||
extern "C" {
|
||||
fn v8__Context__New(isolate: &Isolate) -> *mut Context;
|
||||
|
@ -19,9 +19,10 @@ extern "C" {
|
|||
pub struct Context(Opaque);
|
||||
|
||||
impl Context {
|
||||
pub fn new<'sc>(scope: &mut HandleScope<'sc>) -> Local<'sc, Context> {
|
||||
pub fn new<'sc>(scope: &mut impl ToLocal<'sc>) -> Local<'sc, Context> {
|
||||
// TODO: optional arguments;
|
||||
unsafe { Local::from_raw(v8__Context__New(scope.as_mut())).unwrap() }
|
||||
let ptr = unsafe { v8__Context__New(scope.isolate()) };
|
||||
unsafe { scope.to_local(ptr) }.unwrap()
|
||||
}
|
||||
|
||||
/// Returns the global proxy object.
|
||||
|
@ -34,8 +35,11 @@ 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>(&mut self) -> Local<'sc, Object> {
|
||||
unsafe { Local::from_raw(v8__Context__Global(&mut *self)).unwrap() }
|
||||
pub fn global<'sc>(
|
||||
&mut self,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
) -> Local<'sc, Object> {
|
||||
unsafe { scope.to_local(v8__Context__Global(&mut *self)) }.unwrap()
|
||||
}
|
||||
|
||||
/// Enter this context. After entering a context, all code compiled
|
||||
|
@ -53,6 +57,10 @@ impl Context {
|
|||
// TODO: enter/exit should be controlled by a scope.
|
||||
unsafe { v8__Context__Exit(self) };
|
||||
}
|
||||
|
||||
pub fn get_isolate(&mut self) -> &mut Isolate {
|
||||
unsafe { v8__Context__GetIsolate(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Isolate> for Context {
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
use crate::isolate::Isolate;
|
||||
use crate::support::int;
|
||||
use crate::support::Opaque;
|
||||
use crate::HandleScope;
|
||||
use crate::Local;
|
||||
use crate::String;
|
||||
use crate::ToLocal;
|
||||
use crate::Value;
|
||||
|
||||
extern "C" {
|
||||
|
@ -46,13 +46,12 @@ impl StackTrace {
|
|||
pub struct Message(Opaque);
|
||||
|
||||
impl Message {
|
||||
pub fn get<'sc>(&self, _scope: &mut HandleScope<'sc>) -> Local<'sc, String> {
|
||||
unsafe { Local::from_raw(v8__Message__Get(self)) }.unwrap()
|
||||
pub fn get<'sc>(&self, scope: &mut impl ToLocal<'sc>) -> Local<'sc, String> {
|
||||
unsafe { scope.to_local(v8__Message__Get(self)) }.unwrap()
|
||||
}
|
||||
|
||||
#[allow(clippy::mut_from_ref)]
|
||||
pub unsafe fn get_isolate(&self) -> &mut Isolate {
|
||||
v8__Message__GetIsolate(self)
|
||||
pub fn get_isolate(&mut self) -> &mut Isolate {
|
||||
unsafe { v8__Message__GetIsolate(self) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,59 +59,55 @@ impl Message {
|
|||
/// 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 HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
mut exception: Local<'sc, Value>,
|
||||
) -> Local<'sc, Message> {
|
||||
unsafe {
|
||||
Local::from_raw(v8__Exception__CreateMessage(
|
||||
scope.as_mut(),
|
||||
&mut *exception,
|
||||
))
|
||||
}
|
||||
.unwrap()
|
||||
let isolate = scope.isolate();
|
||||
let ptr = unsafe { v8__Exception__CreateMessage(isolate, &mut *exception) };
|
||||
unsafe { scope.to_local(ptr) }.unwrap()
|
||||
}
|
||||
|
||||
/// 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 HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
mut exception: Local<Value>,
|
||||
) -> Option<Local<'sc, StackTrace>> {
|
||||
unsafe { Local::from_raw(v8__Exception__GetStackTrace(&mut *exception)) }
|
||||
unsafe { scope.to_local(v8__Exception__GetStackTrace(&mut *exception)) }
|
||||
}
|
||||
|
||||
pub fn range_error<'sc>(
|
||||
_scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
mut message: Local<String>,
|
||||
) -> Local<'sc, Value> {
|
||||
unsafe { Local::from_raw(v8__Exception__RangeError(&mut *message)) }.unwrap()
|
||||
unsafe { scope.to_local(v8__Exception__RangeError(&mut *message)) }.unwrap()
|
||||
}
|
||||
|
||||
pub fn reference_error<'sc>(
|
||||
_scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
mut message: Local<String>,
|
||||
) -> Local<'sc, Value> {
|
||||
unsafe { Local::from_raw(v8__Exception__ReferenceError(&mut *message)) }
|
||||
unsafe { scope.to_local(v8__Exception__ReferenceError(&mut *message)) }
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn syntax_error<'sc>(
|
||||
_scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
mut message: Local<String>,
|
||||
) -> Local<'sc, Value> {
|
||||
unsafe { Local::from_raw(v8__Exception__SyntaxError(&mut *message)) }.unwrap()
|
||||
unsafe { scope.to_local(v8__Exception__SyntaxError(&mut *message)) }.unwrap()
|
||||
}
|
||||
|
||||
pub fn type_error<'sc>(
|
||||
_scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
mut message: Local<String>,
|
||||
) -> Local<'sc, Value> {
|
||||
unsafe { Local::from_raw(v8__Exception__TypeError(&mut *message)) }.unwrap()
|
||||
unsafe { scope.to_local(v8__Exception__TypeError(&mut *message)) }.unwrap()
|
||||
}
|
||||
|
||||
pub fn error<'sc>(
|
||||
_scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
mut message: Local<String>,
|
||||
) -> Local<'sc, Value> {
|
||||
unsafe { Local::from_raw(v8__Exception__Error(&mut *message)) }.unwrap()
|
||||
unsafe { scope.to_local(v8__Exception__Error(&mut *message)) }.unwrap()
|
||||
}
|
||||
|
|
|
@ -3,9 +3,10 @@ use std::mem::MaybeUninit;
|
|||
|
||||
use crate::support::{int, Opaque};
|
||||
use crate::Context;
|
||||
use crate::HandleScope;
|
||||
use crate::InIsolate;
|
||||
use crate::Isolate;
|
||||
use crate::Local;
|
||||
use crate::ToLocal;
|
||||
use crate::Value;
|
||||
|
||||
extern "C" {
|
||||
|
@ -62,8 +63,8 @@ impl<'cb> ReturnValue<'cb> {
|
|||
}
|
||||
|
||||
/// Convenience getter for Isolate
|
||||
pub fn get_isolate(&self) -> &Isolate {
|
||||
unsafe { v8__ReturnValue__GetIsolate(self).as_ref().unwrap() }
|
||||
pub fn get_isolate(&mut self) -> &mut Isolate {
|
||||
unsafe { &mut *v8__ReturnValue__GetIsolate(self) }
|
||||
}
|
||||
|
||||
/// Getter. Creates a new Local<> so it comes with a certain performance
|
||||
|
@ -71,9 +72,9 @@ impl<'cb> ReturnValue<'cb> {
|
|||
/// value.
|
||||
pub fn get<'sc>(
|
||||
&mut self,
|
||||
_scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
) -> Local<'sc, Value> {
|
||||
unsafe { Local::from_raw(v8__ReturnValue__Get(self)).unwrap() }
|
||||
unsafe { scope.to_local(v8__ReturnValue__Get(self)) }.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,6 +85,15 @@ impl<'cb> ReturnValue<'cb> {
|
|||
#[repr(C)]
|
||||
pub struct FunctionCallbackInfo(Opaque);
|
||||
|
||||
impl InIsolate for FunctionCallbackInfo {
|
||||
#[allow(clippy::cast_ref_to_mut)]
|
||||
fn isolate(&mut self) -> &mut Isolate {
|
||||
self.get_isolate()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ToLocal<'s> for FunctionCallbackInfo {}
|
||||
|
||||
impl FunctionCallbackInfo {
|
||||
/// The ReturnValue for the call.
|
||||
pub fn get_return_value(&self) -> ReturnValue {
|
||||
|
@ -96,8 +106,8 @@ impl FunctionCallbackInfo {
|
|||
|
||||
/// The current Isolate.
|
||||
#[allow(clippy::mut_from_ref)]
|
||||
pub unsafe fn get_isolate(&self) -> &mut Isolate {
|
||||
v8__FunctionCallbackInfo__GetIsolate(self)
|
||||
pub fn get_isolate(&mut self) -> &mut Isolate {
|
||||
unsafe { v8__FunctionCallbackInfo__GetIsolate(self) }
|
||||
}
|
||||
|
||||
/// The number of available arguments.
|
||||
|
@ -132,26 +142,22 @@ pub struct FunctionTemplate(Opaque);
|
|||
impl FunctionTemplate {
|
||||
/// Creates a function template.
|
||||
pub fn new<'sc>(
|
||||
scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
callback: extern "C" fn(&FunctionCallbackInfo),
|
||||
) -> Local<'sc, FunctionTemplate> {
|
||||
unsafe {
|
||||
Local::from_raw(v8__FunctionTemplate__New(scope.as_mut(), callback))
|
||||
.unwrap()
|
||||
}
|
||||
let ptr = unsafe { v8__FunctionTemplate__New(scope.isolate(), callback) };
|
||||
unsafe { scope.to_local(ptr) }.unwrap()
|
||||
}
|
||||
|
||||
/// Returns the unique function instance in the current execution context.
|
||||
pub fn get_function<'sc>(
|
||||
&mut self,
|
||||
_scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
mut context: Local<Context>,
|
||||
) -> Option<Local<'sc, Function>> {
|
||||
unsafe {
|
||||
Local::from_raw(v8__FunctionTemplate__GetFunction(
|
||||
&mut *self,
|
||||
&mut *context,
|
||||
))
|
||||
scope
|
||||
.to_local(v8__FunctionTemplate__GetFunction(&mut *self, &mut *context))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -165,16 +171,16 @@ impl Function {
|
|||
/// Create a function in the current execution context
|
||||
/// for a given FunctionCallback.
|
||||
pub fn new<'sc>(
|
||||
_scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
mut context: Local<Context>,
|
||||
callback: extern "C" fn(&FunctionCallbackInfo),
|
||||
) -> Option<Local<'sc, Function>> {
|
||||
unsafe { Local::from_raw(v8__Function__New(&mut *context, callback)) }
|
||||
unsafe { scope.to_local(v8__Function__New(&mut *context, callback)) }
|
||||
}
|
||||
|
||||
pub fn call<'sc>(
|
||||
&mut self,
|
||||
_scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
mut context: Local<Context>,
|
||||
mut recv: Local<Value>,
|
||||
arc: i32,
|
||||
|
@ -185,7 +191,7 @@ impl Function {
|
|||
argv_.push(&mut *arg);
|
||||
}
|
||||
unsafe {
|
||||
Local::from_raw(v8__Function__Call(
|
||||
scope.to_local(v8__Function__Call(
|
||||
&mut *self,
|
||||
&mut *context,
|
||||
&mut *recv,
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use std::mem::transmute;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use crate::HandleScope;
|
||||
use crate::InIsolate;
|
||||
use crate::Isolate;
|
||||
use crate::Local;
|
||||
use crate::ToLocal;
|
||||
use crate::Value;
|
||||
|
||||
extern "C" {
|
||||
|
@ -51,10 +52,10 @@ impl<T> Global<T> {
|
|||
/// is non-empty, a new storage cell is created pointing to the same object,
|
||||
/// and no flags are set.
|
||||
pub fn new_from(
|
||||
isolate: &mut impl AsMut<Isolate>,
|
||||
scope: &mut impl InIsolate,
|
||||
other: impl AnyHandle<T>,
|
||||
) -> Self {
|
||||
let isolate = isolate.as_mut();
|
||||
let isolate = scope.isolate();
|
||||
let other_value = other.read(isolate);
|
||||
Self {
|
||||
value: other_value
|
||||
|
@ -72,23 +73,19 @@ impl<T> Global<T> {
|
|||
/// Construct a Local<T> from this global handle.
|
||||
pub fn get<'sc>(
|
||||
&self,
|
||||
scope: &'_ mut (impl AsMut<Isolate> + AsMut<HandleScope<'sc>>),
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
) -> Option<Local<'sc, T>> {
|
||||
self.check_isolate(scope.as_mut());
|
||||
self.check_isolate(scope.isolate());
|
||||
match &self.value {
|
||||
None => None,
|
||||
Some(p) => unsafe { Local::from_raw(p.as_ptr()) },
|
||||
Some(p) => unsafe { scope.to_local(p.as_ptr()) },
|
||||
}
|
||||
}
|
||||
|
||||
/// 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,
|
||||
isolate: &mut impl AsMut<Isolate>,
|
||||
other: impl AnyHandle<T>,
|
||||
) {
|
||||
let isolate = isolate.as_mut();
|
||||
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);
|
||||
match (&mut self.value, &other_value) {
|
||||
|
@ -111,8 +108,8 @@ impl<T> Global<T> {
|
|||
|
||||
/// If non-empty, destroy the underlying storage cell
|
||||
/// IsEmpty() will return true after this call.
|
||||
pub fn reset(&mut self, isolate: &mut impl AsMut<Isolate>) {
|
||||
self.set(isolate, None);
|
||||
pub fn reset(&mut self, scope: &mut impl InIsolate) {
|
||||
self.set(scope, None);
|
||||
}
|
||||
|
||||
fn check_isolate(&self, other: &Isolate) {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use std::marker::PhantomData;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
use crate::isolate::Isolate;
|
||||
use crate::scope::Scope;
|
||||
use crate::scope::Scoped;
|
||||
use crate::InIsolate;
|
||||
use crate::Local;
|
||||
use crate::Value;
|
||||
|
||||
|
@ -30,101 +32,132 @@ extern "C" {
|
|||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct HandleScope<'sc>([usize; 3], PhantomData<&'sc mut ()>);
|
||||
pub struct HandleScope([usize; 3]);
|
||||
|
||||
impl<'sc> HandleScope<'sc> {
|
||||
pub fn enter(
|
||||
isolate: &mut impl AsMut<Isolate>,
|
||||
mut f: impl FnMut(&mut HandleScope<'_>) -> (),
|
||||
) {
|
||||
let isolate = isolate.as_mut();
|
||||
let mut scope: MaybeUninit<Self> = MaybeUninit::uninit();
|
||||
unsafe { v8__HandleScope__CONSTRUCT(&mut scope, isolate) };
|
||||
let scope = unsafe { &mut *(scope.as_mut_ptr()) };
|
||||
f(scope);
|
||||
|
||||
unsafe { v8__HandleScope__DESTRUCT(scope) };
|
||||
impl HandleScope {
|
||||
pub fn new(scope: &mut impl InIsolate) -> Scope<Self> {
|
||||
Scope::new(scope.isolate())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'sc> AsRef<HandleScope<'sc>> for HandleScope<'sc> {
|
||||
unsafe impl<'s> Scoped<'s> for HandleScope {
|
||||
type Args = &'s mut Isolate;
|
||||
|
||||
fn enter_scope(buf: &mut MaybeUninit<Self>, isolate: &mut Isolate) {
|
||||
unsafe { v8__HandleScope__CONSTRUCT(buf, isolate) };
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for HandleScope {
|
||||
fn drop(&mut self) {
|
||||
unsafe { v8__HandleScope__DESTRUCT(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<HandleScope> for HandleScope {
|
||||
fn as_ref(&self) -> &Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'sc> AsMut<HandleScope<'sc>> for HandleScope<'sc> {
|
||||
impl AsMut<HandleScope> for HandleScope {
|
||||
fn as_mut(&mut self) -> &mut Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'sc> AsRef<Isolate> for HandleScope<'sc> {
|
||||
impl AsRef<Isolate> for HandleScope {
|
||||
fn as_ref(&self) -> &Isolate {
|
||||
unsafe { v8__HandleScope__GetIsolate(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'sc> AsMut<Isolate> for HandleScope<'sc> {
|
||||
impl AsMut<Isolate> for HandleScope {
|
||||
fn as_mut(&mut self) -> &mut Isolate {
|
||||
unsafe { v8__HandleScope__GetIsolate(self) }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// A HandleScope which first allocates a handle in the current scope
|
||||
/// which will be later filled with the escape value.
|
||||
pub struct EscapableHandleScope<'sc>([usize; 4], PhantomData<&'sc mut ()>);
|
||||
#[repr(C)]
|
||||
pub struct EscapableHandleScope([usize; 4]);
|
||||
|
||||
impl<'sc> EscapableHandleScope<'sc> {
|
||||
pub fn new(isolate: &mut impl AsMut<Isolate>) -> Self {
|
||||
let isolate = isolate.as_mut();
|
||||
let mut scope: MaybeUninit<Self> = MaybeUninit::uninit();
|
||||
unsafe {
|
||||
v8__EscapableHandleScope__CONSTRUCT(&mut scope, isolate);
|
||||
scope.assume_init()
|
||||
}
|
||||
impl EscapableHandleScope {
|
||||
pub fn new(scope: &mut impl InIsolate) -> Scope<Self> {
|
||||
Scope::new(scope.isolate())
|
||||
}
|
||||
|
||||
/// Pushes the value into the previous scope and returns a handle to it.
|
||||
/// Cannot be called twice.
|
||||
pub fn escape<'parent>(
|
||||
&mut self,
|
||||
mut value: Local<'sc, Value>,
|
||||
) -> Local<'parent, Value> {
|
||||
pub fn escape<'parent, T>(&mut self, value: Local<T>) -> Local<'parent, T> {
|
||||
unsafe {
|
||||
Local::from_raw(v8__EscapableHandleScope__Escape(self, &mut *value))
|
||||
.unwrap()
|
||||
Local::from_raw_(v8__EscapableHandleScope__Escape(
|
||||
self,
|
||||
value.as_ptr() as *mut Value,
|
||||
) as *mut T)
|
||||
}
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'sc> Drop for EscapableHandleScope<'sc> {
|
||||
unsafe impl<'s> Scoped<'s> for EscapableHandleScope {
|
||||
type Args = &'s mut Isolate;
|
||||
|
||||
fn enter_scope(buf: &mut MaybeUninit<Self>, isolate: &mut Isolate) {
|
||||
unsafe { v8__EscapableHandleScope__CONSTRUCT(buf, isolate) };
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for EscapableHandleScope {
|
||||
fn drop(&mut self) {
|
||||
unsafe { v8__EscapableHandleScope__DESTRUCT(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'sc> AsRef<EscapableHandleScope<'sc>> for EscapableHandleScope<'sc> {
|
||||
impl AsRef<EscapableHandleScope> for EscapableHandleScope {
|
||||
fn as_ref(&self) -> &Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'sc> AsMut<EscapableHandleScope<'sc>> for EscapableHandleScope<'sc> {
|
||||
impl AsMut<EscapableHandleScope> for EscapableHandleScope {
|
||||
fn as_mut(&mut self) -> &mut Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'sc> AsRef<Isolate> for EscapableHandleScope<'sc> {
|
||||
impl AsRef<Isolate> for EscapableHandleScope {
|
||||
fn as_ref(&self) -> &Isolate {
|
||||
unsafe { v8__EscapableHandleScope__GetIsolate(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'sc> AsMut<Isolate> for EscapableHandleScope<'sc> {
|
||||
impl AsMut<Isolate> for EscapableHandleScope {
|
||||
fn as_mut(&mut self) -> &mut Isolate {
|
||||
unsafe { v8__EscapableHandleScope__GetIsolate(self) }
|
||||
}
|
||||
}
|
||||
|
||||
use crate::scope::Entered;
|
||||
|
||||
impl<'s> InIsolate for Entered<'s, HandleScope> {
|
||||
fn isolate(&mut self) -> &mut Isolate {
|
||||
unsafe { v8__HandleScope__GetIsolate(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> InIsolate for Entered<'s, EscapableHandleScope> {
|
||||
fn isolate(&mut self) -> &mut Isolate {
|
||||
unsafe { v8__EscapableHandleScope__GetIsolate(self) }
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToLocal<'sc>: InIsolate {
|
||||
unsafe fn to_local<T>(&mut self, ptr: *mut T) -> Option<Local<'sc, T>> {
|
||||
crate::Local::<'sc, T>::from_raw_(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ToLocal<'s> for crate::scope::Entered<'s, HandleScope> {}
|
||||
impl<'s> ToLocal<'s> for crate::scope::Entered<'s, EscapableHandleScope> {}
|
||||
|
|
|
@ -162,7 +162,7 @@ impl Isolate {
|
|||
) -> Local<'sc, Value> {
|
||||
unsafe {
|
||||
let ptr = v8__Isolate__ThrowException(self, &exception);
|
||||
Local::from_raw(ptr).unwrap()
|
||||
Local::from_raw_(ptr).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,6 +207,13 @@ impl DerefMut for OwnedIsolate {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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).
|
||||
fn isolate(&mut self) -> &mut Isolate;
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CreateParams(Opaque);
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ pub fn parse<'sc>(
|
|||
mut context: Local<'sc, Context>,
|
||||
mut json_string: Local<'sc, String>,
|
||||
) -> Option<Local<'sc, Value>> {
|
||||
unsafe { Local::from_raw(v8__JSON__Parse(&mut *context, &mut *json_string)) }
|
||||
unsafe { Local::from_raw_(v8__JSON__Parse(&mut *context, &mut *json_string)) }
|
||||
}
|
||||
|
||||
/// Tries to stringify the JSON-serializable object `json_object` and returns
|
||||
|
@ -32,6 +32,6 @@ pub fn stringify<'sc>(
|
|||
mut json_object: Local<'sc, Value>,
|
||||
) -> Option<Local<'sc, String>> {
|
||||
unsafe {
|
||||
Local::from_raw(v8__JSON__Stringify(&mut *context, &mut *json_object))
|
||||
Local::from_raw_(v8__JSON__Stringify(&mut *context, &mut *json_object))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ extern crate lazy_static;
|
|||
extern crate libc;
|
||||
|
||||
mod array_buffer;
|
||||
mod callback_scope;
|
||||
mod context;
|
||||
mod exception;
|
||||
mod function;
|
||||
|
@ -37,6 +38,7 @@ pub mod array_buffer_view;
|
|||
pub mod inspector;
|
||||
pub mod json;
|
||||
pub mod platform;
|
||||
pub mod scope;
|
||||
pub mod script_compiler;
|
||||
// This module is intentionally named "V8" rather than "v8" to match the
|
||||
// C++ namespace "v8::V8".
|
||||
|
@ -46,15 +48,15 @@ pub mod V8;
|
|||
pub use array_buffer::Allocator;
|
||||
pub use array_buffer::ArrayBuffer;
|
||||
pub use array_buffer::BackingStore;
|
||||
pub use callback_scope::CallbackScope;
|
||||
pub use context::Context;
|
||||
pub use exception::*;
|
||||
pub use function::{
|
||||
Function, FunctionCallbackInfo, FunctionTemplate, ReturnValue,
|
||||
};
|
||||
pub use global::Global;
|
||||
pub use handle_scope::{EscapableHandleScope, HandleScope};
|
||||
pub use isolate::Isolate;
|
||||
pub use isolate::OwnedIsolate;
|
||||
pub use handle_scope::{EscapableHandleScope, HandleScope, ToLocal};
|
||||
pub use isolate::{InIsolate, Isolate, OwnedIsolate};
|
||||
pub use local::Local;
|
||||
pub use locker::Locker;
|
||||
pub use module::*;
|
||||
|
|
|
@ -49,13 +49,17 @@ impl<'sc, T> Clone for Local<'sc, T> {
|
|||
}
|
||||
|
||||
impl<'sc, T> Local<'sc, T> {
|
||||
pub(crate) unsafe fn from_raw(ptr: *mut T) -> Option<Self> {
|
||||
pub(crate) unsafe fn from_raw_(ptr: *mut T) -> Option<Self> {
|
||||
Some(Self(NonNull::new(ptr)?, PhantomData))
|
||||
}
|
||||
|
||||
pub(crate) fn as_non_null(self) -> NonNull<T> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub(crate) fn as_ptr(self) -> *mut T {
|
||||
self.0.as_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'sc, T> Deref for Local<'sc, T> {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
use crate::isolate::Isolate;
|
||||
use crate::InIsolate;
|
||||
use crate::Isolate;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
extern "C" {
|
||||
|
@ -29,6 +30,12 @@ impl Locker {
|
|||
}
|
||||
}
|
||||
|
||||
impl InIsolate for Locker {
|
||||
fn isolate(&mut self) -> &mut Isolate {
|
||||
unsafe { &mut *self.isolate }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Locker {
|
||||
fn drop(&mut self) {
|
||||
unsafe { v8__Locker__DESTRUCT(self) }
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::support::Opaque;
|
|||
use crate::Context;
|
||||
use crate::Local;
|
||||
use crate::String;
|
||||
use crate::ToLocal;
|
||||
use crate::Value;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
|
@ -86,7 +87,7 @@ impl Module {
|
|||
|
||||
/// For a module in kErrored status, this returns the corresponding exception.
|
||||
pub fn get_exception(&self) -> Local<Value> {
|
||||
unsafe { Local::from_raw(v8__Module__GetException(self)).unwrap() }
|
||||
unsafe { Local::from_raw_(v8__Module__GetException(self)).unwrap() }
|
||||
}
|
||||
|
||||
/// Returns the number of modules requested by this module.
|
||||
|
@ -97,7 +98,7 @@ impl Module {
|
|||
/// Returns the ith module specifier in this module.
|
||||
/// i must be < self.get_module_requests_length() and >= 0.
|
||||
pub fn get_module_request(&self, i: usize) -> Local<String> {
|
||||
unsafe { Local::from_raw(v8__Module__GetModuleRequest(self, i)).unwrap() }
|
||||
unsafe { Local::from_raw_(v8__Module__GetModuleRequest(self, i)).unwrap() }
|
||||
}
|
||||
|
||||
/// Returns the source location (line number and column number) of the ith
|
||||
|
@ -161,10 +162,11 @@ impl Module {
|
|||
/// kErrored and propagate the thrown exception (which is then also available
|
||||
/// via |GetException|).
|
||||
#[must_use]
|
||||
pub fn evaluate(
|
||||
pub fn evaluate<'sc>(
|
||||
&mut self,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
mut context: Local<Context>,
|
||||
) -> Option<Local<Value>> {
|
||||
unsafe { Local::from_raw(v8__Module__Evaluate(&mut *self, &mut *context)) }
|
||||
) -> Option<Local<'sc, Value>> {
|
||||
unsafe { scope.to_local(v8__Module__Evaluate(&mut *self, &mut *context)) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::isolate::Isolate;
|
|||
use crate::support::Opaque;
|
||||
use crate::value::Value;
|
||||
use crate::Local;
|
||||
use crate::ToLocal;
|
||||
|
||||
extern "C" {
|
||||
fn v8__Number__New(isolate: *mut Isolate, value: f64) -> *mut Number;
|
||||
|
@ -22,13 +23,11 @@ pub struct Number(Opaque);
|
|||
|
||||
impl Number {
|
||||
pub fn new<'sc>(
|
||||
scope: &mut impl AsMut<Isolate>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
value: f64,
|
||||
) -> Local<'sc, Number> {
|
||||
unsafe {
|
||||
let local = v8__Number__New(scope.as_mut(), value);
|
||||
Local::from_raw(local).unwrap()
|
||||
}
|
||||
let local = unsafe { v8__Number__New(scope.isolate(), value) };
|
||||
unsafe { scope.to_local(local) }.unwrap()
|
||||
}
|
||||
|
||||
pub fn value(&self) -> f64 {
|
||||
|
@ -49,23 +48,19 @@ pub struct Integer(Opaque);
|
|||
|
||||
impl Integer {
|
||||
pub fn new<'sc>(
|
||||
scope: &mut impl AsMut<Isolate>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
value: i32,
|
||||
) -> Local<'sc, Integer> {
|
||||
unsafe {
|
||||
let local = v8__Integer__New(scope.as_mut(), value);
|
||||
Local::from_raw(local).unwrap()
|
||||
}
|
||||
let local = unsafe { v8__Integer__New(scope.isolate(), value) };
|
||||
unsafe { scope.to_local(local) }.unwrap()
|
||||
}
|
||||
|
||||
pub fn new_from_unsigned<'sc>(
|
||||
scope: &mut impl AsMut<Isolate>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
value: u32,
|
||||
) -> Local<'sc, Integer> {
|
||||
unsafe {
|
||||
let local = v8__Integer__NewFromUnsigned(scope.as_mut(), value);
|
||||
Local::from_raw(local).unwrap()
|
||||
}
|
||||
let local = unsafe { v8__Integer__NewFromUnsigned(scope.isolate(), value) };
|
||||
unsafe { scope.to_local(local) }.unwrap()
|
||||
}
|
||||
|
||||
pub fn value(&self) -> i64 {
|
||||
|
|
|
@ -4,9 +4,9 @@ use crate::isolate::Isolate;
|
|||
use crate::support::MaybeBool;
|
||||
use crate::support::Opaque;
|
||||
use crate::Context;
|
||||
use crate::HandleScope;
|
||||
use crate::Local;
|
||||
use crate::Name;
|
||||
use crate::ToLocal;
|
||||
use crate::Value;
|
||||
|
||||
/// A JavaScript object (ECMA-262, 4.3.3)
|
||||
|
@ -45,7 +45,7 @@ impl Object {
|
|||
/// All properties will be created as enumerable, configurable
|
||||
/// and writable properties.
|
||||
pub fn new<'sc>(
|
||||
scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
mut prototype_or_null: Local<'sc, Value>,
|
||||
names: Vec<Local<'sc, Name>>,
|
||||
values: Vec<Local<'sc, Value>>,
|
||||
|
@ -62,16 +62,16 @@ impl Object {
|
|||
let n = &mut *value;
|
||||
values_.push(n);
|
||||
}
|
||||
unsafe {
|
||||
Local::from_raw(v8__Object__New(
|
||||
scope.as_mut(),
|
||||
let ptr = unsafe {
|
||||
v8__Object__New(
|
||||
scope.isolate(),
|
||||
&mut *prototype_or_null,
|
||||
names_.as_mut_ptr(),
|
||||
values_.as_mut_ptr(),
|
||||
length,
|
||||
))
|
||||
.unwrap()
|
||||
}
|
||||
)
|
||||
};
|
||||
unsafe { scope.to_local(ptr) }.unwrap()
|
||||
}
|
||||
|
||||
/// Implements CreateDataProperty (ECMA-262, 7.3.4).
|
||||
|
@ -92,21 +92,18 @@ impl Object {
|
|||
|
||||
pub fn get<'a>(
|
||||
&self,
|
||||
scope: &mut impl ToLocal<'a>,
|
||||
context: Local<Context>,
|
||||
key: Local<Value>,
|
||||
) -> Option<Local<'a, Value>> {
|
||||
unsafe {
|
||||
let ptr = v8__Object__Get(self, &*context, &*key);
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(Local::from_raw(ptr).unwrap())
|
||||
}
|
||||
scope.to_local(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the isolate to which the Object belongs to.
|
||||
pub fn get_isolate(&self) -> &Isolate {
|
||||
pub fn get_isolate(&mut self) -> &Isolate {
|
||||
unsafe { v8__Object__GetIsolate(self) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
use crate::support::int;
|
||||
use crate::support::Opaque;
|
||||
use crate::HandleScope;
|
||||
use crate::Isolate;
|
||||
use crate::Local;
|
||||
use crate::Primitive;
|
||||
use crate::ToLocal;
|
||||
|
||||
extern "C" {
|
||||
fn v8__PrimitiveArray__New(
|
||||
|
@ -38,13 +38,12 @@ pub struct PrimitiveArray(Opaque);
|
|||
|
||||
impl PrimitiveArray {
|
||||
pub fn new<'sc>(
|
||||
scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
length: usize,
|
||||
) -> Local<'sc, PrimitiveArray> {
|
||||
unsafe {
|
||||
let ptr = v8__PrimitiveArray__New(scope.as_mut(), length as int);
|
||||
Local::from_raw(ptr).unwrap()
|
||||
}
|
||||
let ptr =
|
||||
unsafe { v8__PrimitiveArray__New(scope.isolate(), length as int) };
|
||||
unsafe { scope.to_local(ptr) }.unwrap()
|
||||
}
|
||||
|
||||
pub fn length(&self) -> usize {
|
||||
|
@ -53,23 +52,22 @@ impl PrimitiveArray {
|
|||
|
||||
pub fn set<'sc>(
|
||||
&self,
|
||||
scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
index: usize,
|
||||
item: Local<'_, Primitive>,
|
||||
) {
|
||||
unsafe {
|
||||
v8__PrimitiveArray__Set(self, scope.as_mut(), index as int, &item)
|
||||
v8__PrimitiveArray__Set(self, scope.isolate(), index as int, &item)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get<'sc>(
|
||||
&self,
|
||||
scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
index: usize,
|
||||
) -> Local<'sc, Primitive> {
|
||||
unsafe {
|
||||
let ptr = v8__PrimitiveArray__Get(self, scope.as_mut(), index as int);
|
||||
Local::from_raw(ptr).unwrap()
|
||||
}
|
||||
let ptr =
|
||||
unsafe { v8__PrimitiveArray__Get(self, scope.isolate(), index as int) };
|
||||
unsafe { scope.to_local(ptr) }.unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::ops::Deref;
|
|||
use crate::isolate::Isolate;
|
||||
use crate::support::Opaque;
|
||||
use crate::Local;
|
||||
use crate::ToLocal;
|
||||
use crate::Value;
|
||||
|
||||
/// The superclass of primitive values. See ECMA-262 4.3.2.
|
||||
|
@ -28,22 +29,26 @@ extern "C" {
|
|||
fn v8__False(isolate: *mut Isolate) -> *mut Boolean;
|
||||
}
|
||||
|
||||
pub fn new_null<'sc>(scope: &mut impl AsMut<Isolate>) -> Local<'sc, Primitive> {
|
||||
unsafe { Local::from_raw(v8__Null(scope.as_mut())) }.unwrap()
|
||||
pub fn new_null<'sc>(scope: &mut impl ToLocal<'sc>) -> Local<'sc, Primitive> {
|
||||
let ptr = unsafe { v8__Null(scope.isolate()) };
|
||||
unsafe { scope.to_local(ptr) }.unwrap()
|
||||
}
|
||||
|
||||
pub fn new_undefined<'sc>(
|
||||
scope: &mut impl AsMut<Isolate>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
) -> Local<'sc, Primitive> {
|
||||
unsafe { Local::from_raw(v8__Undefined(scope.as_mut())) }.unwrap()
|
||||
let ptr = unsafe { v8__Undefined(scope.isolate()) };
|
||||
unsafe { scope.to_local(ptr) }.unwrap()
|
||||
}
|
||||
|
||||
pub fn new_true<'sc>(scope: &mut impl AsMut<Isolate>) -> Local<'sc, Boolean> {
|
||||
unsafe { Local::from_raw(v8__True(scope.as_mut())) }.unwrap()
|
||||
pub fn new_true<'sc>(scope: &mut impl ToLocal<'sc>) -> Local<'sc, Boolean> {
|
||||
let ptr = unsafe { v8__True(scope.isolate()) };
|
||||
unsafe { scope.to_local(ptr) }.unwrap()
|
||||
}
|
||||
|
||||
pub fn new_false<'sc>(scope: &mut impl AsMut<Isolate>) -> Local<'sc, Boolean> {
|
||||
unsafe { Local::from_raw(v8__False(scope.as_mut())) }.unwrap()
|
||||
pub fn new_false<'sc>(scope: &mut impl ToLocal<'sc>) -> Local<'sc, Boolean> {
|
||||
let ptr = unsafe { v8__False(scope.isolate()) };
|
||||
unsafe { scope.to_local(ptr) }.unwrap()
|
||||
}
|
||||
|
||||
impl Deref for Primitive {
|
||||
|
|
|
@ -4,8 +4,8 @@ use crate::support::MaybeBool;
|
|||
use crate::support::Opaque;
|
||||
use crate::Context;
|
||||
use crate::Function;
|
||||
use crate::HandleScope;
|
||||
use crate::Local;
|
||||
use crate::ToLocal;
|
||||
use crate::Value;
|
||||
|
||||
extern "C" {
|
||||
|
@ -82,9 +82,9 @@ impl Promise {
|
|||
/// be pending.
|
||||
pub fn result<'sc>(
|
||||
&mut self,
|
||||
_scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
) -> Local<'sc, Value> {
|
||||
unsafe { Local::from_raw(v8__Promise__Result(&mut *self)).unwrap() }
|
||||
unsafe { scope.to_local(v8__Promise__Result(&mut *self)) }.unwrap()
|
||||
}
|
||||
|
||||
/// Register a rejection handler with a promise.
|
||||
|
@ -96,7 +96,7 @@ impl Promise {
|
|||
mut handler: Local<'sc, Function>,
|
||||
) -> Option<Local<'sc, Promise>> {
|
||||
unsafe {
|
||||
Local::from_raw(v8__Promise__Catch(
|
||||
Local::from_raw_(v8__Promise__Catch(
|
||||
&mut *self,
|
||||
&mut *context,
|
||||
&mut *handler,
|
||||
|
@ -113,7 +113,7 @@ impl Promise {
|
|||
mut handler: Local<'sc, Function>,
|
||||
) -> Option<Local<'sc, Promise>> {
|
||||
unsafe {
|
||||
Local::from_raw(v8__Promise__Then(
|
||||
Local::from_raw_(v8__Promise__Then(
|
||||
&mut *self,
|
||||
&mut *context,
|
||||
&mut *handler,
|
||||
|
@ -132,7 +132,7 @@ impl Promise {
|
|||
mut on_rejected: Local<'sc, Function>,
|
||||
) -> Option<Local<'sc, Promise>> {
|
||||
unsafe {
|
||||
Local::from_raw(v8__Promise__Then2(
|
||||
Local::from_raw_(v8__Promise__Then2(
|
||||
&mut *self,
|
||||
&mut *context,
|
||||
&mut *on_fulfilled,
|
||||
|
@ -148,20 +148,19 @@ pub struct PromiseResolver(Opaque);
|
|||
impl PromiseResolver {
|
||||
/// Create a new resolver, along with an associated promise in pending state.
|
||||
pub fn new<'sc>(
|
||||
_scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
mut context: Local<'sc, Context>,
|
||||
) -> Option<Local<'sc, PromiseResolver>> {
|
||||
unsafe { Local::from_raw(v8__Promise__Resolver__New(&mut *context)) }
|
||||
unsafe { scope.to_local(v8__Promise__Resolver__New(&mut *context)) }
|
||||
}
|
||||
|
||||
/// Extract the associated promise.
|
||||
pub fn get_promise<'sc>(
|
||||
&mut self,
|
||||
_scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
) -> Local<'sc, Promise> {
|
||||
unsafe {
|
||||
Local::from_raw(v8__Promise__Resolver__GetPromise(&mut *self)).unwrap()
|
||||
}
|
||||
unsafe { scope.to_local(v8__Promise__Resolver__GetPromise(&mut *self)) }
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Resolve the associated promise with a given value.
|
||||
|
@ -206,7 +205,7 @@ pub struct PromiseRejectMessage<'msg>([usize; 3], PhantomData<&'msg ()>);
|
|||
impl<'msg> PromiseRejectMessage<'msg> {
|
||||
pub fn get_promise(&self) -> Local<'msg, Promise> {
|
||||
unsafe {
|
||||
Local::from_raw(v8__PromiseRejectMessage__GetPromise(self)).unwrap()
|
||||
Local::from_raw_(v8__PromiseRejectMessage__GetPromise(self)).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,7 +215,7 @@ impl<'msg> PromiseRejectMessage<'msg> {
|
|||
|
||||
pub fn get_value(&self) -> Local<'msg, Value> {
|
||||
unsafe {
|
||||
Local::from_raw(v8__PromiseRejectMessage__GetValue(self)).unwrap()
|
||||
Local::from_raw_(v8__PromiseRejectMessage__GetValue(self)).unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ use crate::support::Opaque;
|
|||
use crate::Local;
|
||||
use crate::Object;
|
||||
use crate::ReturnValue;
|
||||
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
extern "C" {
|
||||
|
@ -30,11 +31,11 @@ impl PropertyCallbackInfo {
|
|||
}
|
||||
|
||||
#[allow(clippy::mut_from_ref)]
|
||||
pub unsafe fn get_isolate(&self) -> &mut Isolate {
|
||||
v8__PropertyCallbackInfo__GetIsolate(self)
|
||||
pub fn get_isolate(&mut self) -> &mut Isolate {
|
||||
unsafe { v8__PropertyCallbackInfo__GetIsolate(self) }
|
||||
}
|
||||
|
||||
pub fn this(&self) -> Local<Object> {
|
||||
unsafe { Local::from_raw(v8__PropertyCallbackInfo__This(self)).unwrap() }
|
||||
unsafe { Local::from_raw_(v8__PropertyCallbackInfo__This(self)).unwrap() }
|
||||
}
|
||||
}
|
||||
|
|
149
src/scope.rs
Normal file
149
src/scope.rs
Normal file
|
@ -0,0 +1,149 @@
|
|||
use std::marker::PhantomData;
|
||||
use std::mem::size_of;
|
||||
use std::mem::take;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ops::Deref;
|
||||
use std::ops::DerefMut;
|
||||
|
||||
// Note: the 's lifetime is there to ensure that after entering a scope once,
|
||||
// the same scope object can't ever be entered again.
|
||||
|
||||
/// A trait for defining scoped objects.
|
||||
pub unsafe trait Scoped<'s>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
type Args;
|
||||
fn enter_scope(buf: &mut MaybeUninit<Self>, args: Self::Args) -> ();
|
||||
}
|
||||
|
||||
/// A RAII scope wrapper object that will, when the `enter()` method is called,
|
||||
/// initialize and activate the guarded object.
|
||||
pub struct Scope<'s, S>(ScopeState<'s, S>)
|
||||
where
|
||||
S: Scoped<'s>;
|
||||
|
||||
enum ScopeState<'s, S>
|
||||
where
|
||||
S: Scoped<'s>,
|
||||
{
|
||||
Empty,
|
||||
New(S::Args),
|
||||
Uninit(MaybeUninit<S>),
|
||||
Ready(Entered<'s, S>),
|
||||
}
|
||||
|
||||
/// A wrapper around the an instantiated and entered scope object.
|
||||
#[repr(transparent)]
|
||||
pub struct Entered<'s, S>(S, PhantomData<&'s ()>);
|
||||
|
||||
impl<'s, S> Scope<'s, S>
|
||||
where
|
||||
S: Scoped<'s>,
|
||||
{
|
||||
/// Create a new Scope object in unentered state.
|
||||
pub(crate) fn new(args: S::Args) -> Self {
|
||||
Self(ScopeState::New(args))
|
||||
}
|
||||
|
||||
/// Initializes the guarded object and returns a mutable reference to it.
|
||||
/// A scope can only be entered once.
|
||||
pub fn enter(&'s mut self) -> &'s mut Entered<S> {
|
||||
assert_eq!(size_of::<S>(), size_of::<MaybeUninit<S>>());
|
||||
assert_eq!(size_of::<S>(), size_of::<Entered<S>>());
|
||||
|
||||
use ScopeState::*;
|
||||
let state = &mut self.0;
|
||||
|
||||
let args = match take(state) {
|
||||
New(f) => f,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
*state = Uninit(MaybeUninit::uninit());
|
||||
let buf = match state {
|
||||
Uninit(b) => b,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
S::enter_scope(buf, args);
|
||||
|
||||
*state = match take(state) {
|
||||
Uninit(b) => Ready(unsafe { b.assume_init() }.into()),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
match state {
|
||||
Ready(v) => &mut *v,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, S> Default for ScopeState<'s, S>
|
||||
where
|
||||
S: Scoped<'s>,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self::Empty
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, S> From<S> for Entered<'s, S> {
|
||||
fn from(value: S) -> Self {
|
||||
Self(value, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, S> Deref for Entered<'s, S> {
|
||||
type Target = S;
|
||||
fn deref(&self) -> &S {
|
||||
unsafe { &*(self as *const _ as *const S) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, S> DerefMut for Entered<'s, S> {
|
||||
fn deref_mut(&mut self) -> &mut S {
|
||||
unsafe { &mut *(self as *mut _ as *mut S) }
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
impl<'s, S, T> AsRef<T> for Entered<'s, S>
|
||||
where
|
||||
S: AsRef<T>,
|
||||
{
|
||||
fn as_ref(&self) -> &T {
|
||||
self.deref().as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, S, T> AsMut<T> for Entered<'s, S>
|
||||
where
|
||||
S: AsMut<T>,
|
||||
{
|
||||
fn as_mut(&mut self) -> &mut T {
|
||||
self.deref_mut().as_mut()
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
impl<'s, S, T> AsRef<Entered<'s, T>> for Entered<'s, S>
|
||||
where
|
||||
S: AsRef<T>,
|
||||
{
|
||||
fn as_ref(&self) -> &Entered<'s, T> {
|
||||
let t: &T = self.deref().as_ref();
|
||||
unsafe { &*(t as *const _ as *const Entered<'s, T>) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, S, T> AsMut<Entered<'s, T>> for Entered<'s, S>
|
||||
where
|
||||
S: AsMut<T>,
|
||||
{
|
||||
fn as_mut(&mut self) -> &mut Entered<'s, T> {
|
||||
let t: &mut T = self.deref_mut().as_mut();
|
||||
unsafe { &mut *(t as *mut _ as *mut Entered<'s, T>) }
|
||||
}
|
||||
}
|
|
@ -5,10 +5,10 @@ use std::ptr::null;
|
|||
use crate::support::Opaque;
|
||||
use crate::Boolean;
|
||||
use crate::Context;
|
||||
use crate::HandleScope;
|
||||
use crate::Integer;
|
||||
use crate::Local;
|
||||
use crate::String;
|
||||
use crate::ToLocal;
|
||||
use crate::Value;
|
||||
|
||||
/// The origin, within a file, of a script.
|
||||
|
@ -45,20 +45,21 @@ pub struct Script(Opaque);
|
|||
impl Script {
|
||||
/// A shorthand for ScriptCompiler::Compile().
|
||||
pub fn compile<'sc>(
|
||||
_scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
mut context: Local<Context>,
|
||||
mut source: Local<String>,
|
||||
origin: Option<&ScriptOrigin>,
|
||||
) -> Option<Local<'sc, Script>> {
|
||||
// TODO: use the type system to enforce that a Context has been entered.
|
||||
// TODO: `context` and `source` probably shouldn't be mut.
|
||||
unsafe {
|
||||
Local::from_raw(v8__Script__Compile(
|
||||
let ptr = unsafe {
|
||||
v8__Script__Compile(
|
||||
&mut *context,
|
||||
&mut *source,
|
||||
origin.map(|r| r as *const _).unwrap_or(null()),
|
||||
))
|
||||
}
|
||||
)
|
||||
};
|
||||
unsafe { scope.to_local(ptr) }
|
||||
}
|
||||
|
||||
/// Runs the script returning the resulting value. It will be run in the
|
||||
|
@ -66,10 +67,10 @@ impl Script {
|
|||
/// UnboundScript::BindToCurrentContext()).
|
||||
pub fn run<'sc>(
|
||||
&mut self,
|
||||
_scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
mut context: Local<Context>,
|
||||
) -> Option<Local<'sc, Value>> {
|
||||
unsafe { Local::from_raw(v8__Script__Run(self, &mut *context)) }
|
||||
unsafe { scope.to_local(v8__Script__Run(self, &mut *context)) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -76,10 +76,10 @@ pub enum NoCacheReason {
|
|||
///
|
||||
/// Corresponds to the ParseModule abstract operation in the ECMAScript
|
||||
/// specification.
|
||||
pub fn compile_module(
|
||||
pub fn compile_module<'a>(
|
||||
isolate: &Isolate,
|
||||
source: Source,
|
||||
) -> Option<Local<Module>> {
|
||||
) -> Option<Local<'a, Module>> {
|
||||
compile_module2(
|
||||
isolate,
|
||||
source,
|
||||
|
@ -89,14 +89,14 @@ pub fn compile_module(
|
|||
}
|
||||
|
||||
/// Same as compile_module with more options.
|
||||
pub fn compile_module2(
|
||||
pub fn compile_module2<'a>(
|
||||
isolate: &Isolate,
|
||||
source: Source,
|
||||
options: CompileOptions,
|
||||
no_cache_reason: NoCacheReason,
|
||||
) -> Option<Local<Module>> {
|
||||
) -> Option<Local<'a, Module>> {
|
||||
unsafe {
|
||||
Local::from_raw(v8__ScriptCompiler__CompileModule(
|
||||
Local::from_raw_(v8__ScriptCompiler__CompileModule(
|
||||
isolate,
|
||||
&source,
|
||||
options,
|
||||
|
|
|
@ -25,7 +25,7 @@ impl ScriptOrModule {
|
|||
pub fn get_resource_name(&self) -> Local<'_, Value> {
|
||||
unsafe {
|
||||
let ptr = v8__ScriptOrModule__GetResourceName(self);
|
||||
Local::from_raw(ptr).unwrap()
|
||||
Local::from_raw_(ptr).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ impl ScriptOrModule {
|
|||
pub fn get_host_defined_options(&self) -> Local<'_, PrimitiveArray> {
|
||||
unsafe {
|
||||
let ptr = v8__ScriptOrModule__GetHostDefinedOptions(self);
|
||||
Local::from_raw(ptr).unwrap()
|
||||
Local::from_raw_(ptr).unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,13 @@ use std::mem::forget;
|
|||
use std::ops::Deref;
|
||||
use std::slice;
|
||||
|
||||
use crate::isolate::Isolate;
|
||||
use crate::support::char;
|
||||
use crate::support::int;
|
||||
use crate::support::Opaque;
|
||||
use crate::InIsolate;
|
||||
use crate::Isolate;
|
||||
use crate::Local;
|
||||
use crate::ToLocal;
|
||||
use crate::Value;
|
||||
|
||||
extern "C" {
|
||||
|
@ -66,19 +68,19 @@ pub struct String(Opaque);
|
|||
|
||||
impl String {
|
||||
pub fn new_from_utf8<'sc>(
|
||||
scope: &mut impl AsMut<Isolate>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
buffer: &[u8],
|
||||
new_type: NewStringType,
|
||||
) -> Option<Local<'sc, String>> {
|
||||
unsafe {
|
||||
let ptr = v8__String__NewFromUtf8(
|
||||
scope.as_mut(),
|
||||
let ptr = unsafe {
|
||||
v8__String__NewFromUtf8(
|
||||
scope.isolate(),
|
||||
buffer.as_ptr() as *const char,
|
||||
new_type,
|
||||
buffer.len().try_into().ok()?,
|
||||
);
|
||||
Local::from_raw(ptr)
|
||||
}
|
||||
)
|
||||
};
|
||||
unsafe { scope.to_local(ptr) }
|
||||
}
|
||||
|
||||
/// Returns the number of characters (UTF-16 code units) in this string.
|
||||
|
@ -88,13 +90,13 @@ impl String {
|
|||
|
||||
/// Returns the number of bytes in the UTF-8 encoded representation of this
|
||||
/// string.
|
||||
pub fn utf8_length(&self, isolate: &mut impl AsMut<Isolate>) -> usize {
|
||||
unsafe { v8__String__Utf8Length(self, isolate.as_mut()) as usize }
|
||||
pub fn utf8_length(&self, scope: &mut impl InIsolate) -> usize {
|
||||
unsafe { v8__String__Utf8Length(self, scope.isolate()) as usize }
|
||||
}
|
||||
|
||||
pub fn write_utf8(
|
||||
&self,
|
||||
isolate: &mut Isolate,
|
||||
scope: &mut impl InIsolate,
|
||||
buffer: &mut [u8],
|
||||
nchars_ref: Option<&mut usize>,
|
||||
options: WriteOptions,
|
||||
|
@ -103,7 +105,7 @@ impl String {
|
|||
let bytes = unsafe {
|
||||
v8__String__WriteUtf8(
|
||||
self,
|
||||
isolate,
|
||||
scope.isolate(),
|
||||
buffer.as_mut_ptr() as *mut char,
|
||||
buffer.len().try_into().unwrap_or(int::max_value()),
|
||||
&mut nchars_ref_int,
|
||||
|
@ -118,7 +120,7 @@ impl String {
|
|||
|
||||
// Convenience function not present in the original V8 API.
|
||||
pub fn new<'sc>(
|
||||
scope: &mut impl AsMut<Isolate>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
value: &str,
|
||||
) -> Option<Local<'sc, String>> {
|
||||
Self::new_from_utf8(scope, value.as_ref(), NewStringType::Normal)
|
||||
|
@ -127,15 +129,14 @@ impl String {
|
|||
// Convenience function not present in the original V8 API.
|
||||
pub fn to_rust_string_lossy(
|
||||
&self,
|
||||
isolate: &mut impl AsMut<Isolate>,
|
||||
scope: &mut impl InIsolate,
|
||||
) -> std::string::String {
|
||||
let isolate = isolate.as_mut();
|
||||
let capacity = self.utf8_length(isolate);
|
||||
let capacity = self.utf8_length(scope);
|
||||
let mut string = std::string::String::with_capacity(capacity);
|
||||
let data = string.as_mut_ptr();
|
||||
forget(string);
|
||||
let length = self.write_utf8(
|
||||
isolate,
|
||||
scope,
|
||||
unsafe { slice::from_raw_parts_mut(data, capacity) },
|
||||
None,
|
||||
WriteOptions::NO_NULL_TERMINATION | WriteOptions::REPLACE_INVALID_UTF8,
|
||||
|
|
|
@ -5,10 +5,11 @@ use std::mem::take;
|
|||
use std::mem::MaybeUninit;
|
||||
|
||||
use crate::Context;
|
||||
use crate::HandleScope;
|
||||
use crate::InIsolate;
|
||||
use crate::Isolate;
|
||||
use crate::Local;
|
||||
use crate::Message;
|
||||
use crate::ToLocal;
|
||||
use crate::Value;
|
||||
|
||||
extern "C" {
|
||||
|
@ -71,9 +72,9 @@ 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 AsMut<Isolate>) -> TryCatchScope<'tc> {
|
||||
pub fn new(scope: &mut impl InIsolate) -> TryCatchScope<'tc> {
|
||||
TryCatchScope(TryCatchState::New {
|
||||
isolate: scope.as_mut(),
|
||||
isolate: scope.isolate(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -111,17 +112,17 @@ impl<'tc> TryCatch<'tc> {
|
|||
///
|
||||
/// The returned handle is valid until this TryCatch block has been destroyed.
|
||||
pub fn exception(&self) -> Option<Local<'tc, Value>> {
|
||||
unsafe { Local::from_raw(v8__TryCatch__Exception(&self.0)) }
|
||||
unsafe { Local::from_raw_(v8__TryCatch__Exception(&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>(
|
||||
&self,
|
||||
_scope: &mut impl AsMut<HandleScope<'sc>>,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
context: Local<Context>,
|
||||
) -> Option<Local<'sc, Value>> {
|
||||
unsafe { Local::from_raw(v8__TryCatch__StackTrace(&self.0, context)) }
|
||||
unsafe { scope.to_local(v8__TryCatch__StackTrace(&self.0, context)) }
|
||||
}
|
||||
|
||||
/// Returns the message associated with this exception. If there is
|
||||
|
@ -130,7 +131,7 @@ impl<'tc> TryCatch<'tc> {
|
|||
/// The returned handle is valid until this TryCatch block has been
|
||||
/// destroyed.
|
||||
pub fn message(&self) -> Option<Local<'tc, Message>> {
|
||||
unsafe { Local::from_raw(v8__TryCatch__Message(&self.0)) }
|
||||
unsafe { Local::from_raw_(v8__TryCatch__Message(&self.0)) }
|
||||
}
|
||||
|
||||
/// Clears any exceptions that may have been caught by this try/catch block.
|
||||
|
@ -151,7 +152,7 @@ impl<'tc> TryCatch<'tc> {
|
|||
/// ReThrow; the caller must return immediately to where the exception
|
||||
/// is caught.
|
||||
pub fn rethrow<'a>(&'_ mut self) -> Option<Local<'a, Value>> {
|
||||
unsafe { Local::from_raw(v8__TryCatch__ReThrow(&mut self.0)) }
|
||||
unsafe { Local::from_raw_(v8__TryCatch__ReThrow(&mut self.0)) }
|
||||
}
|
||||
|
||||
/// Returns true if verbosity is enabled.
|
||||
|
|
41
tests/compile_fail/handle_scope_lifetimes.rs
Normal file
41
tests/compile_fail/handle_scope_lifetimes.rs
Normal file
|
@ -0,0 +1,41 @@
|
|||
extern crate rusty_v8 as v8;
|
||||
|
||||
pub fn main() {
|
||||
let mut isolate: v8::scope::Entered<'_, v8::HandleScope> = mock();
|
||||
|
||||
{
|
||||
let mut hs = v8::EscapableHandleScope::new(&mut isolate);
|
||||
let hs = hs.enter();
|
||||
let _fail = v8::EscapableHandleScope::new(&mut isolate);
|
||||
let _local = v8::Integer::new(hs, 123);
|
||||
}
|
||||
|
||||
{
|
||||
let mut hs1 = v8::EscapableHandleScope::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 _fail = v8::Integer::new(hs1, 123);
|
||||
let _local2 = v8::Integer::new(hs2, 123);
|
||||
let _local3 = v8::Integer::new(hs2, 123);
|
||||
}
|
||||
|
||||
let _leak1 = {
|
||||
let mut hs = v8::EscapableHandleScope::new(&mut isolate);
|
||||
let hs = hs.enter();
|
||||
v8::Integer::new(hs, 456)
|
||||
};
|
||||
|
||||
let _leak = {
|
||||
let mut hs = v8::EscapableHandleScope::new(&mut isolate);
|
||||
hs.enter()
|
||||
};
|
||||
}
|
||||
|
||||
fn mock<T>() -> T {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn access<T>(_value: T) {}
|
44
tests/compile_fail/handle_scope_lifetimes.stderr
Normal file
44
tests/compile_fail/handle_scope_lifetimes.stderr
Normal file
|
@ -0,0 +1,44 @@
|
|||
error[E0499]: cannot borrow `isolate` as mutable more than once at a time
|
||||
--> $DIR/handle_scope_lifetimes.rs:9:47
|
||||
|
|
||||
7 | let mut hs = v8::EscapableHandleScope::new(&mut isolate);
|
||||
| ------------ first mutable borrow occurs here
|
||||
8 | let hs = hs.enter();
|
||||
9 | let _fail = v8::EscapableHandleScope::new(&mut isolate);
|
||||
| ^^^^^^^^^^^^ second mutable borrow occurs here
|
||||
10 | let _local = v8::Integer::new(hs, 123);
|
||||
| -- first borrow later used here
|
||||
|
||||
error[E0499]: cannot borrow `*hs1` as mutable more than once at a time
|
||||
--> $DIR/handle_scope_lifetimes.rs:20:34
|
||||
|
|
||||
18 | let mut hs2 = v8::EscapableHandleScope::new(hs1);
|
||||
| --- first mutable borrow occurs here
|
||||
19 | let hs2 = hs2.enter();
|
||||
20 | let _fail = v8::Integer::new(hs1, 123);
|
||||
| ^^^ second mutable borrow occurs here
|
||||
21 | let _local2 = v8::Integer::new(hs2, 123);
|
||||
| --- first borrow later used here
|
||||
|
||||
error[E0597]: `hs` does not live long enough
|
||||
--> $DIR/handle_scope_lifetimes.rs:27:14
|
||||
|
|
||||
25 | let _leak1 = {
|
||||
| ------ borrow later stored here
|
||||
26 | let mut hs = v8::EscapableHandleScope::new(&mut isolate);
|
||||
27 | let hs = hs.enter();
|
||||
| ^^ borrowed value does not live long enough
|
||||
28 | v8::Integer::new(hs, 456)
|
||||
29 | };
|
||||
| - `hs` dropped here while still borrowed
|
||||
|
||||
error[E0597]: `hs` does not live long enough
|
||||
--> $DIR/handle_scope_lifetimes.rs:33:5
|
||||
|
|
||||
33 | hs.enter()
|
||||
| ^^--------
|
||||
| |
|
||||
| borrowed value does not live long enough
|
||||
| borrow later used here
|
||||
34 | };
|
||||
| - `hs` dropped here while still borrowed
|
|
@ -2,7 +2,7 @@ extern crate rusty_v8 as v8;
|
|||
|
||||
pub fn main() {
|
||||
let context: v8::Local<v8::Context> = mock();
|
||||
let scope: &mut v8::HandleScope<'_> = mock();
|
||||
let scope: &mut v8::scope::Entered<'_, v8::HandleScope> = mock();
|
||||
|
||||
let _leaked = {
|
||||
let mut try_catch = v8::TryCatch::new(scope);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
extern crate lazy_static;
|
||||
|
||||
use rusty_v8 as v8;
|
||||
use rusty_v8::{new_null, FunctionCallbackInfo, HandleScope, Local};
|
||||
use rusty_v8::{new_null, FunctionCallbackInfo, InIsolate, Local, ToLocal};
|
||||
use std::sync::Mutex;
|
||||
|
||||
lazy_static! {
|
||||
|
@ -45,9 +45,14 @@ fn handle_scope_nested() {
|
|||
params.set_array_buffer_allocator(v8::Allocator::new_default_allocator());
|
||||
let isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope1| {
|
||||
v8::HandleScope::enter(scope1, |_scope2| {});
|
||||
});
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope1 = hs.enter();
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(scope1);
|
||||
let _scope2 = hs.enter();
|
||||
}
|
||||
}
|
||||
drop(locker);
|
||||
drop(g);
|
||||
}
|
||||
|
@ -60,18 +65,22 @@ fn handle_scope_numbers() {
|
|||
params.set_array_buffer_allocator(v8::Allocator::new_default_allocator());
|
||||
let isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope1| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope1 = hs.enter();
|
||||
let l1 = v8::Integer::new(scope1, -123);
|
||||
let l2 = v8::Integer::new_from_unsigned(scope1, 456);
|
||||
v8::HandleScope::enter(scope1, |scope2| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(scope1);
|
||||
let scope2 = hs.enter();
|
||||
let l3 = v8::Number::new(scope2, 78.9);
|
||||
assert_eq!(l1.value(), -123);
|
||||
assert_eq!(l2.value(), 456);
|
||||
assert_eq!(l3.value(), 78.9);
|
||||
assert_eq!(v8::Number::value(&l1), -123f64);
|
||||
assert_eq!(v8::Number::value(&l2), 456f64);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
drop(locker);
|
||||
drop(g);
|
||||
}
|
||||
|
@ -86,35 +95,39 @@ fn global_handles() {
|
|||
let mut g1 = v8::Global::<v8::String>::new();
|
||||
let mut g2 = v8::Global::<v8::Integer>::new();
|
||||
let mut g3 = v8::Global::<v8::Integer>::new();
|
||||
let mut g4 = v8::Global::<v8::Integer>::new();
|
||||
let mut _g4 = v8::Global::<v8::Integer>::new();
|
||||
let g5 = v8::Global::<v8::Script>::new();
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let l1 = v8::String::new(scope, "bla").unwrap();
|
||||
let l2 = v8::Integer::new(scope, 123);
|
||||
g1.set(scope, l1);
|
||||
g2.set(scope, l2);
|
||||
g3.set(scope, &g2);
|
||||
g4 = v8::Global::new_from(scope, l2);
|
||||
});
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
_g4 = v8::Global::new_from(scope, l2);
|
||||
}
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
assert!(!g1.is_empty());
|
||||
assert_eq!(g1.get(scope).unwrap().to_rust_string_lossy(scope), "bla");
|
||||
assert!(!g2.is_empty());
|
||||
assert_eq!(g2.get(scope).unwrap().value(), 123);
|
||||
assert!(!g3.is_empty());
|
||||
assert_eq!(g3.get(scope).unwrap().value(), 123);
|
||||
assert!(!g4.is_empty());
|
||||
assert_eq!(g4.get(scope).unwrap().value(), 123);
|
||||
assert!(!_g4.is_empty());
|
||||
assert_eq!(_g4.get(scope).unwrap().value(), 123);
|
||||
assert!(g5.is_empty());
|
||||
});
|
||||
}
|
||||
g1.reset(&mut locker);
|
||||
assert!(g1.is_empty());
|
||||
g2.reset(&mut locker);
|
||||
assert!(g2.is_empty());
|
||||
g3.reset(&mut locker);
|
||||
assert!(g3.is_empty());
|
||||
g4.reset(&mut locker);
|
||||
assert!(g4.is_empty());
|
||||
_g4.reset(&mut locker);
|
||||
assert!(_g4.is_empty());
|
||||
assert!(g5.is_empty());
|
||||
}
|
||||
|
||||
|
@ -125,13 +138,15 @@ fn test_string() {
|
|||
params.set_array_buffer_allocator(v8::Allocator::new_default_allocator());
|
||||
let isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let reference = "Hello 🦕 world!";
|
||||
let local = v8::String::new(scope, reference).unwrap();
|
||||
assert_eq!(15, local.length());
|
||||
assert_eq!(17, local.utf8_length(scope));
|
||||
assert_eq!(reference, local.to_rust_string_lossy(scope));
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
}
|
||||
|
||||
|
@ -144,42 +159,43 @@ fn escapable_handle_scope() {
|
|||
let mut isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
isolate.enter();
|
||||
v8::HandleScope::enter(&mut locker, |scope1| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope1 = hs.enter();
|
||||
// After dropping EscapableHandleScope, we should be able to
|
||||
// read escaped values.
|
||||
let number_val = {
|
||||
let mut escapable_scope = v8::EscapableHandleScope::new(scope1);
|
||||
let mut hs = v8::EscapableHandleScope::new(scope1);
|
||||
let escapable_scope = hs.enter();
|
||||
let number: Local<v8::Value> =
|
||||
cast(v8::Number::new(&mut escapable_scope, 78.9));
|
||||
cast(v8::Number::new(escapable_scope, 78.9));
|
||||
escapable_scope.escape(number)
|
||||
};
|
||||
let number: Local<v8::Number> = cast(number_val);
|
||||
assert_eq!(number.value(), 78.9);
|
||||
|
||||
let str_val = {
|
||||
let mut escapable_scope = v8::EscapableHandleScope::new(scope1);
|
||||
let string =
|
||||
v8::String::new(&mut escapable_scope, "Hello 🦕 world!").unwrap();
|
||||
escapable_scope.escape(cast(string))
|
||||
let string = {
|
||||
let mut hs = v8::EscapableHandleScope::new(scope1);
|
||||
let escapable_scope = hs.enter();
|
||||
let string = v8::String::new(escapable_scope, "Hello 🦕 world!").unwrap();
|
||||
escapable_scope.escape(string)
|
||||
};
|
||||
let string: Local<v8::String> = cast(str_val);
|
||||
assert_eq!("Hello 🦕 world!", string.to_rust_string_lossy(scope1));
|
||||
|
||||
let str_val = {
|
||||
let mut escapable_scope = v8::EscapableHandleScope::new(scope1);
|
||||
let string = {
|
||||
let mut hs = v8::EscapableHandleScope::new(scope1);
|
||||
let escapable_scope = hs.enter();
|
||||
let nested_str_val = {
|
||||
let mut nested_escapable_scope =
|
||||
v8::EscapableHandleScope::new(&mut escapable_scope);
|
||||
let mut hs = v8::EscapableHandleScope::new(escapable_scope);
|
||||
let nested_escapable_scope = hs.enter();
|
||||
let string =
|
||||
v8::String::new(&mut nested_escapable_scope, "Hello 🦕 world!")
|
||||
.unwrap();
|
||||
nested_escapable_scope.escape(cast(string))
|
||||
v8::String::new(nested_escapable_scope, "Hello 🦕 world!").unwrap();
|
||||
nested_escapable_scope.escape(string)
|
||||
};
|
||||
escapable_scope.escape(nested_str_val)
|
||||
};
|
||||
let string: Local<v8::String> = cast(str_val);
|
||||
assert_eq!("Hello 🦕 world!", string.to_rust_string_lossy(scope1));
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
isolate.exit();
|
||||
drop(g);
|
||||
|
@ -192,7 +208,9 @@ fn array_buffer() {
|
|||
params.set_array_buffer_allocator(v8::Allocator::new_default_allocator());
|
||||
let isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let mut context = v8::Context::new(scope);
|
||||
context.enter();
|
||||
|
||||
|
@ -204,26 +222,29 @@ fn array_buffer() {
|
|||
assert_eq!(false, bs.is_shared());
|
||||
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
}
|
||||
|
||||
fn v8_str<'sc>(
|
||||
isolate: &mut impl AsMut<v8::Isolate>,
|
||||
scope: &mut impl v8::ToLocal<'sc>,
|
||||
s: &str,
|
||||
) -> v8::Local<'sc, v8::String> {
|
||||
v8::String::new(isolate, s).unwrap()
|
||||
v8::String::new(scope, s).unwrap()
|
||||
}
|
||||
|
||||
fn eval<'sc>(
|
||||
scope: &mut HandleScope<'sc>,
|
||||
scope: &mut impl v8::InIsolate,
|
||||
context: Local<v8::Context>,
|
||||
code: &'static str,
|
||||
) -> Option<Local<'sc, v8::Value>> {
|
||||
let mut hs = v8::EscapableHandleScope::new(scope);
|
||||
let scope = hs.enter();
|
||||
let source = v8_str(scope, code);
|
||||
let mut script =
|
||||
v8::Script::compile(&mut *scope, context, source, None).unwrap();
|
||||
script.run(scope, context)
|
||||
let r = script.run(scope, context);
|
||||
r.map(|v| scope.escape(v))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -233,7 +254,9 @@ fn try_catch() {
|
|||
params.set_array_buffer_allocator(v8::Allocator::new_default_allocator());
|
||||
let isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let mut context = v8::Context::new(scope);
|
||||
context.enter();
|
||||
{
|
||||
|
@ -279,7 +302,7 @@ fn try_catch() {
|
|||
assert!(tc1.has_caught());
|
||||
};
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -289,7 +312,9 @@ fn throw_exception() {
|
|||
params.set_array_buffer_allocator(v8::Allocator::new_default_allocator());
|
||||
let isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let mut context = v8::Context::new(scope);
|
||||
context.enter();
|
||||
{
|
||||
|
@ -303,7 +328,7 @@ fn throw_exception() {
|
|||
.strict_equals(v8_str(scope, "boom").into()));
|
||||
};
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -322,16 +347,21 @@ fn add_message_listener() {
|
|||
_exception: Local<v8::Value>,
|
||||
) {
|
||||
CALL_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||
let isolate = unsafe { message.get_isolate() };
|
||||
v8::HandleScope::enter(isolate, |scope| {
|
||||
let mut cbs = v8::CallbackScope::new(message);
|
||||
let scope = cbs.enter();
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(scope);
|
||||
let scope = hs.enter();
|
||||
let message_str = message.get(scope);
|
||||
assert_eq!(message_str.to_rust_string_lossy(scope), "Uncaught foo");
|
||||
});
|
||||
}
|
||||
}
|
||||
isolate.add_message_listener(check_message_0);
|
||||
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |s| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let s = hs.enter();
|
||||
let mut context = v8::Context::new(s);
|
||||
context.enter();
|
||||
let source = v8::String::new(s, "throw 'foo'").unwrap();
|
||||
|
@ -339,7 +369,7 @@ fn add_message_listener() {
|
|||
assert!(script.run(s, context).is_none());
|
||||
assert_eq!(CALL_COUNT.load(Ordering::SeqCst), 1);
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
drop(g);
|
||||
}
|
||||
|
@ -363,39 +393,43 @@ fn set_host_initialize_import_meta_object_callback() {
|
|||
static CALL_COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
extern "C" fn callback(
|
||||
mut context: Local<v8::Context>,
|
||||
context: Local<v8::Context>,
|
||||
_module: Local<v8::Module>,
|
||||
meta: Local<v8::Object>,
|
||||
) {
|
||||
CALL_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||
let key = v8::String::new(&mut *context, "foo").unwrap();
|
||||
let value = v8::String::new(&mut *context, "bar").unwrap();
|
||||
let mut cbs = v8::CallbackScope::new(context);
|
||||
let mut hs = v8::HandleScope::new(cbs.enter());
|
||||
let scope = hs.enter();
|
||||
let key = v8::String::new(scope, "foo").unwrap();
|
||||
let value = v8::String::new(scope, "bar").unwrap();
|
||||
meta.create_data_property(context, cast(key), value.into());
|
||||
}
|
||||
isolate.set_host_initialize_import_meta_object_callback(callback);
|
||||
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |s| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let s = hs.enter();
|
||||
let mut context = v8::Context::new(s);
|
||||
context.enter();
|
||||
|
||||
let source = mock_source(s, "google.com", "import.meta;");
|
||||
let mut module =
|
||||
v8::script_compiler::compile_module(&isolate, source).unwrap();
|
||||
let result =
|
||||
module.instantiate_module(context, unexpected_module_resolve_callback);
|
||||
assert!(result.is_some());
|
||||
let meta = module.evaluate(context).unwrap();
|
||||
let meta = module.evaluate(s, context).unwrap();
|
||||
assert!(meta.is_object());
|
||||
let meta: Local<v8::Object> = cast(meta);
|
||||
let key = v8::String::new(&mut *context, "foo").unwrap();
|
||||
let expected = v8::String::new(&mut *context, "bar").unwrap();
|
||||
let actual = meta.get(context, key.into()).unwrap();
|
||||
let key = v8::String::new(s, "foo").unwrap();
|
||||
let expected = v8::String::new(s, "bar").unwrap();
|
||||
let actual = meta.get(s, context, key.into()).unwrap();
|
||||
assert!(expected.strict_equals(actual));
|
||||
assert_eq!(CALL_COUNT.load(Ordering::SeqCst), 1);
|
||||
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
drop(g);
|
||||
}
|
||||
|
@ -407,8 +441,9 @@ fn script_compile_and_run() {
|
|||
params.set_array_buffer_allocator(v8::Allocator::new_default_allocator());
|
||||
let isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
|
||||
v8::HandleScope::enter(&mut locker, |s| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let s = hs.enter();
|
||||
let mut context = v8::Context::new(s);
|
||||
context.enter();
|
||||
let source = v8::String::new(s, "'Hello ' + 13 + 'th planet'").unwrap();
|
||||
|
@ -420,7 +455,7 @@ fn script_compile_and_run() {
|
|||
unsafe { std::mem::transmute_copy(&result) };
|
||||
assert_eq!(result.to_rust_string_lossy(s), "Hello 13th planet");
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
}
|
||||
|
||||
|
@ -432,7 +467,9 @@ fn script_origin() {
|
|||
let isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
|
||||
v8::HandleScope::enter(&mut locker, |s| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let s = hs.enter();
|
||||
let mut context = v8::Context::new(s);
|
||||
context.enter();
|
||||
|
||||
|
@ -464,7 +501,7 @@ fn script_origin() {
|
|||
source.to_rust_string_lossy(s);
|
||||
let _result = script.run(s, context).unwrap();
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
}
|
||||
|
||||
|
@ -521,7 +558,9 @@ fn test_primitives() {
|
|||
params.set_array_buffer_allocator(v8::Allocator::new_default_allocator());
|
||||
let isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let null = v8::new_null(scope);
|
||||
assert!(!null.is_undefined());
|
||||
assert!(null.is_null());
|
||||
|
@ -541,7 +580,7 @@ fn test_primitives() {
|
|||
assert!(!false_.is_undefined());
|
||||
assert!(!false_.is_null());
|
||||
assert!(!false_.is_null_or_undefined());
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
}
|
||||
|
||||
|
@ -553,7 +592,9 @@ fn exception() {
|
|||
let mut isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
isolate.enter();
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let mut context = v8::Context::new(scope);
|
||||
context.enter();
|
||||
let reference = "This is a test error";
|
||||
|
@ -572,7 +613,7 @@ fn exception() {
|
|||
);
|
||||
assert!(v8::get_stack_trace(scope, exception).is_none());
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
isolate.exit();
|
||||
}
|
||||
|
@ -584,7 +625,9 @@ fn json() {
|
|||
params.set_array_buffer_allocator(v8::Allocator::new_default_allocator());
|
||||
let isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |s| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let s = hs.enter();
|
||||
let mut context = v8::Context::new(s);
|
||||
context.enter();
|
||||
let json_string = v8_str(s, "{\"a\": 1, \"b\": 2}");
|
||||
|
@ -597,7 +640,7 @@ fn json() {
|
|||
let rust_str = stringified.to_rust_string_lossy(s);
|
||||
assert_eq!("{\"a\":1,\"b\":2}".to_string(), rust_str);
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
}
|
||||
|
||||
|
@ -614,7 +657,9 @@ fn object() {
|
|||
params.set_array_buffer_allocator(v8::Allocator::new_default_allocator());
|
||||
let isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let mut context = v8::Context::new(scope);
|
||||
context.enter();
|
||||
let null: v8::Local<v8::Value> = new_null(scope).into();
|
||||
|
@ -629,7 +674,7 @@ fn object() {
|
|||
let object = v8::Object::new(scope, null, names, values, 2);
|
||||
assert!(!object.is_null_or_undefined());
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
}
|
||||
|
||||
|
@ -640,15 +685,18 @@ fn create_data_property() {
|
|||
params.set_array_buffer_allocator(v8::Allocator::new_default_allocator());
|
||||
let isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let mut context = v8::Context::new(scope);
|
||||
context.enter();
|
||||
|
||||
eval(scope, context, "var a = {};");
|
||||
|
||||
let key = v8_str(scope, "a");
|
||||
let obj = context
|
||||
.global()
|
||||
.get(context, v8_str(scope, "a").into())
|
||||
.global(scope)
|
||||
.get(scope, context, key.into())
|
||||
.unwrap();
|
||||
assert!(obj.is_object());
|
||||
let obj: Local<v8::Object> = cast(obj);
|
||||
|
@ -658,11 +706,11 @@ fn create_data_property() {
|
|||
obj.create_data_property(context, cast(key), cast(value)),
|
||||
v8::MaybeBool::JustTrue
|
||||
);
|
||||
let actual = obj.get(context, cast(key)).unwrap();
|
||||
let actual = obj.get(scope, context, cast(key)).unwrap();
|
||||
assert!(value.strict_equals(actual));
|
||||
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
}
|
||||
|
||||
|
@ -673,7 +721,9 @@ fn promise_resolved() {
|
|||
params.set_array_buffer_allocator(v8::Allocator::new_default_allocator());
|
||||
let isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let mut context = v8::Context::new(scope);
|
||||
context.enter();
|
||||
let maybe_resolver = v8::PromiseResolver::new(scope, context);
|
||||
|
@ -698,7 +748,7 @@ fn promise_resolved() {
|
|||
let result_str: v8::Local<v8::String> = cast(result);
|
||||
assert_eq!(result_str.to_rust_string_lossy(scope), "test".to_string());
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
}
|
||||
|
||||
|
@ -709,7 +759,9 @@ fn promise_rejected() {
|
|||
params.set_array_buffer_allocator(v8::Allocator::new_default_allocator());
|
||||
let isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let mut context = v8::Context::new(scope);
|
||||
context.enter();
|
||||
let maybe_resolver = v8::PromiseResolver::new(scope, context);
|
||||
|
@ -735,21 +787,27 @@ fn promise_rejected() {
|
|||
let result_str: v8::Local<v8::String> = cast(result);
|
||||
assert_eq!(result_str.to_rust_string_lossy(scope), "test".to_string());
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
}
|
||||
|
||||
extern "C" fn fn_callback(info: &FunctionCallbackInfo) {
|
||||
assert_eq!(info.length(), 0);
|
||||
let isolate = unsafe { info.get_isolate() };
|
||||
v8::HandleScope::enter(isolate, |scope| {
|
||||
let s = v8::String::new(scope, "Hello callback!").unwrap();
|
||||
let value: Local<v8::Value> = s.into();
|
||||
{
|
||||
let rv = &mut info.get_return_value();
|
||||
let rv_value = rv.get(scope);
|
||||
assert!(rv_value.is_undefined());
|
||||
rv.set(value);
|
||||
});
|
||||
#[allow(mutable_transmutes)]
|
||||
#[allow(clippy::transmute_ptr_to_ptr)]
|
||||
let info: &mut FunctionCallbackInfo = unsafe { std::mem::transmute(info) };
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(info);
|
||||
let scope = hs.enter();
|
||||
let s = v8::String::new(scope, "Hello callback!").unwrap();
|
||||
let value: Local<v8::Value> = s.into();
|
||||
let rv_value = rv.get(scope);
|
||||
assert!(rv_value.is_undefined());
|
||||
rv.set(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -759,10 +817,12 @@ fn function() {
|
|||
params.set_array_buffer_allocator(v8::Allocator::new_default_allocator());
|
||||
let isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let mut context = v8::Context::new(scope);
|
||||
context.enter();
|
||||
let global = context.global();
|
||||
let global = context.global(scope);
|
||||
let recv: Local<v8::Value> = global.into();
|
||||
// create function using template
|
||||
let mut fn_template = v8::FunctionTemplate::new(scope, fn_callback);
|
||||
|
@ -781,7 +841,7 @@ fn function() {
|
|||
let rust_str = value_str.to_rust_string_lossy(scope);
|
||||
assert_eq!(rust_str, "Hello callback!".to_string());
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
}
|
||||
|
||||
|
@ -790,15 +850,17 @@ extern "C" fn promise_reject_callback(msg: v8::PromiseRejectMessage) {
|
|||
assert_eq!(event, v8::PromiseRejectEvent::PromiseRejectWithNoHandler);
|
||||
let mut promise = msg.get_promise();
|
||||
assert_eq!(promise.state(), v8::PromiseState::Rejected);
|
||||
let promise_obj: v8::Local<v8::Object> = cast(promise);
|
||||
let mut promise_obj: v8::Local<v8::Object> = cast(promise);
|
||||
let isolate = promise_obj.get_isolate();
|
||||
let value = msg.get_value();
|
||||
let mut locker = v8::Locker::new(isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let value_str: v8::Local<v8::String> = cast(value);
|
||||
let rust_str = value_str.to_rust_string_lossy(scope);
|
||||
assert_eq!(rust_str, "promise rejected".to_string());
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
}
|
||||
|
||||
|
@ -811,7 +873,9 @@ fn set_promise_reject_callback() {
|
|||
isolate.set_promise_reject_callback(promise_reject_callback);
|
||||
isolate.enter();
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let mut context = v8::Context::new(scope);
|
||||
context.enter();
|
||||
let mut resolver = v8::PromiseResolver::new(scope, context).unwrap();
|
||||
|
@ -819,24 +883,24 @@ fn set_promise_reject_callback() {
|
|||
let value: Local<v8::Value> = cast(str_);
|
||||
resolver.reject(context, value);
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
isolate.exit();
|
||||
}
|
||||
|
||||
fn mock_script_origin<'sc>(
|
||||
isolate: &mut impl AsMut<v8::Isolate>,
|
||||
scope: &mut impl v8::ToLocal<'sc>,
|
||||
resource_name_: &str,
|
||||
) -> v8::ScriptOrigin<'sc> {
|
||||
let resource_name = v8_str(isolate, resource_name_);
|
||||
let resource_line_offset = v8::Integer::new(isolate, 0);
|
||||
let resource_column_offset = v8::Integer::new(isolate, 0);
|
||||
let resource_is_shared_cross_origin = v8::new_true(isolate);
|
||||
let script_id = v8::Integer::new(isolate, 123);
|
||||
let source_map_url = v8_str(isolate, "source_map_url");
|
||||
let resource_is_opaque = v8::new_true(isolate);
|
||||
let is_wasm = v8::new_false(isolate);
|
||||
let is_module = v8::new_true(isolate);
|
||||
let resource_name = v8_str(scope, resource_name_);
|
||||
let resource_line_offset = v8::Integer::new(scope, 0);
|
||||
let resource_column_offset = v8::Integer::new(scope, 0);
|
||||
let resource_is_shared_cross_origin = v8::new_true(scope);
|
||||
let script_id = v8::Integer::new(scope, 123);
|
||||
let source_map_url = v8_str(scope, "source_map_url");
|
||||
let resource_is_opaque = v8::new_true(scope);
|
||||
let is_wasm = v8::new_false(scope);
|
||||
let is_module = v8::new_true(scope);
|
||||
v8::ScriptOrigin::new(
|
||||
resource_name.into(),
|
||||
resource_line_offset,
|
||||
|
@ -850,13 +914,14 @@ fn mock_script_origin<'sc>(
|
|||
)
|
||||
}
|
||||
|
||||
fn mock_source(
|
||||
isolate: &mut impl AsMut<v8::Isolate>,
|
||||
fn mock_source<'sc>(
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
resource_name: &str,
|
||||
source: &str,
|
||||
) -> v8::script_compiler::Source {
|
||||
let script_origin = mock_script_origin(isolate, resource_name);
|
||||
v8::script_compiler::Source::new(v8_str(isolate, source), &script_origin)
|
||||
let source_str = v8_str(scope, source);
|
||||
let script_origin = mock_script_origin(scope, resource_name);
|
||||
v8::script_compiler::Source::new(source_str, &script_origin)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -868,7 +933,9 @@ fn script_compiler_source() {
|
|||
isolate.set_promise_reject_callback(promise_reject_callback);
|
||||
isolate.enter();
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let mut context = v8::Context::new(scope);
|
||||
context.enter();
|
||||
|
||||
|
@ -881,7 +948,7 @@ fn script_compiler_source() {
|
|||
assert!(result.is_some());
|
||||
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
isolate.exit();
|
||||
drop(g);
|
||||
|
@ -895,7 +962,9 @@ fn module_instantiation_failures1() {
|
|||
let mut isolate = v8::Isolate::new(params);
|
||||
isolate.enter();
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let mut context = v8::Context::new(scope);
|
||||
context.enter();
|
||||
|
||||
|
@ -933,13 +1002,15 @@ fn module_instantiation_failures1() {
|
|||
let mut try_catch = v8::TryCatch::new(scope);
|
||||
let tc = try_catch.enter();
|
||||
fn resolve_callback(
|
||||
mut context: v8::Local<v8::Context>,
|
||||
context: v8::Local<v8::Context>,
|
||||
_specifier: v8::Local<v8::String>,
|
||||
_referrer: v8::Local<v8::Module>,
|
||||
) -> *mut v8::Module {
|
||||
let isolate: &mut v8::Isolate = context.as_mut();
|
||||
let e = v8_str(isolate, "boom");
|
||||
isolate.throw_exception(e.into());
|
||||
let mut cbs = v8::CallbackScope::new(context);
|
||||
let mut hs = v8::HandleScope::new(cbs.enter());
|
||||
let scope = hs.enter();
|
||||
let e = v8_str(scope, "boom");
|
||||
scope.isolate().throw_exception(e.into());
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
let result = module.instantiate_module(context, resolve_callback);
|
||||
|
@ -953,22 +1024,25 @@ fn module_instantiation_failures1() {
|
|||
}
|
||||
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
isolate.exit();
|
||||
drop(g);
|
||||
}
|
||||
|
||||
fn compile_specifier_as_module_resolve_callback(
|
||||
mut context: v8::Local<v8::Context>,
|
||||
context: v8::Local<v8::Context>,
|
||||
specifier: v8::Local<v8::String>,
|
||||
_referrer: v8::Local<v8::Module>,
|
||||
) -> *mut v8::Module {
|
||||
let isolate: &mut v8::Isolate = context.as_mut();
|
||||
let origin = mock_script_origin(isolate, "module.js");
|
||||
let mut cbs = v8::CallbackScope::new(context);
|
||||
let mut hs = v8::EscapableHandleScope::new(cbs.enter());
|
||||
let scope = hs.enter();
|
||||
let origin = mock_script_origin(scope, "module.js");
|
||||
let source = v8::script_compiler::Source::new(specifier, &origin);
|
||||
let module = v8::script_compiler::compile_module(isolate, source).unwrap();
|
||||
&mut *cast(module)
|
||||
let module =
|
||||
v8::script_compiler::compile_module(scope.isolate(), source).unwrap();
|
||||
&mut *cast(scope.escape(module))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -979,7 +1053,9 @@ fn module_evaluation() {
|
|||
let mut isolate = v8::Isolate::new(params);
|
||||
isolate.enter();
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let mut context = v8::Context::new(scope);
|
||||
context.enter();
|
||||
|
||||
|
@ -1002,7 +1078,7 @@ fn module_evaluation() {
|
|||
assert!(result.unwrap());
|
||||
assert_eq!(v8::ModuleStatus::Instantiated, module.get_status());
|
||||
|
||||
let result = module.evaluate(context);
|
||||
let result = module.evaluate(scope, context);
|
||||
assert!(result.is_some());
|
||||
assert_eq!(v8::ModuleStatus::Evaluated, module.get_status());
|
||||
|
||||
|
@ -1012,7 +1088,7 @@ fn module_evaluation() {
|
|||
assert!(result.strict_equals(expected.into()));
|
||||
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
isolate.exit();
|
||||
drop(g);
|
||||
|
@ -1026,7 +1102,9 @@ fn primitive_array() {
|
|||
let mut isolate = v8::Isolate::new(params);
|
||||
isolate.enter();
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let mut context = v8::Context::new(scope);
|
||||
context.enter();
|
||||
|
||||
|
@ -1051,7 +1129,7 @@ fn primitive_array() {
|
|||
assert!(array.get(scope, 2).is_number());
|
||||
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
isolate.exit();
|
||||
drop(g);
|
||||
|
@ -1075,7 +1153,9 @@ fn equality() {
|
|||
let mut isolate = v8::Isolate::new(params);
|
||||
isolate.enter();
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let mut context = v8::Context::new(scope);
|
||||
context.enter();
|
||||
|
||||
|
@ -1086,7 +1166,7 @@ fn equality() {
|
|||
assert!(!v8_str(scope, "a").same_value(v8_str(scope, "b").into()));
|
||||
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
isolate.exit();
|
||||
drop(g);
|
||||
|
@ -1100,7 +1180,9 @@ fn array_buffer_view() {
|
|||
let mut isolate = v8::Isolate::new(params);
|
||||
isolate.enter();
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |s| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let s = hs.enter();
|
||||
let mut context = v8::Context::new(s);
|
||||
context.enter();
|
||||
let source = v8::String::new(s, "new Uint8Array([23,23,23,23])").unwrap();
|
||||
|
@ -1121,7 +1203,7 @@ fn array_buffer_view() {
|
|||
let ab = maybe_ab.unwrap();
|
||||
assert_eq!(ab.byte_length(), 4);
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
drop(locker);
|
||||
isolate.exit();
|
||||
drop(g);
|
||||
|
@ -1136,7 +1218,9 @@ fn snapshot_creator() {
|
|||
let mut snapshot_creator = v8::SnapshotCreator::default();
|
||||
let isolate = snapshot_creator.get_isolate();
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let mut context = v8::Context::new(scope);
|
||||
context.enter();
|
||||
|
||||
|
@ -1148,7 +1232,7 @@ fn snapshot_creator() {
|
|||
snapshot_creator.set_default_context(context);
|
||||
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
|
||||
snapshot_creator.create_blob(v8::FunctionCodeHandling::Clear)
|
||||
};
|
||||
|
@ -1161,7 +1245,9 @@ fn snapshot_creator() {
|
|||
params.set_snapshot_blob(&mut startup_data);
|
||||
let isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let mut context = v8::Context::new(scope);
|
||||
context.enter();
|
||||
let source = v8::String::new(scope, "a === 3").unwrap();
|
||||
|
@ -1171,7 +1257,7 @@ fn snapshot_creator() {
|
|||
let true_val: Local<v8::Value> = cast(v8::new_true(scope));
|
||||
assert!(result.same_value(true_val));
|
||||
context.exit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(ry) startup_data is getting leaked and is not cleaned up properly!
|
||||
|
|
Loading…
Reference in a new issue