mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-12-25 16:49:29 -05:00
Add 'Object::set_accessor_with_setter' (#422)
This commit is contained in:
parent
9684640b48
commit
e74b6bcd0d
4 changed files with 148 additions and 0 deletions
|
@ -743,6 +743,15 @@ MaybeBool v8__Object__SetAccessor(const v8::Object& self,
|
||||||
ptr_to_local(&context), ptr_to_local(&key), getter));
|
ptr_to_local(&context), ptr_to_local(&key), getter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MaybeBool v8__Object__SetAccessorWithSetter(const v8::Object& self,
|
||||||
|
const v8::Context& context,
|
||||||
|
const v8::Name& key,
|
||||||
|
v8::AccessorNameGetterCallback getter,
|
||||||
|
v8::AccessorNameSetterCallback setter) {
|
||||||
|
return maybe_to_maybe_bool(ptr_to_local(&self)->SetAccessor(
|
||||||
|
ptr_to_local(&context), ptr_to_local(&key), getter, setter));
|
||||||
|
}
|
||||||
|
|
||||||
v8::Isolate* v8__Object__GetIsolate(const v8::Object& self) {
|
v8::Isolate* v8__Object__GetIsolate(const v8::Object& self) {
|
||||||
return ptr_to_local(&self)->GetIsolate();
|
return ptr_to_local(&self)->GetIsolate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,6 +258,26 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type AccessorNameSetterCallback<'s> =
|
||||||
|
extern "C" fn(Local<'s, Name>, Local<'s, Value>, *const PropertyCallbackInfo);
|
||||||
|
|
||||||
|
impl<F> MapFnFrom<F> for AccessorNameSetterCallback<'_>
|
||||||
|
where
|
||||||
|
F: UnitType
|
||||||
|
+ Fn(&mut HandleScope, Local<Name>, Local<Value>, PropertyCallbackArguments),
|
||||||
|
{
|
||||||
|
fn mapping() -> Self {
|
||||||
|
let f = |key: Local<Name>,
|
||||||
|
value: Local<Value>,
|
||||||
|
info: *const PropertyCallbackInfo| {
|
||||||
|
let scope = &mut unsafe { CallbackScope::new(&*info) };
|
||||||
|
let args = PropertyCallbackArguments::from_property_callback_info(info);
|
||||||
|
(F::get())(scope, key, value, args);
|
||||||
|
};
|
||||||
|
f.to_c_fn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
// TODO: add remaining arguments from C++
|
// TODO: add remaining arguments from C++
|
||||||
/// Create a function in the current execution context
|
/// Create a function in the current execution context
|
||||||
|
|
|
@ -3,6 +3,7 @@ use crate::support::int;
|
||||||
use crate::support::MapFnTo;
|
use crate::support::MapFnTo;
|
||||||
use crate::support::MaybeBool;
|
use crate::support::MaybeBool;
|
||||||
use crate::AccessorNameGetterCallback;
|
use crate::AccessorNameGetterCallback;
|
||||||
|
use crate::AccessorNameSetterCallback;
|
||||||
use crate::Array;
|
use crate::Array;
|
||||||
use crate::Context;
|
use crate::Context;
|
||||||
use crate::HandleScope;
|
use crate::HandleScope;
|
||||||
|
@ -28,6 +29,13 @@ extern "C" {
|
||||||
key: *const Name,
|
key: *const Name,
|
||||||
getter: AccessorNameGetterCallback,
|
getter: AccessorNameGetterCallback,
|
||||||
) -> MaybeBool;
|
) -> MaybeBool;
|
||||||
|
fn v8__Object__SetAccessorWithSetter(
|
||||||
|
this: *const Object,
|
||||||
|
context: *const Context,
|
||||||
|
key: *const Name,
|
||||||
|
getter: AccessorNameGetterCallback,
|
||||||
|
setter: AccessorNameSetterCallback,
|
||||||
|
) -> MaybeBool;
|
||||||
fn v8__Object__Get(
|
fn v8__Object__Get(
|
||||||
this: *const Object,
|
this: *const Object,
|
||||||
context: *const Context,
|
context: *const Context,
|
||||||
|
@ -286,6 +294,25 @@ impl Object {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_accessor_with_setter(
|
||||||
|
&self,
|
||||||
|
scope: &mut HandleScope,
|
||||||
|
name: Local<Name>,
|
||||||
|
getter: impl for<'s> MapFnTo<AccessorNameGetterCallback<'s>>,
|
||||||
|
setter: impl for<'s> MapFnTo<AccessorNameSetterCallback<'s>>,
|
||||||
|
) -> Option<bool> {
|
||||||
|
unsafe {
|
||||||
|
v8__Object__SetAccessorWithSetter(
|
||||||
|
self,
|
||||||
|
&*scope.get_current_context(),
|
||||||
|
&*name,
|
||||||
|
getter.map_fn_to(),
|
||||||
|
setter.map_fn_to(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
/// The `Object` specific equivalent of `Data::get_hash()`.
|
/// The `Object` specific equivalent of `Data::get_hash()`.
|
||||||
/// This function is kept around for testing purposes only.
|
/// This function is kept around for testing purposes only.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
|
|
@ -1345,6 +1345,98 @@ fn object_set_accessor() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn object_set_accessor_with_setter() {
|
||||||
|
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);
|
||||||
|
|
||||||
|
{
|
||||||
|
static CALL_COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
|
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, "getter_setter_key").unwrap();
|
||||||
|
assert!(key.strict_equals(expected_key.into()));
|
||||||
|
|
||||||
|
let int_key = v8::String::new(scope, "int_key").unwrap();
|
||||||
|
let int_value = this.get(scope, int_key.into()).unwrap();
|
||||||
|
let int_value = v8::Local::<v8::Integer>::try_from(int_value).unwrap();
|
||||||
|
assert_eq!(int_value.value(), 42);
|
||||||
|
|
||||||
|
let s = v8::String::new(scope, "hello").unwrap();
|
||||||
|
assert!(rv.get(scope).is_undefined());
|
||||||
|
rv.set(s.into());
|
||||||
|
|
||||||
|
CALL_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||||
|
};
|
||||||
|
|
||||||
|
let setter = |scope: &mut v8::HandleScope,
|
||||||
|
key: v8::Local<v8::Name>,
|
||||||
|
value: v8::Local<v8::Value>,
|
||||||
|
args: v8::PropertyCallbackArguments| {
|
||||||
|
println!("setter called");
|
||||||
|
let this = args.this();
|
||||||
|
|
||||||
|
let expected_key = v8::String::new(scope, "getter_setter_key").unwrap();
|
||||||
|
assert!(key.strict_equals(expected_key.into()));
|
||||||
|
|
||||||
|
let int_key = v8::String::new(scope, "int_key").unwrap();
|
||||||
|
let int_value = this.get(scope, int_key.into()).unwrap();
|
||||||
|
let int_value = v8::Local::<v8::Integer>::try_from(int_value).unwrap();
|
||||||
|
assert_eq!(int_value.value(), 42);
|
||||||
|
|
||||||
|
let new_value = v8::Local::<v8::Integer>::try_from(value).unwrap();
|
||||||
|
this.set(scope, int_key.into(), new_value.into());
|
||||||
|
|
||||||
|
CALL_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||||
|
};
|
||||||
|
|
||||||
|
let obj = v8::Object::new(scope);
|
||||||
|
|
||||||
|
let getter_setter_key =
|
||||||
|
v8::String::new(scope, "getter_setter_key").unwrap();
|
||||||
|
obj.set_accessor_with_setter(
|
||||||
|
scope,
|
||||||
|
getter_setter_key.into(),
|
||||||
|
getter,
|
||||||
|
setter,
|
||||||
|
);
|
||||||
|
|
||||||
|
let int_key = v8::String::new(scope, "int_key").unwrap();
|
||||||
|
let int_value = v8::Integer::new(scope, 42);
|
||||||
|
obj.set(scope, int_key.into(), int_value.into());
|
||||||
|
|
||||||
|
let obj_name = v8::String::new(scope, "obj").unwrap();
|
||||||
|
context
|
||||||
|
.global(scope)
|
||||||
|
.set(scope, obj_name.into(), obj.into());
|
||||||
|
|
||||||
|
let actual = eval(scope, "obj.getter_setter_key").unwrap();
|
||||||
|
let expected = v8::String::new(scope, "hello").unwrap();
|
||||||
|
assert!(actual.strict_equals(expected.into()));
|
||||||
|
|
||||||
|
eval(scope, "obj.getter_setter_key = 123").unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
obj
|
||||||
|
.get(scope, int_key.into())
|
||||||
|
.unwrap()
|
||||||
|
.to_integer(scope)
|
||||||
|
.unwrap()
|
||||||
|
.value(),
|
||||||
|
123
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(CALL_COUNT.load(Ordering::SeqCst), 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn promise_resolved() {
|
fn promise_resolved() {
|
||||||
let _setup_guard = setup();
|
let _setup_guard = setup();
|
||||||
|
|
Loading…
Reference in a new issue