Skip to content

Commit

Permalink
feat: Add ObjectTemplate NamedProperty and IndexedProperty handlers (d…
Browse files Browse the repository at this point in the history
  • Loading branch information
bakjos authored Oct 5, 2022
1 parent 760c48a commit cd51ea1
Show file tree
Hide file tree
Showing 4 changed files with 635 additions and 0 deletions.
27 changes: 27 additions & 0 deletions src/binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1135,6 +1135,33 @@ void v8__ObjectTemplate__SetAccessorWithSetter(
ptr_to_local(&self)->SetAccessor(ptr_to_local(&key), getter, setter);
}

void v8__ObjectTemplate__SetNamedPropertyHandler(
const v8::ObjectTemplate& self,
v8::GenericNamedPropertyGetterCallback getter,
v8::GenericNamedPropertySetterCallback setter,
v8::GenericNamedPropertyQueryCallback query,
v8::GenericNamedPropertyDeleterCallback deleter,
v8::GenericNamedPropertyEnumeratorCallback enumerator,
v8::GenericNamedPropertyDescriptorCallback descriptor,
const v8::Value* data_or_null) {
ptr_to_local(&self)->SetHandler(v8::NamedPropertyHandlerConfiguration(
getter, setter, query, deleter, enumerator, nullptr, descriptor,
ptr_to_local(data_or_null)));
}

void v8__ObjectTemplate__SetIndexedPropertyHandler(
const v8::ObjectTemplate& self, v8::IndexedPropertyGetterCallback getter,
v8::IndexedPropertySetterCallback setter,
v8::IndexedPropertyQueryCallback query,
v8::IndexedPropertyDeleterCallback deleter,
v8::IndexedPropertyEnumeratorCallback enumerator,
v8::IndexedPropertyDescriptorCallback descriptor,
const v8::Value* data_or_null) {
ptr_to_local(&self)->SetHandler(v8::IndexedPropertyHandlerConfiguration(
getter, setter, query, deleter, enumerator, nullptr, descriptor,
ptr_to_local(data_or_null)));
}

void v8__ObjectTemplate__SetAccessorProperty(const v8::ObjectTemplate& self,
const v8::Name& key,
v8::FunctionTemplate& getter,
Expand Down
60 changes: 60 additions & 0 deletions src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,66 @@ where
}
}

//Should return an Array in Return Value
pub type PropertyEnumeratorCallback<'s> =
extern "C" fn(*const PropertyCallbackInfo);

impl<F> MapFnFrom<F> for PropertyEnumeratorCallback<'_>
where
F: UnitType + Fn(&mut HandleScope, PropertyCallbackArguments, ReturnValue),
{
fn mapping() -> Self {
let f = |info: *const PropertyCallbackInfo| {
let info = info as *const PropertyCallbackInfo;
let scope = &mut unsafe { CallbackScope::new(&*info) };
let args = PropertyCallbackArguments::from_property_callback_info(info);
let rv = ReturnValue::from_property_callback_info(info);
(F::get())(scope, args, rv);
};
f.to_c_fn()
}
}

/// IndexedPropertyGetterCallback is used as callback functions when registering a named handler
/// particular property. See Object and ObjectTemplate's method SetHandler.
pub type IndexedPropertyGetterCallback<'s> =
extern "C" fn(u32, *const PropertyCallbackInfo);

impl<F> MapFnFrom<F> for IndexedPropertyGetterCallback<'_>
where
F: UnitType
+ Fn(&mut HandleScope, u32, PropertyCallbackArguments, ReturnValue),
{
fn mapping() -> Self {
let f = |index: u32, info: *const PropertyCallbackInfo| {
let scope = &mut unsafe { CallbackScope::new(&*info) };
let args = PropertyCallbackArguments::from_property_callback_info(info);
let rv = ReturnValue::from_property_callback_info(info);
(F::get())(scope, index, args, rv);
};
f.to_c_fn()
}
}

pub type IndexedPropertySetterCallback<'s> =
extern "C" fn(u32, Local<'s, Value>, *const PropertyCallbackInfo);

impl<F> MapFnFrom<F> for IndexedPropertySetterCallback<'_>
where
F: UnitType
+ Fn(&mut HandleScope, u32, Local<Value>, PropertyCallbackArguments),
{
fn mapping() -> Self {
let f =
|index: u32, value: Local<Value>, info: *const PropertyCallbackInfo| {
let scope = &mut unsafe { CallbackScope::new(&*info) };
let args = PropertyCallbackArguments::from_property_callback_info(info);
(F::get())(scope, index, value, args);
};
f.to_c_fn()
}
}

/// A builder to construct the properties of a Function or FunctionTemplate.
pub struct FunctionBuilder<'s, T> {
pub(crate) callback: FunctionCallback,
Expand Down
249 changes: 249 additions & 0 deletions src/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ use crate::Function;
use crate::FunctionBuilder;
use crate::FunctionCallback;
use crate::HandleScope;
use crate::IndexedPropertyGetterCallback;
use crate::IndexedPropertySetterCallback;
use crate::Local;
use crate::Object;
use crate::PropertyAttribute;
use crate::PropertyEnumeratorCallback;
use crate::SideEffectType;
use crate::Signature;
use crate::String;
Expand Down Expand Up @@ -107,9 +110,215 @@ extern "C" {
setter: *const FunctionTemplate,
attr: PropertyAttribute,
);

fn v8__ObjectTemplate__SetNamedPropertyHandler(
this: *const ObjectTemplate,
getter: Option<AccessorNameGetterCallback>,
setter: Option<AccessorNameSetterCallback>,
query: Option<AccessorNameGetterCallback>,
deleter: Option<AccessorNameGetterCallback>,
enumerator: Option<PropertyEnumeratorCallback>,
descriptor: Option<AccessorNameGetterCallback>,
data_or_null: *const Value,
);

fn v8__ObjectTemplate__SetIndexedPropertyHandler(
this: *const ObjectTemplate,
getter: Option<IndexedPropertyGetterCallback>,
setter: Option<IndexedPropertySetterCallback>,
query: Option<IndexedPropertyGetterCallback>,
deleter: Option<IndexedPropertyGetterCallback>,
enumerator: Option<PropertyEnumeratorCallback>,
descriptor: Option<IndexedPropertyGetterCallback>,
data_or_null: *const Value,
);

fn v8__ObjectTemplate__SetImmutableProto(this: *const ObjectTemplate);
}

#[derive(Default)]
pub struct NamedPropertyHandlerConfiguration<'s> {
pub(crate) getter: Option<AccessorNameGetterCallback<'s>>,
pub(crate) setter: Option<AccessorNameSetterCallback<'s>>,
pub(crate) query: Option<AccessorNameGetterCallback<'s>>,
pub(crate) deleter: Option<AccessorNameGetterCallback<'s>>,
pub(crate) enumerator: Option<PropertyEnumeratorCallback<'s>>,
pub(crate) descriptor: Option<AccessorNameGetterCallback<'s>>,
pub(crate) data: Option<Local<'s, Value>>,
}

impl<'s> NamedPropertyHandlerConfiguration<'s> {
pub fn new() -> Self {
Self {
getter: None,
setter: None,
query: None,
deleter: None,
enumerator: None,
descriptor: None,
data: None,
}
}

pub fn is_some(&self) -> bool {
self.getter.is_some()
|| self.setter.is_some()
|| self.query.is_some()
|| self.deleter.is_some()
|| self.enumerator.is_some()
|| self.descriptor.is_some()
}

pub fn getter(
mut self,
getter: impl MapFnTo<AccessorNameGetterCallback<'s>>,
) -> Self {
self.getter = Some(getter.map_fn_to());
self
}

pub fn setter(
mut self,
setter: impl MapFnTo<AccessorNameSetterCallback<'s>>,
) -> Self {
self.setter = Some(setter.map_fn_to());
self
}

// Intercepts all requests that query the attributes of the property,
// e.g., getOwnPropertyDescriptor(), propertyIsEnumerable(), and defineProperty()
// Use ReturnValue.set_int32(value) to set the property attributes. The value is an interger encoding a v8::PropertyAttribute.
pub fn query(
mut self,
query: impl MapFnTo<AccessorNameGetterCallback<'s>>,
) -> Self {
self.query = Some(query.map_fn_to());
self
}
// Interceptor for delete requests on an object.
// Use ReturnValue.set_bool to indicate whether the request was intercepted or not. If the deleter successfully intercepts the request,
// i.e., if the request should not be further executed, call info.GetReturnValue().Set(value) with a boolean value.
// The value is used as the return value of delete.
pub fn deleter(
mut self,
deleter: impl MapFnTo<AccessorNameGetterCallback<'s>>,
) -> Self {
self.deleter = Some(deleter.map_fn_to());
self
}
// Returns an array containing the names of the properties the named property getter intercepts.
// use ReturnValue.set with a v8::Array
pub fn enumerator(
mut self,
enumerator: impl MapFnTo<PropertyEnumeratorCallback<'s>>,
) -> Self {
self.enumerator = Some(enumerator.map_fn_to());
self
}

pub fn descriptor(
mut self,
descriptor: impl MapFnTo<AccessorNameGetterCallback<'s>>,
) -> Self {
self.descriptor = Some(descriptor.map_fn_to());
self
}

/// Set the associated data. The default is no associated data.
pub fn data(mut self, data: Local<'s, Value>) -> Self {
self.data = Some(data);
self
}
}

#[derive(Default)]
pub struct IndexedPropertyHandlerConfiguration<'s> {
pub(crate) getter: Option<IndexedPropertyGetterCallback<'s>>,
pub(crate) setter: Option<IndexedPropertySetterCallback<'s>>,
pub(crate) query: Option<IndexedPropertyGetterCallback<'s>>,
pub(crate) deleter: Option<IndexedPropertyGetterCallback<'s>>,
pub(crate) enumerator: Option<PropertyEnumeratorCallback<'s>>,
pub(crate) descriptor: Option<IndexedPropertyGetterCallback<'s>>,
pub(crate) data: Option<Local<'s, Value>>,
}

impl<'s> IndexedPropertyHandlerConfiguration<'s> {
pub fn new() -> Self {
Self {
getter: None,
setter: None,
query: None,
deleter: None,
enumerator: None,
descriptor: None,
data: None,
}
}

pub fn is_some(&self) -> bool {
self.getter.is_some()
|| self.setter.is_some()
|| self.query.is_some()
|| self.deleter.is_some()
|| self.enumerator.is_some()
|| self.descriptor.is_some()
}

pub fn getter(
mut self,
getter: impl MapFnTo<IndexedPropertyGetterCallback<'s>>,
) -> Self {
self.getter = Some(getter.map_fn_to());
self
}

pub fn setter(
mut self,
setter: impl MapFnTo<IndexedPropertySetterCallback<'s>>,
) -> Self {
self.setter = Some(setter.map_fn_to());
self
}

pub fn query(
mut self,
query: impl MapFnTo<IndexedPropertyGetterCallback<'s>>,
) -> Self {
self.query = Some(query.map_fn_to());
self
}

pub fn deleter(
mut self,
deleter: impl MapFnTo<IndexedPropertyGetterCallback<'s>>,
) -> Self {
self.deleter = Some(deleter.map_fn_to());
self
}

pub fn enumerator(
mut self,
enumerator: impl MapFnTo<PropertyEnumeratorCallback<'s>>,
) -> Self {
self.enumerator = Some(enumerator.map_fn_to());
self
}

pub fn descriptor(
mut self,
descriptor: impl MapFnTo<IndexedPropertyGetterCallback<'s>>,
) -> Self {
self.descriptor = Some(descriptor.map_fn_to());
self
}

/// Set the associated data. The default is no associated data.
pub fn data(mut self, data: Local<'s, Value>) -> Self {
self.data = Some(data);
self
}
}

impl Template {
/// Adds a property to each instance created by this template.
#[inline(always)]
Expand Down Expand Up @@ -413,6 +622,46 @@ impl ObjectTemplate {
}
}

//Re uses the AccessorNameGetterCallback to avoid implementation conflicts since the declaration for
//GenericNamedPropertyGetterCallback and AccessorNameGetterCallback are the same
pub fn set_named_property_handler(
&self,
configuration: NamedPropertyHandlerConfiguration,
) {
assert!(configuration.is_some());
unsafe {
v8__ObjectTemplate__SetNamedPropertyHandler(
self,
configuration.getter,
configuration.setter,
configuration.query,
configuration.deleter,
configuration.enumerator,
configuration.descriptor,
configuration.data.map_or_else(null, |p| &*p),
)
}
}

pub fn set_indexed_property_handler(
&self,
configuration: IndexedPropertyHandlerConfiguration,
) {
assert!(configuration.is_some());
unsafe {
v8__ObjectTemplate__SetIndexedPropertyHandler(
self,
configuration.getter,
configuration.setter,
configuration.query,
configuration.deleter,
configuration.enumerator,
configuration.descriptor,
configuration.data.map_or_else(null, |p| &*p),
)
}
}

/// Sets an [accessor property](https://tc39.es/ecma262/#sec-property-attributes)
/// on the object template.
///
Expand Down
Loading

0 comments on commit cd51ea1

Please sign in to comment.