0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2024-11-21 15:04:33 -05:00

Add ObjectTemplate::set_accessor{_with_setter} (#687)

This commit is contained in:
Matthew McAllister 2021-05-11 07:40:53 -07:00 committed by GitHub
parent fbd6528e63
commit 6d25d19b4c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 129 additions and 2 deletions

View file

@ -971,6 +971,19 @@ void v8__ObjectTemplate__SetInternalFieldCount(const v8::ObjectTemplate& self,
ptr_to_local(&self)->SetInternalFieldCount(value);
}
void v8__ObjectTemplate__SetAccessor(const v8::ObjectTemplate& self,
const v8::Name& key,
v8::AccessorNameGetterCallback getter) {
ptr_to_local(&self)->SetAccessor(ptr_to_local(&key), getter);
}
void v8__ObjectTemplate__SetAccessorWithSetter(
const v8::ObjectTemplate& self, const v8::Name& key,
v8::AccessorNameGetterCallback getter,
v8::AccessorNameSetterCallback setter) {
ptr_to_local(&self)->SetAccessor(ptr_to_local(&key), getter, setter);
}
const v8::Object* v8__Object__New(v8::Isolate* isolate) {
return local_to_ptr(v8::Object::New(isolate));
}

View file

@ -213,7 +213,9 @@ pub struct PropertyCallbackArguments<'s> {
}
impl<'s> PropertyCallbackArguments<'s> {
fn from_property_callback_info(info: *const PropertyCallbackInfo) -> Self {
pub(crate) fn from_property_callback_info(
info: *const PropertyCallbackInfo,
) -> Self {
Self {
info,
phantom: PhantomData,

View file

@ -6,6 +6,8 @@ use crate::data::Template;
use crate::isolate::Isolate;
use crate::support::int;
use crate::support::MapFnTo;
use crate::AccessorNameGetterCallback;
use crate::AccessorNameSetterCallback;
use crate::CFunction;
use crate::ConstructorBehavior;
use crate::Context;
@ -68,6 +70,17 @@ extern "C" {
this: *const ObjectTemplate,
value: int,
);
fn v8__ObjectTemplate__SetAccessor(
this: *const ObjectTemplate,
key: *const Name,
getter: AccessorNameGetterCallback,
);
fn v8__ObjectTemplate__SetAccessorWithSetter(
this: *const ObjectTemplate,
key: *const Name,
getter: AccessorNameGetterCallback,
setter: AccessorNameSetterCallback,
);
}
impl Template {
@ -228,4 +241,28 @@ impl ObjectTemplate {
}
}
}
pub fn set_accessor(
&self,
key: Local<Name>,
getter: impl for<'s> MapFnTo<AccessorNameGetterCallback<'s>>,
) {
unsafe { v8__ObjectTemplate__SetAccessor(self, &*key, getter.map_fn_to()) }
}
pub fn set_accessor_with_setter(
&self,
key: Local<Name>,
getter: impl for<'s> MapFnTo<AccessorNameGetterCallback<'s>>,
setter: impl for<'s> MapFnTo<AccessorNameSetterCallback<'s>>,
) {
unsafe {
v8__ObjectTemplate__SetAccessorWithSetter(
self,
&*key,
getter.map_fn_to(),
setter.map_fn_to(),
)
}
}
}

View file

@ -1314,6 +1314,81 @@ fn function_template_signature() {
}
}
#[test]
fn object_template_set_accessor() {
let _setup_guard = setup();
let isolate = &mut v8::Isolate::new(Default::default());
let scope = &mut v8::HandleScope::new(isolate);
let context = v8::Context::new(scope);
let scope = &mut v8::ContextScope::new(scope, context);
{
let getter = |scope: &mut v8::HandleScope,
key: v8::Local<v8::Name>,
args: v8::PropertyCallbackArguments,
mut rv: v8::ReturnValue| {
let this = args.this();
let expected_key = v8::String::new(scope, "key").unwrap();
assert!(key.strict_equals(expected_key.into()));
rv.set(this.get_internal_field(scope, 0).unwrap());
};
let setter = |scope: &mut v8::HandleScope,
key: v8::Local<v8::Name>,
value: v8::Local<v8::Value>,
args: v8::PropertyCallbackArguments| {
let this = args.this();
let expected_key = v8::String::new(scope, "key").unwrap();
assert!(key.strict_equals(expected_key.into()));
assert!(value.is_int32());
assert!(this.set_internal_field(0, value));
};
let key = v8::String::new(scope, "key").unwrap();
let name = v8::String::new(scope, "obj").unwrap();
// Lone getter
let templ = v8::ObjectTemplate::new(scope);
templ.set_internal_field_count(1);
templ.set_accessor(key.into(), getter);
let obj = templ.new_instance(scope).unwrap();
let int = v8::Integer::new(scope, 42);
obj.set_internal_field(0, int.into());
scope.get_current_context().global(scope).set(
scope,
name.into(),
obj.into(),
);
assert!(eval(scope, "obj.key").unwrap().strict_equals(int.into()));
// Getter + setter
let templ = v8::ObjectTemplate::new(scope);
templ.set_internal_field_count(1);
templ.set_accessor_with_setter(key.into(), getter, setter);
let obj = templ.new_instance(scope).unwrap();
obj.set_internal_field(0, int.into());
scope.get_current_context().global(scope).set(
scope,
name.into(),
obj.into(),
);
let new_int = v8::Integer::new(scope, 9);
eval(scope, "obj.key = 9");
assert!(obj
.get_internal_field(scope, 0)
.unwrap()
.strict_equals(new_int.into()));
// Falls back on standard setter
assert!(eval(scope, "obj.key2 = null; obj.key2").unwrap().is_null());
}
}
#[test]
fn object() {
let _setup_guard = setup();
@ -4352,7 +4427,7 @@ fn value_serializer_and_deserializer_js_objects() {
} else {
equal = equal && (item == objects[index]);
}
});
});
equal.toString()
}
"#,