diff --git a/benches/function.rs b/benches/function.rs index 3c6e906b..b1b9f8d9 100644 --- a/benches/function.rs +++ b/benches/function.rs @@ -31,9 +31,9 @@ fn main() { } { extern "C" fn callback(info: *const v8::FunctionCallbackInfo) { - let scope = unsafe { &mut v8::CallbackScope::new(&*info) }; - let mut rv = - unsafe { v8::ReturnValue::from_function_callback_info(info) }; + let info = unsafe { &*info }; + let scope = unsafe { &mut v8::CallbackScope::new(info) }; + let mut rv = v8::ReturnValue::from_function_callback_info(info); rv.set(v8::Integer::new(scope, 42).into()); } let func = v8::Function::new_raw(scope, callback).unwrap(); @@ -42,8 +42,8 @@ fn main() { } { extern "C" fn callback(info: *const v8::FunctionCallbackInfo) { - let mut rv = - unsafe { v8::ReturnValue::from_function_callback_info(info) }; + let info = unsafe { &*info }; + let mut rv = v8::ReturnValue::from_function_callback_info(info); rv.set_uint32(42); } let func = v8::Function::new_raw(scope, callback).unwrap(); @@ -96,9 +96,9 @@ fn main() { { extern "C" fn callback(info: *const v8::FunctionCallbackInfo) { - let scope = unsafe { &mut v8::CallbackScope::new(&*info) }; - let mut rv = - unsafe { v8::ReturnValue::from_function_callback_info(info) }; + let info = unsafe { &*info }; + let scope = unsafe { &mut v8::CallbackScope::new(info) }; + let mut rv = v8::ReturnValue::from_function_callback_info(info); rv.set(v8::undefined(scope).into()); } let func = v8::Function::new_raw(scope, callback).unwrap(); @@ -108,12 +108,11 @@ fn main() { { extern "C" fn callback(info: *const v8::FunctionCallbackInfo) { - let mut rv = - unsafe { v8::ReturnValue::from_function_callback_info(info) }; - let mut info = unsafe { - v8::FunctionCallbackArguments::from_function_callback_info(info) - }; - rv.set(v8::undefined(unsafe { info.get_isolate() }).into()); + let info = unsafe { &*info }; + let mut rv = v8::ReturnValue::from_function_callback_info(info); + let mut args = + v8::FunctionCallbackArguments::from_function_callback_info(info); + rv.set(v8::undefined(unsafe { args.get_isolate() }).into()); } let func = v8::Function::new_raw(scope, callback).unwrap(); let name = v8::String::new(scope, "undefined_from_isolate").unwrap(); diff --git a/src/binding.cc b/src/binding.cc index 5804af96..08d1da16 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -100,7 +100,7 @@ static_assert(offsetof(v8::ScriptCompiler::CachedData, buffer_policy) == 12, #endif extern "C" { -const extern size_t v8__internal__Internals__kIsolateEmbedderDataOffset = +const extern int v8__internal__Internals__kIsolateEmbedderDataOffset = v8::internal::Internals::kIsolateEmbedderDataOffset; void v8__V8__SetFlagsFromCommandLine(int* argc, char** argv, @@ -1908,39 +1908,15 @@ const v8::ObjectTemplate* v8__FunctionTemplate__InstanceTemplate( return local_to_ptr(ptr_to_local(&self)->InstanceTemplate()); } -v8::Isolate* v8__FunctionCallbackInfo__GetIsolate( - const v8::FunctionCallbackInfo& self) { - return self.GetIsolate(); -} +const extern int v8__FunctionCallbackInfo__kArgsLength = + v8::FunctionCallbackInfo::kArgsLength; -v8::Value* v8__FunctionCallbackInfo__GetReturnValue( - const v8::FunctionCallbackInfo& self) { - return make_pod(self.GetReturnValue()); -} +const extern int v8__PropertyCallbackInfo__kArgsLength = + v8::PropertyCallbackInfo::kArgsLength; -const v8::Object* v8__FunctionCallbackInfo__This( - const v8::FunctionCallbackInfo& self) { - return local_to_ptr(self.This()); -} - -int v8__FunctionCallbackInfo__Length( - const v8::FunctionCallbackInfo& self) { - return self.Length(); -} - -const v8::Value* v8__FunctionCallbackInfo__GetArgument( - const v8::FunctionCallbackInfo& self, int i) { - return local_to_ptr(self[i]); -} - -const v8::Value* v8__FunctionCallbackInfo__Data( - const v8::FunctionCallbackInfo& self) { - return local_to_ptr(self.Data()); -} - -const v8::Value* v8__FunctionCallbackInfo__NewTarget( - const v8::FunctionCallbackInfo& self) { - return local_to_ptr(self.NewTarget()); +bool v8__PropertyCallbackInfo__ShouldThrowOnError( + const v8::PropertyCallbackInfo& self) { + return self.ShouldThrowOnError(); } void v8__ReturnValue__Set(v8::ReturnValue* self, @@ -2290,21 +2266,6 @@ const v8::Value* v8__PromiseRejectMessage__GetValue( return local_to_ptr(self.GetValue()); } -v8::Isolate* v8__PropertyCallbackInfo__GetIsolate( - const v8::PropertyCallbackInfo& self) { - return self.GetIsolate(); -} - -v8::Value* v8__PropertyCallbackInfo__GetReturnValue( - const v8::PropertyCallbackInfo& self) { - return make_pod(self.GetReturnValue()); -} - -const v8::Object* v8__PropertyCallbackInfo__This( - const v8::PropertyCallbackInfo& self) { - return local_to_ptr(self.This()); -} - const v8::Proxy* v8__Proxy__New(const v8::Context& context, const v8::Object& target, const v8::Object& handler) { diff --git a/src/function.rs b/src/function.rs index 8d159acc..b8cc7769 100644 --- a/src/function.rs +++ b/src/function.rs @@ -1,6 +1,7 @@ use std::convert::TryFrom; use std::marker::PhantomData; use std::ptr::null; +use std::ptr::NonNull; use crate::scope::CallbackScope; use crate::script_compiler::CachedData; @@ -9,6 +10,7 @@ use crate::support::MapFnTo; use crate::support::ToCFn; use crate::support::UnitType; use crate::support::{int, Opaque}; +use crate::undefined; use crate::Context; use crate::Function; use crate::HandleScope; @@ -52,34 +54,13 @@ extern "C" { script: *const Function, ) -> *mut CachedData<'static>; - fn v8__FunctionCallbackInfo__GetReturnValue( - info: *const FunctionCallbackInfo, - ) -> *mut Value; - fn v8__FunctionCallbackInfo__This( - this: *const FunctionCallbackInfo, - ) -> *const Object; - fn v8__FunctionCallbackInfo__Length(this: *const FunctionCallbackInfo) - -> int; - fn v8__FunctionCallbackInfo__GetArgument( - this: *const FunctionCallbackInfo, - i: int, - ) -> *const Value; - fn v8__FunctionCallbackInfo__Data( - this: *const FunctionCallbackInfo, - ) -> *const Value; - fn v8__FunctionCallbackInfo__NewTarget( - this: *const FunctionCallbackInfo, - ) -> *const Value; - fn v8__FunctionCallbackInfo__GetIsolate( - this: *const FunctionCallbackInfo, - ) -> *mut Isolate; + static v8__FunctionCallbackInfo__kArgsLength: int; - fn v8__PropertyCallbackInfo__GetReturnValue( + static v8__PropertyCallbackInfo__kArgsLength: int; + + fn v8__PropertyCallbackInfo__ShouldThrowOnError( this: *const PropertyCallbackInfo, - ) -> *mut Value; - fn v8__PropertyCallbackInfo__This( - this: *const PropertyCallbackInfo, - ) -> *const Object; + ) -> bool; fn v8__ReturnValue__Set(this: *mut ReturnValue, value: *const Value); fn v8__ReturnValue__Set__Bool(this: *mut ReturnValue, value: bool); @@ -126,7 +107,7 @@ pub enum SideEffectType { // is derived. #[repr(C)] #[derive(Debug)] -pub struct ReturnValue<'cb>(*mut Value, PhantomData<&'cb ()>); +pub struct ReturnValue<'cb>(NonNull, PhantomData<&'cb ()>); /// In V8 ReturnValue<> has a type parameter, but /// it turns out that in most of the APIs it's ReturnValue @@ -134,17 +115,15 @@ pub struct ReturnValue<'cb>(*mut Value, PhantomData<&'cb ()>); /// other types. So for now it's a simplified version. impl<'cb> ReturnValue<'cb> { #[inline(always)] - pub unsafe fn from_function_callback_info( - info: *const FunctionCallbackInfo, - ) -> Self { - let slot = v8__FunctionCallbackInfo__GetReturnValue(info); - Self(slot, PhantomData) + pub fn from_function_callback_info(info: &'cb FunctionCallbackInfo) -> Self { + let nn = info.get_return_value_non_null(); + Self(nn, PhantomData) } #[inline(always)] - fn from_property_callback_info(info: *const PropertyCallbackInfo) -> Self { - let slot = unsafe { v8__PropertyCallbackInfo__GetReturnValue(info) }; - Self(slot, PhantomData) + fn from_property_callback_info(info: &'cb PropertyCallbackInfo) -> Self { + let nn = info.get_return_value_non_null(); + Self(nn, PhantomData) } #[inline(always)] @@ -205,11 +184,109 @@ impl<'cb> ReturnValue<'cb> { pub struct FunctionCallbackInfo { // The layout of this struct must match that of `class FunctionCallbackInfo` // as defined in v8.h. - implicit_args: *mut Opaque, - values: *const Value, + implicit_args: *mut *const Opaque, + values: *mut *const Opaque, length: int, } +// These constants must match those defined on `class FunctionCallbackInfo` in +// v8-function-callback.h. +#[allow(dead_code, non_upper_case_globals)] +impl FunctionCallbackInfo { + const kHolderIndex: i32 = 0; + const kIsolateIndex: i32 = 1; + const kReturnValueDefaultValueIndex: i32 = 2; + const kReturnValueIndex: i32 = 3; + const kDataIndex: i32 = 4; + const kNewTargetIndex: i32 = 5; + const kArgsLength: i32 = 6; +} + +impl FunctionCallbackInfo { + #[inline(always)] + pub(crate) fn get_isolate_ptr(&self) -> *mut Isolate { + let arg_nn = + self.get_implicit_arg_non_null::<*mut Isolate>(Self::kIsolateIndex); + *unsafe { arg_nn.as_ref() } + } + + #[inline(always)] + pub(crate) fn get_return_value_non_null(&self) -> NonNull { + self.get_implicit_arg_non_null::(Self::kReturnValueIndex) + } + + #[inline(always)] + pub(crate) fn holder(&self) -> Local { + unsafe { self.get_implicit_arg_local(Self::kHolderIndex) } + } + + #[inline(always)] + pub(crate) fn new_target(&self) -> Local { + unsafe { self.get_implicit_arg_local(Self::kNewTargetIndex) } + } + + #[inline(always)] + pub(crate) fn this(&self) -> Local { + unsafe { self.get_arg_local(-1) } + } + + #[inline(always)] + pub(crate) fn data(&self) -> Local { + unsafe { self.get_implicit_arg_local(Self::kDataIndex) } + } + + #[inline(always)] + pub(crate) fn length(&self) -> i32 { + self.length + } + + #[inline(always)] + pub(crate) fn get(&self, index: int) -> Local { + if index >= 0 && index < self.length { + unsafe { self.get_arg_local(index) } + } else { + let isolate = unsafe { &mut *self.get_isolate_ptr() }; + undefined(isolate).into() + } + } + + #[inline(always)] + fn get_implicit_arg_non_null(&self, index: i32) -> NonNull { + // In debug builds, check that `FunctionCallbackInfo::kArgsLength` matches + // the C++ definition. Unfortunately we can't check the other constants + // because they are declared protected in the C++ header. + debug_assert_eq!( + unsafe { v8__FunctionCallbackInfo__kArgsLength }, + Self::kArgsLength + ); + // Assert that `index` is in bounds. + assert!(index >= 0); + assert!(index < Self::kArgsLength); + // Compute the address of the implicit argument and cast to `NonNull`. + let ptr = unsafe { self.implicit_args.offset(index as isize) as *mut T }; + debug_assert!(!ptr.is_null()); + unsafe { NonNull::new_unchecked(ptr) } + } + + // SAFETY: caller must guarantee that the implicit argument at `index` + // contains a valid V8 handle. + #[inline(always)] + unsafe fn get_implicit_arg_local(&self, index: i32) -> Local { + let nn = self.get_implicit_arg_non_null::(index); + Local::from_non_null(nn) + } + + // SAFETY: caller must guarantee that the `index` value lies between -1 and + // self.length. + #[inline(always)] + unsafe fn get_arg_local(&self, index: i32) -> Local { + let ptr = self.values.offset(index as _) as *mut T; + debug_assert!(!ptr.is_null()); + let nn = NonNull::new_unchecked(ptr); + Local::from_non_null(nn) + } +} + /// The information passed to a property callback about the context /// of the property access. #[repr(C)] @@ -217,89 +294,166 @@ pub struct FunctionCallbackInfo { pub struct PropertyCallbackInfo { // The layout of this struct must match that of `class PropertyCallbackInfo` // as defined in v8.h. - args: *mut Opaque, + args: *mut *const Opaque, } -#[derive(Debug)] -pub struct FunctionCallbackArguments<'s> { - info: *const FunctionCallbackInfo, - phantom: PhantomData<&'s ()>, +// These constants must match those defined on `class PropertyCallbackInfo` in +// v8-function-callback.h. +#[allow(dead_code, non_upper_case_globals)] +impl PropertyCallbackInfo { + const kShouldThrowOnErrorIndex: i32 = 0; + const kHolderIndex: i32 = 1; + const kIsolateIndex: i32 = 2; + const kReturnValueDefaultValueIndex: i32 = 3; + const kReturnValueIndex: i32 = 4; + const kDataIndex: i32 = 5; + const kThisIndex: i32 = 6; + const kArgsLength: i32 = 7; } -impl<'s> FunctionCallbackArguments<'s> { +impl PropertyCallbackInfo { #[inline(always)] - pub unsafe fn from_function_callback_info( - info: *const FunctionCallbackInfo, - ) -> Self { - Self { - info, - phantom: PhantomData, - } + pub(crate) fn get_isolate_ptr(&self) -> *mut Isolate { + let arg_nn = self.get_arg_non_null::<*mut Isolate>(Self::kIsolateIndex); + *unsafe { arg_nn.as_ref() } } + #[inline(always)] + pub(crate) fn get_return_value_non_null(&self) -> NonNull { + self.get_arg_non_null::(Self::kReturnValueIndex) + } + + #[inline(always)] + pub(crate) fn holder(&self) -> Local { + unsafe { self.get_arg_local(Self::kHolderIndex) } + } + + #[inline(always)] + pub(crate) fn this(&self) -> Local { + unsafe { self.get_arg_local(Self::kThisIndex) } + } + + #[inline(always)] + pub(crate) fn data(&self) -> Local { + unsafe { self.get_arg_local(Self::kDataIndex) } + } + + #[inline(always)] + pub(crate) fn should_throw_on_error(&self) -> bool { + unsafe { v8__PropertyCallbackInfo__ShouldThrowOnError(self) } + } + + #[inline(always)] + fn get_arg_non_null(&self, index: i32) -> NonNull { + // In debug builds, verify that `PropertyCallbackInfo::kArgsLength` matches + // the C++ definition. Unfortunately we can't check the other constants + // because they are declared protected in the C++ header. + debug_assert_eq!( + unsafe { v8__PropertyCallbackInfo__kArgsLength }, + Self::kArgsLength + ); + // Assert that `index` is in bounds. + assert!(index >= 0); + assert!(index < Self::kArgsLength); + // Compute the address of the implicit argument and cast to `NonNull`. + let ptr = unsafe { self.args.offset(index as isize) as *mut T }; + debug_assert!(!ptr.is_null()); + unsafe { NonNull::new_unchecked(ptr) } + } + + // SAFETY: caller must guarantee that the implicit argument at `index` + // contains a valid V8 handle. + #[inline(always)] + unsafe fn get_arg_local(&self, index: i32) -> Local { + let nn = self.get_arg_non_null::(index); + Local::from_non_null(nn) + } +} + +#[derive(Debug)] +pub struct FunctionCallbackArguments<'s>(&'s FunctionCallbackInfo); + +impl<'s> FunctionCallbackArguments<'s> { + #[inline(always)] + pub fn from_function_callback_info(info: &'s FunctionCallbackInfo) -> Self { + Self(info) + } + + /// SAFETY: caller must guarantee that no other references to the isolate are + /// accessible. Specifically, if an open CallbackScope or HandleScope exists + /// in the current function, `FunctionCallbackArguments::get_isolate()` should + /// not be called. #[inline(always)] pub unsafe fn get_isolate(&mut self) -> &mut Isolate { - &mut *v8__FunctionCallbackInfo__GetIsolate(self.info) + &mut *self.0.get_isolate_ptr() + } + + /// If the callback was created without a Signature, this is the same value as + /// `this()`. If there is a signature, and the signature didn't match `this()` + /// but one of its hidden prototypes, this will be the respective hidden + /// prototype. + /// + /// Note that this is not the prototype of `this()` on which the accessor + /// referencing this callback was found (which in V8 internally is often + /// referred to as holder [sic]). + #[inline(always)] + pub fn holder(&self) -> Local<'s, Object> { + self.0.holder() + } + + /// For construct calls, this returns the "new.target" value. + #[inline(always)] + pub fn new_target(&self) -> Local<'s, Value> { + self.0.new_target() } /// Returns the receiver. This corresponds to the "this" value. #[inline(always)] pub fn this(&self) -> Local<'s, Object> { - unsafe { - Local::from_raw(v8__FunctionCallbackInfo__This(self.info)).unwrap() - } + self.0.this() } /// Returns the data argument specified when creating the callback. #[inline(always)] - pub fn data(&self) -> Option> { - unsafe { Local::from_raw(v8__FunctionCallbackInfo__Data(self.info)) } + pub fn data(&self) -> Local<'s, Value> { + self.0.data() } /// The number of available arguments. #[inline(always)] pub fn length(&self) -> int { - unsafe { - let length = (*self.info).length; - debug_assert_eq!(length, v8__FunctionCallbackInfo__Length(self.info)); - length - } + self.0.length() } /// Accessor for the available arguments. Returns `undefined` if the index is /// out of bounds. #[inline(always)] pub fn get(&self, i: int) -> Local<'s, Value> { - unsafe { - Local::from_raw(v8__FunctionCallbackInfo__GetArgument(self.info, i)) - .unwrap() - } - } - - /// For construct calls, this returns the "new.target" value. - #[inline(always)] - pub fn new_target(&self) -> Local<'s, Value> { - unsafe { - Local::from_raw(v8__FunctionCallbackInfo__NewTarget(self.info)).unwrap() - } + self.0.get(i) } } #[derive(Debug)] -pub struct PropertyCallbackArguments<'s> { - info: *const PropertyCallbackInfo, - phantom: PhantomData<&'s ()>, -} +pub struct PropertyCallbackArguments<'s>(&'s PropertyCallbackInfo); impl<'s> PropertyCallbackArguments<'s> { #[inline(always)] pub(crate) fn from_property_callback_info( - info: *const PropertyCallbackInfo, + info: &'s PropertyCallbackInfo, ) -> Self { - Self { - info, - phantom: PhantomData, - } + Self(info) + } + + /// Returns he object in the prototype chain of the receiver that has the + /// interceptor. Suppose you have `x` and its prototype is `y`, and `y` has an + /// interceptor. Then `info.this()` is `x` and `info.holder()` is `y`. The + /// `holder()` could be a hidden object (the global object, rather than the + /// global proxy). + /// + /// For security reasons, do not pass the object back into the runtime. + #[inline(always)] + pub fn holder(&self) -> Local<'s, Object> { + self.0.holder() } /// Returns the receiver. In many cases, this is the object on which the @@ -343,9 +497,25 @@ impl<'s> PropertyCallbackArguments<'s> { /// ``` #[inline(always)] pub fn this(&self) -> Local<'s, Object> { - unsafe { - Local::from_raw(v8__PropertyCallbackInfo__This(self.info)).unwrap() - } + self.0.this() + } + + /// Returns the data set in the configuration, i.e., in + /// `NamedPropertyHandlerConfiguration` or + /// `IndexedPropertyHandlerConfiguration.` + #[inline(always)] + pub fn data(&self) -> Local<'s, Value> { + self.0.data() + } + + /// Returns `true` if the intercepted function should throw if an error + /// occurs. Usually, `true` corresponds to `'use strict'`. + /// + /// Always `false` when intercepting `Reflect.set()` independent of the + /// language mode. + #[inline(always)] + pub fn should_throw_on_error(&self) -> bool { + self.0.should_throw_on_error() } } @@ -358,10 +528,10 @@ where { fn mapping() -> Self { let f = |info: *const FunctionCallbackInfo| { - let scope = &mut unsafe { CallbackScope::new(&*info) }; - let args = - unsafe { FunctionCallbackArguments::from_function_callback_info(info) }; - let rv = unsafe { ReturnValue::from_function_callback_info(info) }; + let info = unsafe { &*info }; + let scope = &mut unsafe { CallbackScope::new(info) }; + let args = FunctionCallbackArguments::from_function_callback_info(info); + let rv = ReturnValue::from_function_callback_info(info); (F::get())(scope, args, rv); }; f.to_c_fn() @@ -380,7 +550,8 @@ where { fn mapping() -> Self { let f = |key: Local, info: *const PropertyCallbackInfo| { - let scope = &mut unsafe { CallbackScope::new(&*info) }; + let info = unsafe { &*info }; + let scope = &mut unsafe { CallbackScope::new(info) }; let args = PropertyCallbackArguments::from_property_callback_info(info); let rv = ReturnValue::from_property_callback_info(info); (F::get())(scope, key, args, rv); @@ -401,7 +572,8 @@ where let f = |key: Local, value: Local, info: *const PropertyCallbackInfo| { - let scope = &mut unsafe { CallbackScope::new(&*info) }; + let info = unsafe { &*info }; + let scope = &mut unsafe { CallbackScope::new(info) }; let args = PropertyCallbackArguments::from_property_callback_info(info); (F::get())(scope, key, value, args); }; @@ -419,8 +591,8 @@ where { fn mapping() -> Self { let f = |info: *const PropertyCallbackInfo| { - let info = info as *const PropertyCallbackInfo; - let scope = &mut unsafe { CallbackScope::new(&*info) }; + let info = unsafe { &*info }; + let scope = &mut unsafe { CallbackScope::new(info) }; let args = PropertyCallbackArguments::from_property_callback_info(info); let rv = ReturnValue::from_property_callback_info(info); (F::get())(scope, args, rv); @@ -441,7 +613,8 @@ where { fn mapping() -> Self { let f = |index: u32, info: *const PropertyCallbackInfo| { - let scope = &mut unsafe { CallbackScope::new(&*info) }; + let info = unsafe { &*info }; + let scope = &mut unsafe { CallbackScope::new(info) }; let args = PropertyCallbackArguments::from_property_callback_info(info); let rv = ReturnValue::from_property_callback_info(info); (F::get())(scope, index, args, rv); @@ -461,7 +634,8 @@ where fn mapping() -> Self { let f = |index: u32, value: Local, info: *const PropertyCallbackInfo| { - let scope = &mut unsafe { CallbackScope::new(&*info) }; + let info = unsafe { &*info }; + let scope = &mut unsafe { CallbackScope::new(info) }; let args = PropertyCallbackArguments::from_property_callback_info(info); (F::get())(scope, index, value, args); }; diff --git a/src/isolate.rs b/src/isolate.rs index 0f1dd66c..cece521c 100644 --- a/src/isolate.rs +++ b/src/isolate.rs @@ -7,6 +7,7 @@ use crate::isolate_create_params::CreateParams; use crate::promise::PromiseRejectMessage; use crate::scope::data::ScopeData; use crate::snapshot::SnapshotCreator; +use crate::support::int; use crate::support::Allocated; use crate::support::MapFnFrom; use crate::support::MapFnTo; @@ -340,7 +341,7 @@ pub type PrepareStackTraceCallback<'s> = ) -> PrepareStackTraceCallbackRet; extern "C" { - static v8__internal__Internals__kIsolateEmbedderDataOffset: usize; + static v8__internal__Internals__kIsolateEmbedderDataOffset: int; fn v8__Isolate__New(params: *const raw::CreateParams) -> *mut Isolate; fn v8__Isolate__Dispose(this: *mut Isolate); @@ -510,7 +511,7 @@ impl Isolate { Self::EMBEDDER_DATA_SLOT_COUNT ); assert_eq!( - unsafe { v8__internal__Internals__kIsolateEmbedderDataOffset }, + unsafe { v8__internal__Internals__kIsolateEmbedderDataOffset } as usize, Self::EMBEDDER_DATA_OFFSET ); } diff --git a/src/scope.rs b/src/scope.rs index d37106fd..85710457 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -903,13 +903,13 @@ mod getter { impl<'s> GetIsolate<'s> for &'s FunctionCallbackInfo { unsafe fn get_isolate_mut(self) -> &'s mut Isolate { - &mut *raw::v8__FunctionCallbackInfo__GetIsolate(self) + &mut *self.get_isolate_ptr() } } impl<'s> GetIsolate<'s> for &'s PropertyCallbackInfo { unsafe fn get_isolate_mut(self) -> &'s mut Isolate { - &mut *raw::v8__PropertyCallbackInfo__GetIsolate(self) + &mut *self.get_isolate_ptr() } } @@ -1733,12 +1733,6 @@ mod raw { pub(super) fn v8__Message__GetIsolate(this: *const Message) -> *mut Isolate; pub(super) fn v8__Object__GetIsolate(this: *const Object) -> *mut Isolate; - pub(super) fn v8__FunctionCallbackInfo__GetIsolate( - this: *const FunctionCallbackInfo, - ) -> *mut Isolate; - pub(super) fn v8__PropertyCallbackInfo__GetIsolate( - this: *const PropertyCallbackInfo, - ) -> *mut Isolate; } } diff --git a/src/wasm.rs b/src/wasm.rs index cc9753a9..0c1191ba 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -181,15 +181,14 @@ where where F: UnitType + Fn(&mut HandleScope, Local, WasmStreaming), { - let scope = &mut unsafe { CallbackScope::new(&*info) }; - let args = - unsafe { FunctionCallbackArguments::from_function_callback_info(info) }; - let data = args.data().unwrap(); // Always present. - let data = &*data as *const Value; + let info = unsafe { &*info }; + let scope = &mut unsafe { CallbackScope::new(info) }; + let args = FunctionCallbackArguments::from_function_callback_info(info); + let data = args.data(); let zero = null_mut(); let mut that = WasmStreamingSharedPtr([zero, zero]); unsafe { - v8__WasmStreaming__Unpack(scope.get_isolate_ptr(), data, &mut that) + v8__WasmStreaming__Unpack(scope.get_isolate_ptr(), &*data, &mut that) }; let source = args.get(0); (F::get())(scope, source, WasmStreaming(that)); diff --git a/tests/test_api.rs b/tests/test_api.rs index a2b840ad..202064df 100644 --- a/tests/test_api.rs +++ b/tests/test_api.rs @@ -1634,6 +1634,10 @@ fn instance_template_with_internal_field() { mut retval: v8::ReturnValue, ) { let this = args.this(); + + assert_eq!(args.holder(), this); + assert!(args.data().is_undefined()); + assert!(this.set_internal_field(0, v8::Integer::new(scope, 42).into())); retval.set(this.into()) } @@ -1671,6 +1675,10 @@ fn object_template_set_accessor() { mut rv: v8::ReturnValue| { let this = args.this(); + assert_eq!(args.holder(), this); + assert!(args.data().is_undefined()); + assert!(!args.should_throw_on_error()); + let expected_key = v8::String::new(scope, "key").unwrap(); assert!(key.strict_equals(expected_key.into())); @@ -1683,6 +1691,10 @@ fn object_template_set_accessor() { args: v8::PropertyCallbackArguments| { let this = args.this(); + assert_eq!(args.holder(), this); + assert!(args.data().is_undefined()); + assert!(!args.should_throw_on_error()); + let expected_key = v8::String::new(scope, "key").unwrap(); assert!(key.strict_equals(expected_key.into())); @@ -1737,6 +1749,10 @@ fn object_template_set_accessor() { _: v8::ReturnValue, ) { let this = args.this(); + + assert_eq!(args.holder(), this); + assert!(args.data().is_undefined()); + let ret = v8::Integer::new(scope, 69); assert!(this.set_internal_field(0, ret.into())); } @@ -1794,6 +1810,10 @@ fn object_template_set_named_property_handler() { mut rv: v8::ReturnValue| { let this = args.this(); + assert_eq!(args.holder(), this); + assert!(args.data().is_undefined()); + assert!(!args.should_throw_on_error()); + let expected_key = v8::String::new(scope, "key").unwrap(); assert!(key.strict_equals(expected_key.into())); @@ -1806,6 +1826,10 @@ fn object_template_set_named_property_handler() { args: v8::PropertyCallbackArguments| { let this = args.this(); + assert_eq!(args.holder(), this); + assert!(args.data().is_undefined()); + assert!(!args.should_throw_on_error()); + let expected_key = v8::String::new(scope, "key").unwrap(); assert!(key.strict_equals(expected_key.into())); @@ -1819,6 +1843,10 @@ fn object_template_set_named_property_handler() { mut rv: v8::ReturnValue| { let this = args.this(); + assert_eq!(args.holder(), this); + assert!(args.data().is_undefined()); + assert!(!args.should_throw_on_error()); + let expected_key = v8::String::new(scope, "key").unwrap(); assert!(key.strict_equals(expected_key.into())); //PropertyAttribute::READ_ONLY @@ -1843,7 +1871,12 @@ fn object_template_set_named_property_handler() { args: v8::PropertyCallbackArguments, mut rv: v8::ReturnValue| { let this = args.this(); - //Validate is the current object + + assert_eq!(args.holder(), this); + assert!(args.data().is_undefined()); + assert!(!args.should_throw_on_error()); + + // Validate is the current object. let expected_value = v8::Integer::new(scope, 42); assert!(this .get_internal_field(scope, 0) @@ -1962,6 +1995,11 @@ fn object_template_set_indexed_property_handler() { args: v8::PropertyCallbackArguments, mut rv: v8::ReturnValue| { let this = args.this(); + + assert_eq!(args.holder(), this); + assert!(args.data().is_undefined()); + assert!(!args.should_throw_on_error()); + let expected_index = 37; assert!(index.eq(&expected_index)); rv.set(this.get_internal_field(scope, 0).unwrap()); @@ -1973,6 +2011,10 @@ fn object_template_set_indexed_property_handler() { args: v8::PropertyCallbackArguments| { let this = args.this(); + assert_eq!(args.holder(), this); + assert!(args.data().is_undefined()); + assert!(!args.should_throw_on_error()); + assert_eq!(index, 37); assert!(value.is_int32()); @@ -1992,7 +2034,12 @@ fn object_template_set_indexed_property_handler() { args: v8::PropertyCallbackArguments, mut rv: v8::ReturnValue| { let this = args.this(); - //Validate is the current object + + assert_eq!(args.holder(), this); + assert!(args.data().is_undefined()); + assert!(!args.should_throw_on_error()); + + // Validate is the current object. let expected_value = v8::Integer::new(scope, 42); assert!(this .get_internal_field(scope, 0) @@ -2295,6 +2342,10 @@ fn object_set_accessor() { mut rv: v8::ReturnValue| { let this = args.this(); + assert_eq!(args.holder(), this); + assert!(args.data().is_undefined()); + assert!(!args.should_throw_on_error()); + let expected_key = v8::String::new(scope, "getter_key").unwrap(); assert!(key.strict_equals(expected_key.into())); @@ -2349,6 +2400,10 @@ fn object_set_accessor_with_setter() { mut rv: v8::ReturnValue| { let this = args.this(); + assert_eq!(args.holder(), this); + assert!(args.data().is_undefined()); + assert!(!args.should_throw_on_error()); + let expected_key = v8::String::new(scope, "getter_setter_key").unwrap(); assert!(key.strict_equals(expected_key.into())); @@ -2369,8 +2424,13 @@ fn object_set_accessor_with_setter() { value: v8::Local, args: v8::PropertyCallbackArguments| { println!("setter called"); + let this = args.this(); + assert_eq!(args.holder(), this); + assert!(args.data().is_undefined()); + assert!(!args.should_throw_on_error()); + let expected_key = v8::String::new(scope, "getter_setter_key").unwrap(); assert!(key.strict_equals(expected_key.into())); @@ -2507,7 +2567,7 @@ fn fn_callback_external( mut rv: v8::ReturnValue, ) { assert_eq!(args.length(), 0); - let data = args.data().unwrap(); + let data = args.data(); let external = v8::Local::::try_from(data).unwrap(); let data = unsafe { std::slice::from_raw_parts(external.value() as *mut u8, 5) }; @@ -2578,8 +2638,6 @@ fn data_is_true_callback( _rv: v8::ReturnValue, ) { let data = args.data(); - assert!(data.is_some()); - let data = data.unwrap(); assert!(data.is_true()); } @@ -2610,15 +2668,14 @@ fn function_builder_raw() { let recv: v8::Local = global.into(); extern "C" fn callback(info: *const v8::FunctionCallbackInfo) { - let scope = unsafe { &mut v8::CallbackScope::new(&*info) }; - let args = unsafe { - v8::FunctionCallbackArguments::from_function_callback_info(info) - }; + let info = unsafe { &*info }; + let scope = unsafe { &mut v8::CallbackScope::new(info) }; + let args = + v8::FunctionCallbackArguments::from_function_callback_info(info); assert!(args.length() == 1); assert!(args.get(0).is_string()); - let mut rv = - unsafe { v8::ReturnValue::from_function_callback_info(info) }; + let mut rv = v8::ReturnValue::from_function_callback_info(info); rv.set( v8::String::new(scope, "Hello from function!") .unwrap()