mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-11-24 15:19:31 -05:00
Add more Object methods (#1240)
Specifically Object::get_own_property_descriptor and Object::get_property_attributes
This commit is contained in:
parent
2aa6debd2b
commit
43b798a39d
4 changed files with 149 additions and 0 deletions
|
@ -1426,6 +1426,21 @@ MaybeBool v8__Object__HasPrivate(const v8::Object& self,
|
|||
ptr_to_local(&context), ptr_to_local(&key)));
|
||||
}
|
||||
|
||||
void v8__Object__GetPropertyAttributes(
|
||||
const v8::Object& self, const v8::Context& context,
|
||||
const v8::Value& key, v8::Maybe<v8::PropertyAttribute>* out) {
|
||||
*out = ptr_to_local(&self)->GetPropertyAttributes(ptr_to_local(&context),
|
||||
ptr_to_local(&key));
|
||||
}
|
||||
|
||||
const v8::Value* v8__Object__GetOwnPropertyDescriptor(
|
||||
const v8::Object& self, const v8::Context& context,
|
||||
const v8::Name& key) {
|
||||
return maybe_local_to_ptr(ptr_to_local(&self)->GetOwnPropertyDescriptor(
|
||||
ptr_to_local(&context), ptr_to_local(&key)));
|
||||
}
|
||||
|
||||
|
||||
const v8::Array* v8__Array__New(v8::Isolate* isolate, int length) {
|
||||
return local_to_ptr(v8::Array::New(isolate, length));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::isolate::Isolate;
|
||||
use crate::support::int;
|
||||
use crate::support::MapFnTo;
|
||||
use crate::support::Maybe;
|
||||
use crate::support::MaybeBool;
|
||||
use crate::AccessorConfiguration;
|
||||
use crate::AccessorNameGetterCallback;
|
||||
|
@ -180,6 +181,17 @@ extern "C" {
|
|||
context: *const Context,
|
||||
key: *const Private,
|
||||
) -> MaybeBool;
|
||||
fn v8__Object__GetPropertyAttributes(
|
||||
this: *const Object,
|
||||
context: *const Context,
|
||||
key: *const Value,
|
||||
out: *mut Maybe<PropertyAttribute>,
|
||||
);
|
||||
fn v8__Object__GetOwnPropertyDescriptor(
|
||||
this: *const Object,
|
||||
context: *const Context,
|
||||
key: *const Name,
|
||||
) -> *const Value;
|
||||
|
||||
fn v8__Array__New(isolate: *mut Isolate, length: int) -> *const Array;
|
||||
fn v8__Array__New_with_elements(
|
||||
|
@ -755,6 +767,46 @@ impl Object {
|
|||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Gets the property attributes of a property which can be
|
||||
/// [PropertyAttribute::NONE] or any combination of
|
||||
/// [PropertyAttribute::READ_ONLY], [PropertyAttribute::DONT_ENUM] and
|
||||
/// [PropertyAttribute::DONT_DELETE].
|
||||
/// Returns [PropertyAttribute::NONE] when the property doesn't exist.
|
||||
pub fn get_property_attributes(
|
||||
&self,
|
||||
scope: &mut HandleScope,
|
||||
key: Local<Value>,
|
||||
) -> Option<PropertyAttribute> {
|
||||
let mut out = Maybe::<PropertyAttribute>::default();
|
||||
unsafe {
|
||||
v8__Object__GetPropertyAttributes(
|
||||
self,
|
||||
&*scope.get_current_context(),
|
||||
&*key,
|
||||
&mut out,
|
||||
)
|
||||
};
|
||||
out.into()
|
||||
}
|
||||
|
||||
/// Implements Object.getOwnPropertyDescriptor(O, P), see
|
||||
/// https://tc39.es/ecma262/#sec-object.getownpropertydescriptor.
|
||||
pub fn get_own_property_descriptor<'s>(
|
||||
&self,
|
||||
scope: &mut HandleScope<'s>,
|
||||
key: Local<Name>,
|
||||
) -> Option<Local<'s, Value>> {
|
||||
unsafe {
|
||||
scope.cast_local(|sd| {
|
||||
v8__Object__GetOwnPropertyDescriptor(
|
||||
self,
|
||||
sd.get_current_context(),
|
||||
&*key,
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Object integrity levels can be used to restrict what can be done to an
|
||||
|
|
|
@ -48,6 +48,11 @@ impl PropertyAttribute {
|
|||
let Self(rhs) = that;
|
||||
0 != lhs & rhs
|
||||
}
|
||||
|
||||
pub fn as_u32(&self) -> u32 {
|
||||
let Self(bits) = self;
|
||||
*bits
|
||||
}
|
||||
}
|
||||
|
||||
// Identical to #[derive(Default)] but arguably clearer when made explicit.
|
||||
|
|
|
@ -6129,6 +6129,83 @@ fn get_constructor_name() {
|
|||
check_ctor_name(scope, "proto", "Parent");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_property_attributes() {
|
||||
let _setup_guard = setup::parallel_test();
|
||||
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 obj = eval(scope, "({ a: 1 })").unwrap();
|
||||
let obj = obj.to_object(scope).unwrap();
|
||||
let key = v8::String::new(scope, "a").unwrap();
|
||||
let attrs = obj.get_property_attributes(scope, key.into()).unwrap();
|
||||
assert!(!attrs.is_read_only());
|
||||
assert!(!attrs.is_dont_enum());
|
||||
assert!(!attrs.is_dont_delete());
|
||||
assert!(attrs.is_none());
|
||||
|
||||
// doesn't exist
|
||||
let key = v8::String::new(scope, "b").unwrap();
|
||||
let attrs = obj.get_property_attributes(scope, key.into()).unwrap();
|
||||
assert!(attrs.is_none());
|
||||
|
||||
// exception
|
||||
let key = eval(scope, "({ toString() { throw 'foo' } })").unwrap();
|
||||
let tc = &mut v8::TryCatch::new(scope);
|
||||
assert!(obj.get_property_attributes(tc, key).is_none());
|
||||
assert!(tc.has_caught());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_own_property_descriptor() {
|
||||
let _setup_guard = setup::parallel_test();
|
||||
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 obj = eval(scope, "({ a: 1 })").unwrap();
|
||||
let obj = obj.to_object(scope).unwrap();
|
||||
let key = v8::String::new(scope, "a").unwrap();
|
||||
let desc = obj.get_own_property_descriptor(scope, key.into()).unwrap();
|
||||
let desc = desc.to_object(scope).unwrap();
|
||||
|
||||
let value_key = v8::String::new(scope, "value").unwrap();
|
||||
let value = desc.get(scope, value_key.into()).unwrap();
|
||||
assert!(value.is_number());
|
||||
|
||||
let writable_key = v8::String::new(scope, "writable").unwrap();
|
||||
let writable = desc.get(scope, writable_key.into()).unwrap();
|
||||
assert!(writable.is_boolean());
|
||||
assert!(writable.boolean_value(scope));
|
||||
|
||||
let enumerable_key = v8::String::new(scope, "enumerable").unwrap();
|
||||
let enumerable = desc.get(scope, enumerable_key.into()).unwrap();
|
||||
assert!(enumerable.is_boolean());
|
||||
assert!(enumerable.boolean_value(scope));
|
||||
|
||||
let configurable_key = v8::String::new(scope, "configurable").unwrap();
|
||||
let configurable = desc.get(scope, configurable_key.into()).unwrap();
|
||||
assert!(configurable.is_boolean());
|
||||
|
||||
let get_key = v8::String::new(scope, "get").unwrap();
|
||||
let get = desc.get(scope, get_key.into()).unwrap();
|
||||
assert!(get.is_undefined());
|
||||
|
||||
let set_key = v8::String::new(scope, "set").unwrap();
|
||||
let set = desc.get(scope, set_key.into()).unwrap();
|
||||
assert!(set.is_undefined());
|
||||
|
||||
// doesn't exist
|
||||
let b_key = v8::String::new(scope, "b").unwrap();
|
||||
let desc = obj
|
||||
.get_own_property_descriptor(scope, b_key.into())
|
||||
.unwrap();
|
||||
assert!(desc.is_undefined());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prototype_api() {
|
||||
let _setup_guard = setup::parallel_test();
|
||||
|
|
Loading…
Reference in a new issue