mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-11-21 15:04:33 -05:00
perf: optimize FunctionCallbackInfo and PropertyCallbackInfo methods (#1104)
This commit is contained in:
parent
c89ae9453b
commit
d85f78527f
7 changed files with 368 additions and 183 deletions
|
@ -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();
|
||||
|
|
|
@ -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<v8::Value>& self) {
|
||||
return self.GetIsolate();
|
||||
}
|
||||
const extern int v8__FunctionCallbackInfo__kArgsLength =
|
||||
v8::FunctionCallbackInfo<v8::Value>::kArgsLength;
|
||||
|
||||
v8::Value* v8__FunctionCallbackInfo__GetReturnValue(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& self) {
|
||||
return make_pod<v8::Value*>(self.GetReturnValue());
|
||||
}
|
||||
const extern int v8__PropertyCallbackInfo__kArgsLength =
|
||||
v8::PropertyCallbackInfo<v8::Value>::kArgsLength;
|
||||
|
||||
const v8::Object* v8__FunctionCallbackInfo__This(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& self) {
|
||||
return local_to_ptr(self.This());
|
||||
}
|
||||
|
||||
int v8__FunctionCallbackInfo__Length(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& self) {
|
||||
return self.Length();
|
||||
}
|
||||
|
||||
const v8::Value* v8__FunctionCallbackInfo__GetArgument(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& self, int i) {
|
||||
return local_to_ptr(self[i]);
|
||||
}
|
||||
|
||||
const v8::Value* v8__FunctionCallbackInfo__Data(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& self) {
|
||||
return local_to_ptr(self.Data());
|
||||
}
|
||||
|
||||
const v8::Value* v8__FunctionCallbackInfo__NewTarget(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& self) {
|
||||
return local_to_ptr(self.NewTarget());
|
||||
bool v8__PropertyCallbackInfo__ShouldThrowOnError(
|
||||
const v8::PropertyCallbackInfo<v8::Value>& self) {
|
||||
return self.ShouldThrowOnError();
|
||||
}
|
||||
|
||||
void v8__ReturnValue__Set(v8::ReturnValue<v8::Value>* 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<v8::Value>& self) {
|
||||
return self.GetIsolate();
|
||||
}
|
||||
|
||||
v8::Value* v8__PropertyCallbackInfo__GetReturnValue(
|
||||
const v8::PropertyCallbackInfo<v8::Value>& self) {
|
||||
return make_pod<v8::Value*>(self.GetReturnValue());
|
||||
}
|
||||
|
||||
const v8::Object* v8__PropertyCallbackInfo__This(
|
||||
const v8::PropertyCallbackInfo<v8::Value>& 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) {
|
||||
|
|
364
src/function.rs
364
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<Value>, PhantomData<&'cb ()>);
|
||||
|
||||
/// In V8 ReturnValue<> has a type parameter, but
|
||||
/// it turns out that in most of the APIs it's ReturnValue<Value>
|
||||
|
@ -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<Value> {
|
||||
self.get_implicit_arg_non_null::<Value>(Self::kReturnValueIndex)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn holder(&self) -> Local<Object> {
|
||||
unsafe { self.get_implicit_arg_local(Self::kHolderIndex) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn new_target(&self) -> Local<Value> {
|
||||
unsafe { self.get_implicit_arg_local(Self::kNewTargetIndex) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn this(&self) -> Local<Object> {
|
||||
unsafe { self.get_arg_local(-1) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn data(&self) -> Local<Value> {
|
||||
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<Value> {
|
||||
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<T>(&self, index: i32) -> NonNull<T> {
|
||||
// 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<T>`.
|
||||
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<T>(&self, index: i32) -> Local<T> {
|
||||
let nn = self.get_implicit_arg_non_null::<T>(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<T>(&self, index: i32) -> Local<T> {
|
||||
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<Value> {
|
||||
self.get_arg_non_null::<Value>(Self::kReturnValueIndex)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn holder(&self) -> Local<Object> {
|
||||
unsafe { self.get_arg_local(Self::kHolderIndex) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn this(&self) -> Local<Object> {
|
||||
unsafe { self.get_arg_local(Self::kThisIndex) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn data(&self) -> Local<Value> {
|
||||
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<T>(&self, index: i32) -> NonNull<T> {
|
||||
// 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<T>`.
|
||||
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<T>(&self, index: i32) -> Local<T> {
|
||||
let nn = self.get_arg_non_null::<T>(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<Local<'s, Value>> {
|
||||
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<Name>, 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<Name>,
|
||||
value: Local<Value>,
|
||||
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<Value>, 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);
|
||||
};
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
10
src/scope.rs
10
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
11
src/wasm.rs
11
src/wasm.rs
|
@ -181,15 +181,14 @@ where
|
|||
where
|
||||
F: UnitType + Fn(&mut HandleScope, Local<Value>, 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));
|
||||
|
|
|
@ -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<v8::Value>,
|
||||
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::<v8::External>::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<v8::Value> = 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()
|
||||
|
|
Loading…
Reference in a new issue