diff --git a/src/context.rs b/src/context.rs index 6ded92a7..4e8c10a4 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,6 +1,7 @@ // 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; @@ -18,9 +19,9 @@ extern "C" { pub struct Context(Opaque); impl Context { - pub fn new(isolate: &Isolate) -> Local { + pub fn new<'sc>(scope: &mut HandleScope<'sc>) -> Local<'sc, Context> { // TODO: optional arguments; - unsafe { Local::from_raw(v8__Context__New(isolate)).unwrap() } + unsafe { Local::from_raw(v8__Context__New(scope.as_mut())).unwrap() } } /// Returns the global proxy object. @@ -33,7 +34,7 @@ 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(&mut self) -> Local { + pub fn global<'sc>(&mut self) -> Local<'sc, Object> { unsafe { Local::from_raw(v8__Context__Global(&mut *self)).unwrap() } } diff --git a/src/exception.rs b/src/exception.rs index c57783f7..7a2ab83d 100644 --- a/src/exception.rs +++ b/src/exception.rs @@ -3,6 +3,7 @@ use crate::isolate::Isolate; use crate::support::int; use crate::support::Opaque; +use crate::HandleScope; use crate::Local; use crate::String; use crate::Value; @@ -45,11 +46,12 @@ impl StackTrace { pub struct Message(Opaque); impl Message { - pub fn get(&self) -> Local { + pub fn get<'sc>(&self, _scope: &mut HandleScope<'sc>) -> Local<'sc, String> { unsafe { Local::from_raw(v8__Message__Get(self)) }.unwrap() } - pub fn get_isolate(&self) -> &Isolate { + #[allow(clippy::mut_from_ref)] + pub fn get_isolate(&self) -> &mut Isolate { unsafe { v8__Message__GetIsolate(self) } } } @@ -57,41 +59,60 @@ impl Message { /// 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( - isolate: &Isolate, - mut exception: Local, -) -> Local { +pub fn create_message<'sc>( + scope: &mut HandleScope<'sc>, + mut exception: Local<'sc, Value>, +) -> Local<'sc, Message> { unsafe { - Local::from_raw(v8__Exception__CreateMessage(isolate, &mut *exception)) + Local::from_raw(v8__Exception__CreateMessage( + scope.as_mut(), + &mut *exception, + )) } .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( +pub fn get_stack_trace<'sc>( + _scope: &mut HandleScope<'sc>, mut exception: Local, -) -> Option> { +) -> Option> { unsafe { Local::from_raw(v8__Exception__GetStackTrace(&mut *exception)) } } -pub fn range_error(mut message: Local) -> Local { +pub fn range_error<'sc>( + _scope: &mut HandleScope<'sc>, + mut message: Local, +) -> Local<'sc, Value> { unsafe { Local::from_raw(v8__Exception__RangeError(&mut *message)) }.unwrap() } -pub fn reference_error(mut message: Local) -> Local { +pub fn reference_error<'sc>( + _scope: &mut HandleScope<'sc>, + mut message: Local, +) -> Local<'sc, Value> { unsafe { Local::from_raw(v8__Exception__ReferenceError(&mut *message)) } .unwrap() } -pub fn syntax_error(mut message: Local) -> Local { +pub fn syntax_error<'sc>( + _scope: &mut HandleScope<'sc>, + mut message: Local, +) -> Local<'sc, Value> { unsafe { Local::from_raw(v8__Exception__SyntaxError(&mut *message)) }.unwrap() } -pub fn type_error(mut message: Local) -> Local { +pub fn type_error<'sc>( + _scope: &mut HandleScope<'sc>, + mut message: Local, +) -> Local<'sc, Value> { unsafe { Local::from_raw(v8__Exception__TypeError(&mut *message)) }.unwrap() } -pub fn error(mut message: Local) -> Local { +pub fn error<'sc>( + _scope: &mut HandleScope<'sc>, + mut message: Local, +) -> Local<'sc, Value> { unsafe { Local::from_raw(v8__Exception__Error(&mut *message)) }.unwrap() } diff --git a/src/function.rs b/src/function.rs index a7624afa..70727482 100644 --- a/src/function.rs +++ b/src/function.rs @@ -1,5 +1,6 @@ use crate::support::{int, Opaque}; use crate::Context; +use crate::HandleScope; use crate::Isolate; use crate::Local; use crate::Value; @@ -63,7 +64,10 @@ impl ReturnValue { /// 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(&mut self) -> Local { + pub fn get<'sc>( + &mut self, + _scope: &mut HandleScope<'sc>, + ) -> Local<'sc, Value> { unsafe { Local::from_raw(v8__ReturnValue__Get(&mut *self)).unwrap() } } } @@ -122,20 +126,22 @@ pub struct FunctionTemplate(Opaque); impl FunctionTemplate { /// Creates a function template. - pub fn new( - isolate: &Isolate, + pub fn new<'sc>( + scope: &mut HandleScope<'sc>, callback: extern "C" fn(&FunctionCallbackInfo), - ) -> Local { + ) -> Local<'sc, FunctionTemplate> { unsafe { - Local::from_raw(v8__FunctionTemplate__New(isolate, callback)).unwrap() + Local::from_raw(v8__FunctionTemplate__New(scope.as_mut(), callback)) + .unwrap() } } /// Returns the unique function instance in the current execution context. - pub fn get_function( + pub fn get_function<'sc>( &mut self, + _scope: &mut HandleScope<'sc>, mut context: Local, - ) -> Option> { + ) -> Option> { unsafe { Local::from_raw(v8__FunctionTemplate__GetFunction( &mut *self, @@ -153,20 +159,22 @@ impl Function { // TODO: add remaining arguments from C++ /// Create a function in the current execution context /// for a given FunctionCallback. - pub fn new( + pub fn new<'sc>( + _scope: &mut HandleScope<'sc>, mut context: Local, callback: extern "C" fn(&FunctionCallbackInfo), - ) -> Option> { + ) -> Option> { unsafe { Local::from_raw(v8__Function__New(&mut *context, callback)) } } - pub fn call( + pub fn call<'sc>( &mut self, + _scope: &mut HandleScope<'sc>, mut context: Local, mut recv: Local, arc: i32, argv: Vec>, - ) -> Option> { + ) -> Option> { let mut argv_: Vec<*mut Value> = vec![]; for mut arg in argv { argv_.push(&mut *arg); diff --git a/src/handle_scope.rs b/src/handle_scope.rs index e57dc9c9..ed707960 100644 --- a/src/handle_scope.rs +++ b/src/handle_scope.rs @@ -1,3 +1,4 @@ +use std::marker::PhantomData; use std::mem::MaybeUninit; use crate::isolate::Isolate; @@ -8,22 +9,36 @@ extern "C" { isolate: &Isolate, ); fn v8__HandleScope__DESTRUCT(this: &mut HandleScope); - fn v8__HandleScope__GetIsolate(this: &HandleScope) -> &mut Isolate; + fn v8__HandleScope__GetIsolate<'sc>( + this: &'sc HandleScope, + ) -> &'sc mut Isolate; } #[repr(C)] -pub struct HandleScope([usize; 3]); +pub struct HandleScope<'sc>([usize; 3], PhantomData<&'sc mut ()>); -impl HandleScope { - pub fn enter(isolate: &Isolate, mut f: impl FnMut(&mut HandleScope) -> ()) { +impl<'sc> HandleScope<'sc> { + pub fn enter( + isolate: &Isolate, + mut f: impl FnMut(&mut HandleScope<'_>) -> (), + ) { let mut scope: MaybeUninit = MaybeUninit::uninit(); unsafe { v8__HandleScope__CONSTRUCT(&mut scope, isolate) }; let scope = unsafe { &mut *(scope.as_mut_ptr()) }; f(scope); + unsafe { v8__HandleScope__DESTRUCT(scope) }; } +} - fn get_isolate(&self) -> &Isolate { +impl<'sc> AsRef for HandleScope<'sc> { + fn as_ref(&self) -> &Isolate { + unsafe { v8__HandleScope__GetIsolate(self) } + } +} + +impl<'sc> AsMut for HandleScope<'sc> { + fn as_mut(&mut self) -> &mut Isolate { unsafe { v8__HandleScope__GetIsolate(self) } } } diff --git a/src/isolate.rs b/src/isolate.rs index 5bc82265..82d2b887 100644 --- a/src/isolate.rs +++ b/src/isolate.rs @@ -131,6 +131,18 @@ impl Isolate { } } +impl AsRef for Isolate { + fn as_ref(&self) -> &Isolate { + self + } +} + +impl AsMut for Isolate { + fn as_mut(&mut self) -> &mut Isolate { + self + } +} + /// Same as Isolate but gets disposed when it goes out of scope. pub struct OwnedIsolate(NonNull); diff --git a/src/json.rs b/src/json.rs index 52a12501..5c7e218d 100644 --- a/src/json.rs +++ b/src/json.rs @@ -18,19 +18,19 @@ extern "C" { /// Tries to parse the string `json_string` and returns it as value if /// successful. -pub fn parse( - mut context: Local, - mut json_string: Local, -) -> Option> { +pub fn parse<'sc>( + mut context: Local<'sc, Context>, + mut json_string: Local<'sc, String>, +) -> Option> { unsafe { Local::from_raw(v8__JSON__Parse(&mut *context, &mut *json_string)) } } /// Tries to stringify the JSON-serializable object `json_object` and returns /// it as string if successful. -pub fn stringify( - mut context: Local, - mut json_object: Local, -) -> Option> { +pub fn stringify<'sc>( + mut context: Local<'sc, Context>, + mut json_object: Local<'sc, Value>, +) -> Option> { unsafe { Local::from_raw(v8__JSON__Stringify(&mut *context, &mut *json_object)) } diff --git a/src/local.rs b/src/local.rs index 9bd6b51a..bf69398a 100644 --- a/src/local.rs +++ b/src/local.rs @@ -1,4 +1,5 @@ use crate::value::Value; +use std::marker::PhantomData; use std::ops::Deref; use std::ops::DerefMut; use std::ptr::NonNull; @@ -37,30 +38,30 @@ use std::ptr::NonNull; /// Note: Local handles in Rusty V8 differ from the V8 C++ API in that they are /// never empty. In situations where empty handles are needed, use /// Option. -pub struct Local(NonNull); +pub struct Local<'sc, T>(NonNull, PhantomData<&'sc ()>); -impl Copy for Local {} +impl<'sc, T> Copy for Local<'sc, T> {} -impl Clone for Local { +impl<'sc, T> Clone for Local<'sc, T> { fn clone(&self) -> Self { - Self(self.0) + Self(self.0, self.1) } } -impl Local { +impl<'sc, T> Local<'sc, T> { pub unsafe fn from_raw(ptr: *mut T) -> Option { - Some(Self(NonNull::new(ptr)?)) + Some(Self(NonNull::new(ptr)?, PhantomData)) } } -impl Deref for Local { +impl<'sc, T> Deref for Local<'sc, T> { type Target = T; fn deref(&self) -> &T { unsafe { self.0.as_ref() } } } -impl DerefMut for Local { +impl<'sc, T> DerefMut for Local<'sc, T> { fn deref_mut(&mut self) -> &mut T { unsafe { self.0.as_mut() } } @@ -68,11 +69,11 @@ impl DerefMut for Local { // TODO make it possible for targets other than Local. For example // Local should be able to be down cast to Local. -impl From> for Local +impl<'sc, T> From> for Local<'sc, Value> where T: Deref, { - fn from(v: Local) -> Local { + fn from(v: Local<'sc, T>) -> Local<'sc, Value> { unsafe { std::mem::transmute(v) } } } diff --git a/src/locker.rs b/src/locker.rs index 4d788355..ebcb42db 100644 --- a/src/locker.rs +++ b/src/locker.rs @@ -1,5 +1,6 @@ // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. use crate::isolate::Isolate; +use std::marker::PhantomData; use std::mem::MaybeUninit; extern "C" { @@ -12,9 +13,9 @@ extern "C" { /// construction and destruction, the current thread is allowed to use the locked /// isolate. V8 guarantees that an isolate can be locked by at most one thread at /// any time. In other words, the scope of a v8::Locker is a critical section. -pub struct Locker([usize; 2]); +pub struct Locker<'sc>([usize; 2], PhantomData<&'sc mut ()>); -impl Locker { +impl<'a> Locker<'a> { /// Initialize Locker for a given Isolate. pub fn new(isolate: &Isolate) -> Self { let mut buf = MaybeUninit::::uninit(); @@ -25,7 +26,7 @@ impl Locker { } } -impl Drop for Locker { +impl<'a> Drop for Locker<'a> { fn drop(&mut self) { unsafe { v8__Locker__DESTRUCT(self) } } diff --git a/src/module.rs b/src/module.rs index b119766f..ea1e989f 100644 --- a/src/module.rs +++ b/src/module.rs @@ -79,5 +79,8 @@ impl Module { } } -type ResolveCallback = - dyn Fn(Local, Local, Local) -> Option>; +type ResolveCallback<'sc> = dyn Fn( + Local<'sc, Context>, + Local<'sc, String>, + Local<'sc, Module>, +) -> Option>; diff --git a/src/number.rs b/src/number.rs index cce825bd..8fd01921 100644 --- a/src/number.rs +++ b/src/number.rs @@ -1,19 +1,20 @@ use std::ops::Deref; +use crate::isolate::Isolate; use crate::support::Opaque; -use crate::Isolate; +use crate::value::Value; +use crate::HandleScope; use crate::Local; -use crate::Value; extern "C" { - fn v8__Number__New(isolate: &Isolate, value: f64) -> *mut Number; + fn v8__Number__New(isolate: *mut Isolate, value: f64) -> *mut Number; fn v8__Number__Value(this: &Number) -> f64; - fn v8__Integer__New(isolate: &Isolate, value: i32) -> *mut Integer; + fn v8__Integer__New(isolate: *mut Isolate, value: i32) -> *mut Integer; fn v8__Integer__NewFromUnsigned( - isolate: &Isolate, + isolate: *mut Isolate, value: u32, ) -> *mut Integer; - fn v8__Integer__Value(this: &Integer) -> i64; + fn v8__Integer__Value(this: *const Integer) -> i64; } /// A JavaScript number value (ECMA-262, 4.3.20) @@ -21,9 +22,12 @@ extern "C" { pub struct Number(Opaque); impl Number { - pub fn new(isolate: &Isolate, value: f64) -> Local { + pub fn new<'sc>( + scope: &mut HandleScope<'sc>, + value: f64, + ) -> Local<'sc, Number> { unsafe { - let local = v8__Number__New(isolate, value); + let local = v8__Number__New(scope.as_mut(), value); Local::from_raw(local).unwrap() } } @@ -45,16 +49,22 @@ impl Deref for Number { pub struct Integer(Opaque); impl Integer { - pub fn new(isolate: &Isolate, value: i32) -> Local { + pub fn new<'sc>( + scope: &mut HandleScope<'sc>, + value: i32, + ) -> Local<'sc, Integer> { unsafe { - let local = v8__Integer__New(isolate, value); + let local = v8__Integer__New(scope.as_mut(), value); Local::from_raw(local).unwrap() } } - pub fn new_from_unsigned(isolate: &Isolate, value: u32) -> Local { + pub fn new_from_unsigned<'sc>( + scope: &mut HandleScope<'sc>, + value: u32, + ) -> Local<'sc, Integer> { unsafe { - let local = v8__Integer__NewFromUnsigned(isolate, value); + let local = v8__Integer__NewFromUnsigned(scope.as_mut(), value); Local::from_raw(local).unwrap() } } diff --git a/src/object.rs b/src/object.rs index 82dfd315..c2aa098c 100644 --- a/src/object.rs +++ b/src/object.rs @@ -2,6 +2,7 @@ use std::ops::Deref; use crate::isolate::Isolate; use crate::support::Opaque; +use crate::HandleScope; use crate::Local; use crate::Name; use crate::Value; @@ -12,7 +13,7 @@ pub struct Object(Opaque); extern "C" { fn v8__Object__New( - isolate: &Isolate, + isolate: *mut Isolate, prototype_or_null: *mut Value, names: *mut *mut Name, values: *mut *mut Value, @@ -28,13 +29,13 @@ impl Object { /// a prototype at all). This is similar to Object.create(). /// All properties will be created as enumerable, configurable /// and writable properties. - pub fn new( - isolate: &Isolate, - mut prototype_or_null: Local, - names: Vec>, - values: Vec>, + pub fn new<'sc>( + scope: &mut HandleScope<'sc>, + mut prototype_or_null: Local<'sc, Value>, + names: Vec>, + values: Vec>, length: usize, - ) -> Local { + ) -> Local<'sc, Object> { let mut names_: Vec<*mut Name> = vec![]; for mut name in names { let n = &mut *name; @@ -48,7 +49,7 @@ impl Object { } unsafe { Local::from_raw(v8__Object__New( - isolate, + scope.as_mut(), &mut *prototype_or_null, names_.as_mut_ptr(), values_.as_mut_ptr(), diff --git a/src/primitives.rs b/src/primitives.rs index 43f2615a..8f84649e 100644 --- a/src/primitives.rs +++ b/src/primitives.rs @@ -2,6 +2,7 @@ use std::ops::Deref; use crate::isolate::Isolate; use crate::support::Opaque; +use crate::HandleScope; use crate::Local; use crate::Value; @@ -19,29 +20,31 @@ pub struct Boolean(Opaque); pub struct Name(Opaque); extern "C" { - fn v8__Null(isolate: &Isolate) -> *mut Primitive; + fn v8__Null(isolate: *mut Isolate) -> *mut Primitive; - fn v8__Undefined(isolate: &Isolate) -> *mut Primitive; + fn v8__Undefined(isolate: *mut Isolate) -> *mut Primitive; - fn v8__True(isolate: &Isolate) -> *mut Boolean; + fn v8__True(isolate: *mut Isolate) -> *mut Boolean; - fn v8__False(isolate: &Isolate) -> *mut Boolean; + fn v8__False(isolate: *mut Isolate) -> *mut Boolean; } -pub fn new_null(isolate: &Isolate) -> Local { - unsafe { Local::from_raw(v8__Null(isolate)) }.unwrap() +pub fn new_null<'sc>(scope: &mut HandleScope<'sc>) -> Local<'sc, Primitive> { + unsafe { Local::from_raw(v8__Null(scope.as_mut())) }.unwrap() } -pub fn new_undefined(isolate: &Isolate) -> Local { - unsafe { Local::from_raw(v8__Undefined(isolate)) }.unwrap() +pub fn new_undefined<'sc>( + scope: &mut HandleScope<'sc>, +) -> Local<'sc, Primitive> { + unsafe { Local::from_raw(v8__Undefined(scope.as_mut())) }.unwrap() } -pub fn new_true(isolate: &Isolate) -> Local { - unsafe { Local::from_raw(v8__True(isolate)) }.unwrap() +pub fn new_true<'sc>(scope: &mut HandleScope<'sc>) -> Local<'sc, Boolean> { + unsafe { Local::from_raw(v8__True(scope.as_mut())) }.unwrap() } -pub fn new_false(isolate: &Isolate) -> Local { - unsafe { Local::from_raw(v8__False(isolate)) }.unwrap() +pub fn new_false<'sc>(scope: &mut HandleScope<'sc>) -> Local<'sc, Boolean> { + unsafe { Local::from_raw(v8__False(scope.as_mut())) }.unwrap() } impl Deref for Primitive { diff --git a/src/promise.rs b/src/promise.rs index 52256dac..4d217a93 100644 --- a/src/promise.rs +++ b/src/promise.rs @@ -1,7 +1,10 @@ +use std::marker::PhantomData; + use crate::support::MaybeBool; use crate::support::Opaque; use crate::Context; use crate::Function; +use crate::HandleScope; use crate::Local; use crate::Value; @@ -77,18 +80,21 @@ impl Promise { /// Returns the content of the [[PromiseResult]] field. The Promise must not /// be pending. - pub fn result(&mut self) -> Local { + pub fn result<'sc>( + &mut self, + _scope: &mut HandleScope<'sc>, + ) -> Local<'sc, Value> { unsafe { Local::from_raw(v8__Promise__Result(&mut *self)).unwrap() } } /// Register a rejection handler with a promise. /// /// See `Self::then2`. - pub fn catch( + pub fn catch<'sc>( &mut self, - mut context: Local, - mut handler: Local, - ) -> Option> { + mut context: Local<'sc, Context>, + mut handler: Local<'sc, Function>, + ) -> Option> { unsafe { Local::from_raw(v8__Promise__Catch( &mut *self, @@ -101,11 +107,11 @@ impl Promise { /// Register a resolution handler with a promise. /// /// See `Self::then2`. - pub fn then( + pub fn then<'sc>( &mut self, - mut context: Local, - mut handler: Local, - ) -> Option> { + mut context: Local<'sc, Context>, + mut handler: Local<'sc, Function>, + ) -> Option> { unsafe { Local::from_raw(v8__Promise__Then( &mut *self, @@ -119,12 +125,12 @@ 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( + pub fn then2<'sc>( &mut self, - mut context: Local, - mut on_fulfilled: Local, - mut on_rejected: Local, - ) -> Option> { + mut context: Local<'sc, Context>, + mut on_fulfilled: Local<'sc, Function>, + mut on_rejected: Local<'sc, Function>, + ) -> Option> { unsafe { Local::from_raw(v8__Promise__Then2( &mut *self, @@ -141,12 +147,18 @@ pub struct PromiseResolver(Opaque); impl PromiseResolver { /// Create a new resolver, along with an associated promise in pending state. - pub fn new(mut context: Local) -> Option> { + pub fn new<'sc>( + _scope: &mut HandleScope<'sc>, + mut context: Local<'sc, Context>, + ) -> Option> { unsafe { Local::from_raw(v8__Promise__Resolver__New(&mut *context)) } } /// Extract the associated promise. - pub fn get_promise(&mut self) -> Local { + pub fn get_promise<'sc>( + &mut self, + _scope: &mut HandleScope<'sc>, + ) -> Local<'sc, Promise> { unsafe { Local::from_raw(v8__Promise__Resolver__GetPromise(&mut *self)).unwrap() } @@ -154,10 +166,10 @@ impl PromiseResolver { /// Resolve the associated promise with a given value. /// Ignored if the promise is no longer pending. - pub fn resolve( + pub fn resolve<'sc>( &mut self, - mut context: Local, - mut value: Local, + mut context: Local<'sc, Context>, + mut value: Local<'sc, Value>, ) -> Option { unsafe { v8__Promise__Resolver__Resolve(&mut *self, &mut *context, &mut *value) @@ -167,10 +179,10 @@ impl PromiseResolver { /// Reject the associated promise with a given value. /// Ignored if the promise is no longer pending. - pub fn reject( + pub fn reject<'sc>( &mut self, - mut context: Local, - mut value: Local, + mut context: Local<'sc, Context>, + mut value: Local<'sc, Value>, ) -> Option { unsafe { v8__Promise__Resolver__Reject(&mut *self, &mut *context, &mut *value) @@ -189,10 +201,10 @@ pub enum PromiseRejectEvent { } #[repr(C)] -pub struct PromiseRejectMessage([usize; 3]); +pub struct PromiseRejectMessage<'msg>([usize; 3], PhantomData<&'msg ()>); -impl PromiseRejectMessage { - pub fn get_promise(&self) -> Local { +impl<'msg> PromiseRejectMessage<'msg> { + pub fn get_promise(&self) -> Local<'msg, Promise> { unsafe { Local::from_raw(v8__PromiseRejectMessage__GetPromise(self)).unwrap() } @@ -202,7 +214,7 @@ impl PromiseRejectMessage { unsafe { v8__PromiseRejectMessage__GetEvent(self) } } - pub fn get_value(&self) -> Local { + pub fn get_value(&self) -> Local<'msg, Value> { unsafe { Local::from_raw(v8__PromiseRejectMessage__GetValue(self)).unwrap() } diff --git a/src/script.rs b/src/script.rs index fa8ecbc3..d2004cb7 100644 --- a/src/script.rs +++ b/src/script.rs @@ -1,9 +1,11 @@ +use std::marker::PhantomData; use std::mem::MaybeUninit; 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; @@ -11,7 +13,7 @@ use crate::Value; /// The origin, within a file, of a script. #[repr(C)] -pub struct ScriptOrigin([usize; 7]); +pub struct ScriptOrigin<'sc>([usize; 7], PhantomData<&'sc ()>); extern "C" { fn v8__Script__Compile( @@ -42,11 +44,12 @@ pub struct Script(Opaque); impl Script { /// A shorthand for ScriptCompiler::Compile(). - pub fn compile( + pub fn compile<'sc>( + _scope: &mut HandleScope<'sc>, mut context: Local, mut source: Local, - origin: Option<&'_ ScriptOrigin>, - ) -> Option> { + origin: Option<&ScriptOrigin>, + ) -> Option> { // TODO: use the type system to enforce that a Context has been entered. // TODO: `context` and `source` probably shouldn't be mut. unsafe { @@ -61,24 +64,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(&mut self, mut context: Local) -> Option> { + pub fn run<'sc>( + &mut self, + _scope: &mut HandleScope<'sc>, + mut context: Local, + ) -> Option> { unsafe { Local::from_raw(v8__Script__Run(self, &mut *context)) } } } /// The origin, within a file, of a script. -impl ScriptOrigin { +impl<'sc> ScriptOrigin<'sc> { #[allow(clippy::too_many_arguments)] pub fn new( - mut resource_name: Local, - mut resource_line_offset: Local, - mut resource_column_offset: Local, - mut resource_is_shared_cross_origin: Local, - mut script_id: Local, - mut source_map_url: Local, - mut resource_is_opaque: Local, - mut is_wasm: Local, - mut is_module: Local, + mut resource_name: Local<'sc, Value>, + mut resource_line_offset: Local<'sc, Integer>, + mut resource_column_offset: Local<'sc, Integer>, + mut resource_is_shared_cross_origin: Local<'sc, Boolean>, + mut script_id: Local<'sc, Integer>, + mut source_map_url: Local<'sc, Value>, + mut resource_is_opaque: Local<'sc, Boolean>, + mut is_wasm: Local<'sc, Boolean>, + mut is_module: Local<'sc, Boolean>, ) -> Self { unsafe { let mut buf = std::mem::MaybeUninit::::uninit(); diff --git a/src/string.rs b/src/string.rs index c85447b2..bc0a3ec2 100644 --- a/src/string.rs +++ b/src/string.rs @@ -8,12 +8,13 @@ use crate::isolate::Isolate; use crate::support::char; use crate::support::int; use crate::support::Opaque; +use crate::HandleScope; use crate::Local; use crate::Value; extern "C" { fn v8__String__NewFromUtf8( - isolate: &Isolate, + isolate: *mut Isolate, data: *const char, new_type: NewStringType, length: int, @@ -21,11 +22,11 @@ extern "C" { fn v8__String__Length(this: &String) -> int; - fn v8__String__Utf8Length(this: &String, isolate: &Isolate) -> int; + fn v8__String__Utf8Length(this: &String, isolate: *mut Isolate) -> int; fn v8__String__WriteUtf8( this: &String, - isolate: &Isolate, + isolate: *mut Isolate, buffer: *mut char, length: int, nchars_ref: *mut int, @@ -65,14 +66,14 @@ bitflags! { pub struct String(Opaque); impl String { - pub fn new_from_utf8( - isolate: &Isolate, + pub fn new_from_utf8<'sc>( + scope: &mut HandleScope<'sc>, buffer: &[u8], new_type: NewStringType, - ) -> Option> { + ) -> Option> { unsafe { let ptr = v8__String__NewFromUtf8( - isolate, + scope.as_mut(), buffer.as_ptr() as *const char, new_type, buffer.len().try_into().ok()?, @@ -88,13 +89,13 @@ impl String { /// Returns the number of bytes in the UTF-8 encoded representation of this /// string. - pub fn utf8_length(&self, isolate: &Isolate) -> usize { - unsafe { v8__String__Utf8Length(self, isolate) as usize } + pub fn utf8_length(&self, isolate: &mut impl AsMut) -> usize { + unsafe { v8__String__Utf8Length(self, isolate.as_mut()) as usize } } pub fn write_utf8( &self, - isolate: &Isolate, + isolate: &mut Isolate, buffer: &mut [u8], nchars_ref: Option<&mut usize>, options: WriteOptions, @@ -117,16 +118,20 @@ impl String { } // Convenience function not present in the original V8 API. - pub fn new( - isolate: &Isolate, + pub fn new<'sc>( + scope: &mut HandleScope<'sc>, value: &str, new_type: NewStringType, - ) -> Option> { - Self::new_from_utf8(isolate, value.as_ref(), new_type) + ) -> Option> { + Self::new_from_utf8(scope, value.as_ref(), new_type) } // Convenience function not present in the original V8 API. - pub fn to_rust_string_lossy(&self, isolate: &Isolate) -> std::string::String { + pub fn to_rust_string_lossy( + &self, + isolate: &mut impl AsMut, + ) -> std::string::String { + let isolate = isolate.as_mut(); let capacity = self.utf8_length(isolate); let mut string = std::string::String::with_capacity(capacity); let data = string.as_mut_ptr(); diff --git a/tests/test_api.rs b/tests/test_api.rs index 1b91436c..8b2670d3 100644 --- a/tests/test_api.rs +++ b/tests/test_api.rs @@ -4,7 +4,8 @@ extern crate lazy_static; use rusty_v8 as v8; -use rusty_v8::{new_null, FunctionCallbackInfo, Local}; +use rusty_v8::{new_null, FunctionCallbackInfo, HandleScope, Local}; +use std::default::Default; use std::sync::Mutex; lazy_static! { @@ -64,11 +65,11 @@ fn handle_scope_numbers() { ); let isolate = v8::Isolate::new(params); let locker = v8::Locker::new(&isolate); - v8::HandleScope::enter(&isolate, |_scope| { - let l1 = v8::Integer::new(&isolate, -123); - let l2 = v8::Integer::new_from_unsigned(&isolate, 456); - v8::HandleScope::enter(&isolate, |_scope2| { - let l3 = v8::Number::new(&isolate, 78.9); + v8::HandleScope::enter(&isolate, |scope| { + let l1 = v8::Integer::new(scope, -123); + let l2 = v8::Integer::new_from_unsigned(scope, 456); + v8::HandleScope::enter(&isolate, |scope2| { + let l3 = v8::Number::new(scope2, 78.9); assert_eq!(l1.value(), -123); assert_eq!(l2.value(), 456); assert_eq!(l3.value(), 78.9); @@ -89,18 +90,22 @@ fn test_string() { ); let isolate = v8::Isolate::new(params); let locker = v8::Locker::new(&isolate); - v8::HandleScope::enter(&isolate, |_scope| { + v8::HandleScope::enter(&isolate, |scope| { let reference = "Hello 🦕 world!"; - let local = v8_str(&isolate, reference); + let local = + v8::String::new(scope, reference, v8::NewStringType::Normal).unwrap(); assert_eq!(15, local.length()); - assert_eq!(17, local.utf8_length(&isolate)); - assert_eq!(reference, local.to_rust_string_lossy(&isolate)); + assert_eq!(17, local.utf8_length(scope)); + assert_eq!(reference, local.to_rust_string_lossy(scope)); }); drop(locker); } -fn v8_str(isolate: &v8::Isolate, s: &str) -> v8::Local { - v8::String::new(&isolate, s, v8::NewStringType::Normal).unwrap() +fn v8_str<'sc>( + scope: &mut HandleScope<'sc>, + s: &str, +) -> v8::Local<'sc, v8::String> { + v8::String::new(scope, s, v8::NewStringType::Normal).unwrap() } #[test] @@ -122,18 +127,20 @@ fn isolate_add_message_listener() { ) { CALL_COUNT.fetch_add(1, Ordering::SeqCst); let isolate = message.get_isolate(); - let message_str = message.get(); - assert_eq!(message_str.to_rust_string_lossy(&isolate), "Uncaught foo"); + v8::HandleScope::enter(&isolate, |scope| { + 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 locker = v8::Locker::new(&isolate); - v8::HandleScope::enter(&isolate, |_s| { - let mut context = v8::Context::new(&isolate); + v8::HandleScope::enter(&isolate, |s| { + let mut context = v8::Context::new(s); context.enter(); - let source = v8_str(&isolate, "throw 'foo'"); - let mut script = v8::Script::compile(context, source, None).unwrap(); - assert!(script.run(context).is_none()); + let source = v8::String::new(s, "throw 'foo'", Default::default()).unwrap(); + let mut script = v8::Script::compile(s, context, source, None).unwrap(); + assert!(script.run(s, context).is_none()); assert_eq!(CALL_COUNT.load(Ordering::SeqCst), 1); context.exit(); }); @@ -151,17 +158,19 @@ fn script_compile_and_run() { let isolate = v8::Isolate::new(params); let locker = v8::Locker::new(&isolate); - v8::HandleScope::enter(&isolate, |_s| { - let mut context = v8::Context::new(&isolate); + v8::HandleScope::enter(&isolate, |s| { + let mut context = v8::Context::new(s); context.enter(); - let source = v8_str(&isolate, "'Hello ' + 13 + 'th planet'"); - let mut script = v8::Script::compile(context, source, None).unwrap(); - source.to_rust_string_lossy(&isolate); - let result = script.run(context).unwrap(); + let source = + v8::String::new(s, "'Hello ' + 13 + 'th planet'", Default::default()) + .unwrap(); + let mut script = v8::Script::compile(s, context, source, None).unwrap(); + source.to_rust_string_lossy(s); + let result = script.run(s, context).unwrap(); // TODO: safer casts. let result: v8::Local = unsafe { std::mem::transmute_copy(&result) }; - assert_eq!(result.to_rust_string_lossy(&isolate), "Hello 13th planet"); + assert_eq!(result.to_rust_string_lossy(s), "Hello 13th planet"); context.exit(); }); drop(locker); @@ -177,19 +186,21 @@ fn script_origin() { let isolate = v8::Isolate::new(params); let locker = v8::Locker::new(&isolate); - v8::HandleScope::enter(&isolate, |_s| { - let mut context = v8::Context::new(&isolate); + v8::HandleScope::enter(&isolate, |s| { + let mut context = v8::Context::new(s); context.enter(); - let resource_name = v8_str(&isolate, "foo.js"); - let resource_line_offset = v8::Integer::new(&isolate, 4); - let resource_column_offset = v8::Integer::new(&isolate, 5); - 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_false(&isolate); + let resource_name = + v8::String::new(s, "foo.js", Default::default()).unwrap(); + let resource_line_offset = v8::Integer::new(s, 4); + let resource_column_offset = v8::Integer::new(s, 5); + let resource_is_shared_cross_origin = v8::new_true(s); + let script_id = v8::Integer::new(s, 123); + let source_map_url = + v8::String::new(s, "source_map_url", Default::default()).unwrap(); + let resource_is_opaque = v8::new_true(s); + let is_wasm = v8::new_false(s); + let is_module = v8::new_false(s); let script_origin = v8::ScriptOrigin::new( resource_name.into(), @@ -203,11 +214,11 @@ fn script_origin() { is_module, ); - let source = v8_str(&isolate, "1+2"); + let source = v8::String::new(s, "1+2", Default::default()).unwrap(); let mut script = - v8::Script::compile(context, source, Some(&script_origin)).unwrap(); - source.to_rust_string_lossy(&isolate); - let _result = script.run(context).unwrap(); + v8::Script::compile(s, context, source, Some(&script_origin)).unwrap(); + source.to_rust_string_lossy(s); + let _result = script.run(s, context).unwrap(); context.exit(); }); drop(locker); @@ -268,23 +279,23 @@ fn test_primitives() { ); let isolate = v8::Isolate::new(params); let locker = v8::Locker::new(&isolate); - v8::HandleScope::enter(&isolate, |_scope| { - let null = v8::new_null(&isolate); + v8::HandleScope::enter(&isolate, |scope| { + let null = v8::new_null(scope); assert!(!null.is_undefined()); assert!(null.is_null()); assert!(null.is_null_or_undefined()); - let undefined = v8::new_undefined(&isolate); + let undefined = v8::new_undefined(scope); assert!(undefined.is_undefined()); assert!(!undefined.is_null()); assert!(undefined.is_null_or_undefined()); - let true_ = v8::new_true(&isolate); + let true_ = v8::new_true(scope); assert!(!true_.is_undefined()); assert!(!true_.is_null()); assert!(!true_.is_null_or_undefined()); - let false_ = v8::new_false(&isolate); + let false_ = v8::new_false(scope); assert!(!false_.is_undefined()); assert!(!false_.is_null()); assert!(!false_.is_null_or_undefined()); @@ -302,24 +313,25 @@ fn exception() { let mut isolate = v8::Isolate::new(params); let locker = v8::Locker::new(&isolate); isolate.enter(); - v8::HandleScope::enter(&isolate, |_scope| { - let mut context = v8::Context::new(&isolate); + v8::HandleScope::enter(&isolate, |scope| { + let mut context = v8::Context::new(scope); context.enter(); let reference = "This is a test error"; - let local = v8_str(&isolate, reference); - v8::range_error(local); - v8::reference_error(local); - v8::syntax_error(local); - v8::type_error(local); - let exception = v8::error(local); - let msg = v8::create_message(&isolate, exception); - let msg_string = msg.get(); - let rust_msg_string = msg_string.to_rust_string_lossy(&isolate); + let local = + v8::String::new(scope, reference, v8::NewStringType::Normal).unwrap(); + v8::range_error(scope, local); + v8::reference_error(scope, local); + v8::syntax_error(scope, local); + v8::type_error(scope, local); + let exception = v8::error(scope, local); + let msg = v8::create_message(scope, exception); + let msg_string = msg.get(scope); + let rust_msg_string = msg_string.to_rust_string_lossy(scope); assert_eq!( "Uncaught Error: This is a test error".to_string(), rust_msg_string ); - assert!(v8::get_stack_trace(exception).is_none()); + assert!(v8::get_stack_trace(scope, exception).is_none()); context.exit(); }); drop(locker); @@ -335,17 +347,17 @@ fn json() { ); let isolate = v8::Isolate::new(params); let locker = v8::Locker::new(&isolate); - v8::HandleScope::enter(&isolate, |_s| { - let mut context = v8::Context::new(&isolate); + v8::HandleScope::enter(&isolate, |s| { + let mut context = v8::Context::new(s); context.enter(); - let json_string = v8_str(&isolate, "{\"a\": 1, \"b\": 2}"); + let json_string = v8_str(s, "{\"a\": 1, \"b\": 2}"); let maybe_value = v8::json::parse(context, json_string); assert!(maybe_value.is_some()); let value = maybe_value.unwrap(); let maybe_stringified = v8::json::stringify(context, value); assert!(maybe_stringified.is_some()); let stringified = maybe_stringified.unwrap(); - let rust_str = stringified.to_rust_string_lossy(&isolate); + let rust_str = stringified.to_rust_string_lossy(s); assert_eq!("{\"a\":1,\"b\":2}".to_string(), rust_str); context.exit(); }); @@ -367,19 +379,19 @@ fn object() { ); let isolate = v8::Isolate::new(params); let locker = v8::Locker::new(&isolate); - v8::HandleScope::enter(&isolate, |_scope| { - let mut context = v8::Context::new(&isolate); + v8::HandleScope::enter(&isolate, |scope| { + let mut context = v8::Context::new(scope); context.enter(); - let null: v8::Local = new_null(&isolate).into(); - let s1 = v8_str(&isolate, "a"); - let s2 = v8_str(&isolate, "b"); + let null: v8::Local = new_null(scope).into(); + let s1 = v8::String::new(scope, "a", v8::NewStringType::Normal).unwrap(); + let s2 = v8::String::new(scope, "b", v8::NewStringType::Normal).unwrap(); let name1: Local = cast(s1); let name2: Local = cast(s2); let names = vec![name1, name2]; - let v1: v8::Local = v8::Number::new(&isolate, 1.0).into(); - let v2: v8::Local = v8::Number::new(&isolate, 2.0).into(); + let v1: v8::Local = v8::Number::new(scope, 1.0).into(); + let v2: v8::Local = v8::Number::new(scope, 2.0).into(); let values = vec![v1, v2]; - let object = v8::Object::new(&isolate, null, names, values, 2); + let object = v8::Object::new(scope, null, names, values, 2); assert!(!object.is_null_or_undefined()); context.exit(); }); @@ -395,36 +407,32 @@ fn promise_resolved() { ); let isolate = v8::Isolate::new(params); let locker = v8::Locker::new(&isolate); - v8::HandleScope::enter(&isolate, |_scope| { - let mut context = v8::Context::new(&isolate); + v8::HandleScope::enter(&isolate, |scope| { + let mut context = v8::Context::new(scope); context.enter(); - let maybe_resolver = v8::PromiseResolver::new(context); + let maybe_resolver = v8::PromiseResolver::new(scope, context); assert!(maybe_resolver.is_some()); let mut resolver = maybe_resolver.unwrap(); - let mut promise = resolver.get_promise(); + let mut promise = resolver.get_promise(scope); assert!(!promise.has_handler()); assert_eq!(promise.state(), v8::PromiseState::Pending); - let str = v8_str(&isolate, "test"); + let str = + v8::String::new(scope, "test", v8::NewStringType::Normal).unwrap(); let value: Local = cast(str); resolver.resolve(context, value); assert_eq!(promise.state(), v8::PromiseState::Fulfilled); - let result = promise.result(); + let result = promise.result(scope); let result_str: v8::Local = cast(result); - assert_eq!( - result_str.to_rust_string_lossy(&isolate), - "test".to_string() - ); + assert_eq!(result_str.to_rust_string_lossy(scope), "test".to_string()); // Resolve again with different value, since promise is already in `Fulfilled` state // it should be ignored. - let str = v8_str(&isolate, "test2"); + let str = + v8::String::new(scope, "test2", v8::NewStringType::Normal).unwrap(); let value: Local = cast(str); resolver.resolve(context, value); - let result = promise.result(); + let result = promise.result(scope); let result_str: v8::Local = cast(result); - assert_eq!( - result_str.to_rust_string_lossy(&isolate), - "test".to_string() - ); + assert_eq!(result_str.to_rust_string_lossy(scope), "test".to_string()); context.exit(); }); drop(locker); @@ -439,37 +447,33 @@ fn promise_rejected() { ); let isolate = v8::Isolate::new(params); let locker = v8::Locker::new(&isolate); - v8::HandleScope::enter(&isolate, |_scope| { - let mut context = v8::Context::new(&isolate); + v8::HandleScope::enter(&isolate, |scope| { + let mut context = v8::Context::new(scope); context.enter(); - let maybe_resolver = v8::PromiseResolver::new(context); + let maybe_resolver = v8::PromiseResolver::new(scope, context); assert!(maybe_resolver.is_some()); let mut resolver = maybe_resolver.unwrap(); - let mut promise = resolver.get_promise(); + let mut promise = resolver.get_promise(scope); assert!(!promise.has_handler()); assert_eq!(promise.state(), v8::PromiseState::Pending); - let str = v8_str(&isolate, "test"); + let str = + v8::String::new(scope, "test", v8::NewStringType::Normal).unwrap(); let value: Local = cast(str); let rejected = resolver.reject(context, value); assert!(rejected.unwrap()); assert_eq!(promise.state(), v8::PromiseState::Rejected); - let result = promise.result(); + let result = promise.result(scope); let result_str: v8::Local = cast(result); - assert_eq!( - result_str.to_rust_string_lossy(&isolate), - "test".to_string() - ); + assert_eq!(result_str.to_rust_string_lossy(scope), "test".to_string()); // Reject again with different value, since promise is already in `Rejected` state // it should be ignored. - let str = v8_str(&isolate, "test2"); + let str = + v8::String::new(scope, "test2", v8::NewStringType::Normal).unwrap(); let value: Local = cast(str); resolver.reject(context, value); - let result = promise.result(); + let result = promise.result(scope); let result_str: v8::Local = cast(result); - assert_eq!( - result_str.to_rust_string_lossy(&isolate), - "test".to_string() - ); + assert_eq!(result_str.to_rust_string_lossy(scope), "test".to_string()); context.exit(); }); drop(locker); @@ -478,16 +482,15 @@ fn promise_rejected() { extern "C" fn fn_callback(info: &FunctionCallbackInfo) { assert_eq!(info.length(), 0); let isolate = info.get_isolate(); - v8::HandleScope::enter(&isolate, |_scope| { - let mut context = v8::Context::new(&isolate); - context.enter(); - let s = v8_str(&isolate, "Hello callback!"); + v8::HandleScope::enter(&isolate, |scope| { + let s = + v8::String::new(scope, "Hello callback!", v8::NewStringType::Normal) + .unwrap(); let value: Local = s.into(); let rv = &mut info.get_return_value(); - let rv_value = rv.get(); + let rv_value = rv.get(scope); assert!(rv_value.is_undefined()); rv.set(value); - context.exit(); }); } @@ -500,25 +503,26 @@ fn function() { ); let isolate = v8::Isolate::new(params); let locker = v8::Locker::new(&isolate); - v8::HandleScope::enter(&isolate, |_scope| { - let mut context = v8::Context::new(&isolate); + v8::HandleScope::enter(&isolate, |scope| { + let mut context = v8::Context::new(scope); context.enter(); let global = context.global(); let recv: Local = global.into(); // create function using template - let mut fn_template = v8::FunctionTemplate::new(&isolate, fn_callback); + let mut fn_template = v8::FunctionTemplate::new(scope, fn_callback); let mut function = fn_template - .get_function(context) + .get_function(scope, context) .expect("Unable to create function"); - let _value = v8::Function::call(&mut *function, context, recv, 0, vec![]); + let _value = + v8::Function::call(&mut *function, scope, context, recv, 0, vec![]); // create function without a template - let mut function = v8::Function::new(context, fn_callback) + let mut function = v8::Function::new(scope, context, fn_callback) .expect("Unable to create function"); let maybe_value = - v8::Function::call(&mut *function, context, recv, 0, vec![]); + v8::Function::call(&mut *function, scope, context, recv, 0, vec![]); let value = maybe_value.unwrap(); let value_str: v8::Local = cast(value); - let rust_str = value_str.to_rust_string_lossy(&isolate); + let rust_str = value_str.to_rust_string_lossy(scope); assert_eq!(rust_str, "Hello callback!".to_string()); context.exit(); }); @@ -534,9 +538,9 @@ extern "C" fn promise_reject_callback(msg: v8::PromiseRejectMessage) { let isolate = promise_obj.get_isolate(); let value = msg.get_value(); let locker = v8::Locker::new(isolate); - v8::HandleScope::enter(&isolate, |_scope| { + v8::HandleScope::enter(&isolate, |scope| { let value_str: v8::Local = cast(value); - let rust_str = value_str.to_rust_string_lossy(&isolate); + let rust_str = value_str.to_rust_string_lossy(scope); assert_eq!(rust_str, "promise rejected".to_string()); }); drop(locker); @@ -553,11 +557,13 @@ fn set_promise_reject_callback() { isolate.set_promise_reject_callback(promise_reject_callback); isolate.enter(); let locker = v8::Locker::new(&isolate); - v8::HandleScope::enter(&isolate, |_scope| { - let mut context = v8::Context::new(&isolate); + v8::HandleScope::enter(&isolate, |scope| { + let mut context = v8::Context::new(scope); context.enter(); - let mut resolver = v8::PromiseResolver::new(context).unwrap(); - let str_ = v8_str(&isolate, "promise rejected"); + let mut resolver = v8::PromiseResolver::new(scope, context).unwrap(); + let str_ = + v8::String::new(scope, "promise rejected", v8::NewStringType::Normal) + .unwrap(); let value: Local = cast(str_); resolver.reject(context, value); context.exit(); @@ -566,16 +572,18 @@ fn set_promise_reject_callback() { isolate.exit(); } -fn mock_script_origin(isolate: &v8::Isolate) -> v8::ScriptOrigin { - let resource_name = v8_str(&isolate, "foo.js"); - let resource_line_offset = v8::Integer::new(&isolate, 4); - let resource_column_offset = v8::Integer::new(&isolate, 5); - 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); +fn mock_script_origin<'sc>( + scope: &mut HandleScope<'sc>, +) -> v8::ScriptOrigin<'sc> { + let resource_name = v8_str(scope, "foo.js"); + let resource_line_offset = v8::Integer::new(scope, 4); + let resource_column_offset = v8::Integer::new(scope, 5); + 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, @@ -600,16 +608,14 @@ fn script_compiler_source() { isolate.set_promise_reject_callback(promise_reject_callback); isolate.enter(); let locker = v8::Locker::new(&isolate); - v8::HandleScope::enter(&isolate, |_scope| { - let mut context = v8::Context::new(&isolate); + v8::HandleScope::enter(&isolate, |scope| { + let mut context = v8::Context::new(scope); context.enter(); let source = "1+2"; - let script_origin = mock_script_origin(&isolate); - let source = v8::script_compiler::Source::new( - v8_str(&isolate, source), - &script_origin, - ); + let script_origin = mock_script_origin(scope); + let source = + v8::script_compiler::Source::new(v8_str(scope, source), &script_origin); let result = v8::script_compiler::compile_module( &isolate,