mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-11-22 04:40:01 +00:00
Improved ObjectTemplate::set_*_handlers (#1237)
Prior to this commit, `v8::NamedPropertyHandlerConfiguration` and `v8::IndexedPropertyHandlerConfiguration` did not expose the `definer` hook, or `flags`. This commit adds these options. In the process of doing this a couple of other changes were made: - Bitflag enum consts are now member consts of the related struct. This is done because PropertyHandlerFlags has conflicts with PropertyAttribute. - PropertyDescriptor gets all C++ introspection methods exposed to Rust. - NamedPropertyHandlerConfiguration callback types get rustdoc comments. - IndexedPropertyHandlerConfiguration callback types get rustdoc comments. - GenericNamedPropertySetterCallback gets a ReturnValue parameter, to signal trap passthrough. Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This commit is contained in:
parent
43b798a39d
commit
e7f96ac708
@ -1148,11 +1148,13 @@ void v8__ObjectTemplate__SetNamedPropertyHandler(
|
||||
v8::GenericNamedPropertyQueryCallback query,
|
||||
v8::GenericNamedPropertyDeleterCallback deleter,
|
||||
v8::GenericNamedPropertyEnumeratorCallback enumerator,
|
||||
v8::GenericNamedPropertyDefinerCallback definer,
|
||||
v8::GenericNamedPropertyDescriptorCallback descriptor,
|
||||
const v8::Value* data_or_null) {
|
||||
const v8::Value* data_or_null,
|
||||
v8::PropertyHandlerFlags flags) {
|
||||
ptr_to_local(&self)->SetHandler(v8::NamedPropertyHandlerConfiguration(
|
||||
getter, setter, query, deleter, enumerator, nullptr, descriptor,
|
||||
ptr_to_local(data_or_null)));
|
||||
getter, setter, query, deleter, enumerator, definer, descriptor,
|
||||
ptr_to_local(data_or_null), flags));
|
||||
}
|
||||
|
||||
void v8__ObjectTemplate__SetIndexedPropertyHandler(
|
||||
@ -1161,11 +1163,13 @@ void v8__ObjectTemplate__SetIndexedPropertyHandler(
|
||||
v8::IndexedPropertyQueryCallback query,
|
||||
v8::IndexedPropertyDeleterCallback deleter,
|
||||
v8::IndexedPropertyEnumeratorCallback enumerator,
|
||||
v8::IndexedPropertyDefinerCallback definer,
|
||||
v8::IndexedPropertyDescriptorCallback descriptor,
|
||||
const v8::Value* data_or_null) {
|
||||
const v8::Value* data_or_null,
|
||||
v8::PropertyHandlerFlags flags) {
|
||||
ptr_to_local(&self)->SetHandler(v8::IndexedPropertyHandlerConfiguration(
|
||||
getter, setter, query, deleter, enumerator, nullptr, descriptor,
|
||||
ptr_to_local(data_or_null)));
|
||||
getter, setter, query, deleter, enumerator, definer, descriptor,
|
||||
ptr_to_local(data_or_null), flags));
|
||||
}
|
||||
|
||||
void v8__ObjectTemplate__SetAccessorProperty(const v8::ObjectTemplate& self,
|
||||
@ -3357,6 +3361,60 @@ void v8__PropertyDescriptor__DESTRUCT(v8::PropertyDescriptor* self) {
|
||||
self->~PropertyDescriptor();
|
||||
}
|
||||
|
||||
bool v8__PropertyDescriptor__configurable(const v8::PropertyDescriptor* self) {
|
||||
return self->configurable();
|
||||
}
|
||||
|
||||
bool v8__PropertyDescriptor__enumerable(const v8::PropertyDescriptor* self) {
|
||||
return self->enumerable();
|
||||
}
|
||||
|
||||
bool v8__PropertyDescriptor__writable(const v8::PropertyDescriptor* self) {
|
||||
return self->writable();
|
||||
}
|
||||
|
||||
const v8::Value* v8__PropertyDescriptor__value(
|
||||
const v8::PropertyDescriptor* self) {
|
||||
return local_to_ptr(self->value());
|
||||
}
|
||||
|
||||
const v8::Value* v8__PropertyDescriptor__get(
|
||||
const v8::PropertyDescriptor* self) {
|
||||
return local_to_ptr(self->get());
|
||||
}
|
||||
|
||||
const v8::Value* v8__PropertyDescriptor__set(
|
||||
const v8::PropertyDescriptor* self) {
|
||||
return local_to_ptr(self->set());
|
||||
}
|
||||
|
||||
bool v8__PropertyDescriptor__has_configurable(
|
||||
const v8::PropertyDescriptor* self) {
|
||||
return self->has_configurable();
|
||||
}
|
||||
|
||||
bool v8__PropertyDescriptor__has_enumerable(
|
||||
const v8::PropertyDescriptor* self) {
|
||||
return self->has_enumerable();
|
||||
}
|
||||
|
||||
bool v8__PropertyDescriptor__has_writable(
|
||||
const v8::PropertyDescriptor* self) {
|
||||
return self->has_writable();
|
||||
}
|
||||
|
||||
bool v8__PropertyDescriptor__has_value(const v8::PropertyDescriptor* self) {
|
||||
return self->has_value();
|
||||
}
|
||||
|
||||
bool v8__PropertyDescriptor__has_get(const v8::PropertyDescriptor* self) {
|
||||
return self->has_get();
|
||||
}
|
||||
|
||||
bool v8__PropertyDescriptor__has_set(const v8::PropertyDescriptor* self) {
|
||||
return self->has_set();
|
||||
}
|
||||
|
||||
void v8__PropertyDescriptor__set_enumerable(v8::PropertyDescriptor* self,
|
||||
bool enumurable) {
|
||||
self->set_enumerable(enumurable);
|
||||
|
@ -1,14 +1,27 @@
|
||||
// Copyright 2019-2021 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::support::intptr_t;
|
||||
use crate::AccessorNameGetterCallback;
|
||||
use crate::FunctionCallback;
|
||||
use crate::IndexedDefinerCallback;
|
||||
use crate::IndexedGetterCallback;
|
||||
use crate::IndexedSetterCallback;
|
||||
use crate::MessageCallback;
|
||||
use crate::NamedDefinerCallback;
|
||||
use crate::NamedGetterCallback;
|
||||
use crate::NamedSetterCallback;
|
||||
use crate::PropertyEnumeratorCallback;
|
||||
use std::ffi::c_void;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub union ExternalReference<'s> {
|
||||
pub function: FunctionCallback,
|
||||
pub getter: AccessorNameGetterCallback<'s>,
|
||||
pub named_getter: NamedGetterCallback<'s>,
|
||||
pub named_setter: NamedSetterCallback<'s>,
|
||||
pub named_definer: NamedDefinerCallback<'s>,
|
||||
pub indexed_getter: IndexedGetterCallback<'s>,
|
||||
pub indexed_setter: IndexedSetterCallback<'s>,
|
||||
pub indexed_definer: IndexedDefinerCallback<'s>,
|
||||
pub enumerator: PropertyEnumeratorCallback<'s>,
|
||||
pub message: MessageCallback,
|
||||
pub pointer: *mut c_void,
|
||||
}
|
||||
|
133
src/function.rs
133
src/function.rs
@ -18,6 +18,7 @@ use crate::Isolate;
|
||||
use crate::Local;
|
||||
use crate::Name;
|
||||
use crate::Object;
|
||||
use crate::PropertyDescriptor;
|
||||
use crate::Signature;
|
||||
use crate::String;
|
||||
use crate::UniqueRef;
|
||||
@ -121,7 +122,7 @@ impl<'cb> ReturnValue<'cb> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn from_property_callback_info(info: &'cb PropertyCallbackInfo) -> Self {
|
||||
pub fn from_property_callback_info(info: &'cb PropertyCallbackInfo) -> Self {
|
||||
let nn = info.get_return_value_non_null();
|
||||
Self(nn, PhantomData)
|
||||
}
|
||||
@ -521,10 +522,10 @@ impl<'s> PropertyCallbackArguments<'s> {
|
||||
|
||||
pub type FunctionCallback = extern "C" fn(*const FunctionCallbackInfo);
|
||||
|
||||
impl<'a, F> MapFnFrom<F> for FunctionCallback
|
||||
impl<F> MapFnFrom<F> for FunctionCallback
|
||||
where
|
||||
F: UnitType
|
||||
+ Fn(&mut HandleScope<'a>, FunctionCallbackArguments<'a>, ReturnValue),
|
||||
+ for<'s> Fn(&mut HandleScope<'s>, FunctionCallbackArguments<'s>, ReturnValue),
|
||||
{
|
||||
fn mapping() -> Self {
|
||||
let f = |info: *const FunctionCallbackInfo| {
|
||||
@ -538,15 +539,18 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// AccessorNameGetterCallback is used as callback functions when getting a
|
||||
/// particular property. See Object and ObjectTemplate's method SetAccessor.
|
||||
pub type AccessorNameGetterCallback<'s> =
|
||||
pub(crate) type NamedGetterCallback<'s> =
|
||||
extern "C" fn(Local<'s, Name>, *const PropertyCallbackInfo);
|
||||
|
||||
impl<F> MapFnFrom<F> for AccessorNameGetterCallback<'_>
|
||||
impl<F> MapFnFrom<F> for NamedGetterCallback<'_>
|
||||
where
|
||||
F: UnitType
|
||||
+ Fn(&mut HandleScope, Local<Name>, PropertyCallbackArguments, ReturnValue),
|
||||
+ for<'s> Fn(
|
||||
&mut HandleScope<'s>,
|
||||
Local<'s, Name>,
|
||||
PropertyCallbackArguments<'s>,
|
||||
ReturnValue,
|
||||
),
|
||||
{
|
||||
fn mapping() -> Self {
|
||||
let f = |key: Local<Name>, info: *const PropertyCallbackInfo| {
|
||||
@ -560,13 +564,19 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub type AccessorNameSetterCallback<'s> =
|
||||
pub(crate) type NamedSetterCallback<'s> =
|
||||
extern "C" fn(Local<'s, Name>, Local<'s, Value>, *const PropertyCallbackInfo);
|
||||
|
||||
impl<F> MapFnFrom<F> for AccessorNameSetterCallback<'_>
|
||||
impl<F> MapFnFrom<F> for NamedSetterCallback<'_>
|
||||
where
|
||||
F: UnitType
|
||||
+ Fn(&mut HandleScope, Local<Name>, Local<Value>, PropertyCallbackArguments),
|
||||
+ for<'s> Fn(
|
||||
&mut HandleScope<'s>,
|
||||
Local<'s, Name>,
|
||||
Local<'s, Value>,
|
||||
PropertyCallbackArguments<'s>,
|
||||
ReturnValue,
|
||||
),
|
||||
{
|
||||
fn mapping() -> Self {
|
||||
let f = |key: Local<Name>,
|
||||
@ -575,19 +585,21 @@ where
|
||||
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);
|
||||
let rv = ReturnValue::from_property_callback_info(info);
|
||||
(F::get())(scope, key, value, args, rv);
|
||||
};
|
||||
f.to_c_fn()
|
||||
}
|
||||
}
|
||||
|
||||
//Should return an Array in Return Value
|
||||
pub type PropertyEnumeratorCallback<'s> =
|
||||
// Should return an Array in Return Value
|
||||
pub(crate) type PropertyEnumeratorCallback<'s> =
|
||||
extern "C" fn(*const PropertyCallbackInfo);
|
||||
|
||||
impl<F> MapFnFrom<F> for PropertyEnumeratorCallback<'_>
|
||||
where
|
||||
F: UnitType + Fn(&mut HandleScope, PropertyCallbackArguments, ReturnValue),
|
||||
F: UnitType
|
||||
+ for<'s> Fn(&mut HandleScope<'s>, PropertyCallbackArguments<'s>, ReturnValue),
|
||||
{
|
||||
fn mapping() -> Self {
|
||||
let f = |info: *const PropertyCallbackInfo| {
|
||||
@ -601,15 +613,50 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// 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);
|
||||
pub(crate) type NamedDefinerCallback<'s> = extern "C" fn(
|
||||
Local<'s, Name>,
|
||||
*const PropertyDescriptor,
|
||||
*const PropertyCallbackInfo,
|
||||
);
|
||||
|
||||
impl<F> MapFnFrom<F> for IndexedPropertyGetterCallback<'_>
|
||||
impl<F> MapFnFrom<F> for NamedDefinerCallback<'_>
|
||||
where
|
||||
F: UnitType
|
||||
+ Fn(&mut HandleScope, u32, PropertyCallbackArguments, ReturnValue),
|
||||
+ for<'s> Fn(
|
||||
&mut HandleScope<'s>,
|
||||
Local<'s, Name>,
|
||||
&PropertyDescriptor,
|
||||
PropertyCallbackArguments<'s>,
|
||||
ReturnValue,
|
||||
),
|
||||
{
|
||||
fn mapping() -> Self {
|
||||
let f = |key: Local<Name>,
|
||||
desc: *const PropertyDescriptor,
|
||||
info: *const PropertyCallbackInfo| {
|
||||
let info = unsafe { &*info };
|
||||
let scope = &mut unsafe { CallbackScope::new(info) };
|
||||
let args = PropertyCallbackArguments::from_property_callback_info(info);
|
||||
let desc = unsafe { &*desc };
|
||||
let rv = ReturnValue::from_property_callback_info(info);
|
||||
(F::get())(scope, key, desc, args, rv);
|
||||
};
|
||||
f.to_c_fn()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type IndexedGetterCallback<'s> =
|
||||
extern "C" fn(u32, *const PropertyCallbackInfo);
|
||||
|
||||
impl<F> MapFnFrom<F> for IndexedGetterCallback<'_>
|
||||
where
|
||||
F: UnitType
|
||||
+ for<'s> Fn(
|
||||
&mut HandleScope<'s>,
|
||||
u32,
|
||||
PropertyCallbackArguments<'s>,
|
||||
ReturnValue,
|
||||
),
|
||||
{
|
||||
fn mapping() -> Self {
|
||||
let f = |index: u32, info: *const PropertyCallbackInfo| {
|
||||
@ -623,13 +670,19 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub type IndexedPropertySetterCallback<'s> =
|
||||
pub(crate) type IndexedSetterCallback<'s> =
|
||||
extern "C" fn(u32, Local<'s, Value>, *const PropertyCallbackInfo);
|
||||
|
||||
impl<F> MapFnFrom<F> for IndexedPropertySetterCallback<'_>
|
||||
impl<F> MapFnFrom<F> for IndexedSetterCallback<'_>
|
||||
where
|
||||
F: UnitType
|
||||
+ Fn(&mut HandleScope, u32, Local<Value>, PropertyCallbackArguments),
|
||||
+ for<'s> Fn(
|
||||
&mut HandleScope<'s>,
|
||||
u32,
|
||||
Local<'s, Value>,
|
||||
PropertyCallbackArguments<'s>,
|
||||
ReturnValue,
|
||||
),
|
||||
{
|
||||
fn mapping() -> Self {
|
||||
let f =
|
||||
@ -637,12 +690,42 @@ where
|
||||
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);
|
||||
let rv = ReturnValue::from_property_callback_info(info);
|
||||
(F::get())(scope, index, value, args, rv);
|
||||
};
|
||||
f.to_c_fn()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type IndexedDefinerCallback<'s> =
|
||||
extern "C" fn(u32, *const PropertyDescriptor, *const PropertyCallbackInfo);
|
||||
|
||||
impl<F> MapFnFrom<F> for IndexedDefinerCallback<'_>
|
||||
where
|
||||
F: UnitType
|
||||
+ for<'s> Fn(
|
||||
&mut HandleScope<'s>,
|
||||
u32,
|
||||
&PropertyDescriptor,
|
||||
PropertyCallbackArguments<'s>,
|
||||
ReturnValue,
|
||||
),
|
||||
{
|
||||
fn mapping() -> Self {
|
||||
let f = |index: u32,
|
||||
desc: *const PropertyDescriptor,
|
||||
info: *const PropertyCallbackInfo| {
|
||||
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);
|
||||
let desc = unsafe { &*desc };
|
||||
(F::get())(scope, index, desc, args, rv);
|
||||
};
|
||||
f.to_c_fn()
|
||||
}
|
||||
}
|
||||
|
||||
/// A builder to construct the properties of a Function or FunctionTemplate.
|
||||
pub struct FunctionBuilder<'s, T> {
|
||||
pub(crate) callback: FunctionCallback,
|
||||
|
35
src/gc.rs
35
src/gc.rs
@ -7,17 +7,19 @@
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||
pub struct GCType(u32);
|
||||
|
||||
pub const GC_TYPE_TYPE_SCAVENGE: GCType = GCType(1);
|
||||
impl GCType {
|
||||
pub const SCAVENGE: Self = Self(1 << 0);
|
||||
|
||||
pub const GC_TYPE_MINOR_MARK_COMPACT: GCType = GCType(2);
|
||||
pub const MINOR_MARK_COMPACT: Self = Self(1 << 1);
|
||||
|
||||
pub const GC_TYPE_MARK_SWEEP_COMPACT: GCType = GCType(4);
|
||||
pub const MARK_SWEEP_COMPACT: Self = Self(1 << 2);
|
||||
|
||||
pub const GC_TYPE_INCREMENTAL_MARKING: GCType = GCType(8);
|
||||
pub const INCREMENTAL_MARKING: Self = Self(1 << 3);
|
||||
|
||||
pub const GC_TYPE_PROCESS_WEAK_CALLBACK: GCType = GCType(16);
|
||||
pub const PROCESS_WEAK_CALLBACKS: Self = Self(1 << 4);
|
||||
|
||||
pub const GC_TYPE_ALL: GCType = GCType(31);
|
||||
pub const ALL: Self = Self(31);
|
||||
}
|
||||
|
||||
impl std::ops::BitOr for GCType {
|
||||
type Output = Self;
|
||||
@ -44,24 +46,21 @@ impl std::ops::BitOr for GCType {
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||
pub struct GCCallbackFlags(u32);
|
||||
|
||||
pub const GC_CALLBACK_FLAGS_NO_FLAGS: GCCallbackFlags = GCCallbackFlags(0);
|
||||
impl GCCallbackFlags {
|
||||
pub const NONE: Self = Self(0);
|
||||
|
||||
pub const GC_CALLBACK_FLAGS_CONSTRUCT_RETAINED_OBJECT_INFOS: GCCallbackFlags =
|
||||
GCCallbackFlags(2);
|
||||
pub const CONSTRUCT_RETAINED_OBJECT_INFOS: Self = Self(1 << 1);
|
||||
|
||||
pub const GC_CALLBACK_FLAGS_FORCED: GCCallbackFlags = GCCallbackFlags(4);
|
||||
pub const FORCED: Self = Self(1 << 2);
|
||||
|
||||
pub const GC_CALLBACK_FLAGS_SYNCHRONOUS_PHANTOM_CALLBACK_PROCESSING:
|
||||
GCCallbackFlags = GCCallbackFlags(8);
|
||||
pub const SYNCHRONOUS_PHANTOM_CALLBACK_PROCESSING: Self = Self(1 << 3);
|
||||
|
||||
pub const GC_CALLBACK_FLAGS_COLLECT_ALL_AVAILABLE_GARBAGE: GCCallbackFlags =
|
||||
GCCallbackFlags(16);
|
||||
pub const COLLECT_ALL_AVAILABLE_GARBAGE: Self = Self(1 << 4);
|
||||
|
||||
pub const GC_CALLBACK_FLAGS_COLLECT_ALL_EXTERNAL_MEMORY: GCCallbackFlags =
|
||||
GCCallbackFlags(32);
|
||||
pub const COLLECT_ALL_EXTERNAL_MEMORY: Self = Self(1 << 5);
|
||||
|
||||
pub const GC_CALLBACK_FLAGS_SCHEDULE_IDLE_GARBAGE_COLLECTION: GCCallbackFlags =
|
||||
GCCallbackFlags(64);
|
||||
pub const SCHEDULE_IDLE_GARBAGE_COLLECTION: Self = Self(1 << 6);
|
||||
}
|
||||
|
||||
impl std::ops::BitOr for GCCallbackFlags {
|
||||
type Output = Self;
|
||||
|
@ -1,6 +1,4 @@
|
||||
use crate::PropertyFilter;
|
||||
use crate::ONLY_ENUMERABLE;
|
||||
use crate::SKIP_SYMBOLS;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
@ -47,7 +45,8 @@ impl Default for GetPropertyNamesArgs {
|
||||
fn default() -> Self {
|
||||
GetPropertyNamesArgs {
|
||||
mode: KeyCollectionMode::IncludePrototypes,
|
||||
property_filter: ONLY_ENUMERABLE | SKIP_SYMBOLS,
|
||||
property_filter: PropertyFilter::ONLY_ENUMERABLE
|
||||
| PropertyFilter::SKIP_SYMBOLS,
|
||||
index_filter: IndexFilter::IncludeIndices,
|
||||
key_conversion: KeyConversionMode::KeepNumbers,
|
||||
}
|
||||
@ -72,7 +71,8 @@ impl GetPropertyNamesArgsBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
mode: KeyCollectionMode::IncludePrototypes,
|
||||
property_filter: ONLY_ENUMERABLE | SKIP_SYMBOLS,
|
||||
property_filter: PropertyFilter::ONLY_ENUMERABLE
|
||||
| PropertyFilter::SKIP_SYMBOLS,
|
||||
index_filter: IndexFilter::IncludeIndices,
|
||||
key_conversion: KeyConversionMode::KeepNumbers,
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ mod promise;
|
||||
mod property_attribute;
|
||||
mod property_descriptor;
|
||||
mod property_filter;
|
||||
mod property_handler_flags;
|
||||
mod proxy;
|
||||
mod scope;
|
||||
mod script;
|
||||
@ -126,6 +127,7 @@ pub use promise::{PromiseRejectEvent, PromiseRejectMessage, PromiseState};
|
||||
pub use property_attribute::*;
|
||||
pub use property_descriptor::*;
|
||||
pub use property_filter::*;
|
||||
pub use property_handler_flags::*;
|
||||
pub use proxy::*;
|
||||
pub use scope::CallbackScope;
|
||||
pub use scope::ContextScope;
|
||||
|
@ -2,44 +2,44 @@
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct PropertyAttribute(u32);
|
||||
|
||||
/// No property attributes.
|
||||
pub const NONE: PropertyAttribute = PropertyAttribute(0);
|
||||
|
||||
/// Not writable. Corresponds to
|
||||
/// `Object.defineProperty(o, "p", { writable: false })`.
|
||||
pub const READ_ONLY: PropertyAttribute = PropertyAttribute(1);
|
||||
|
||||
/// Not enumerable. Corresponds to
|
||||
/// `Object.defineProperty(o, "p", { enumerable: false })`.
|
||||
pub const DONT_ENUM: PropertyAttribute = PropertyAttribute(2);
|
||||
|
||||
/// Not configurable. Corresponds to
|
||||
/// `Object.defineProperty(o, "p", { configurable: false })`.
|
||||
pub const DONT_DELETE: PropertyAttribute = PropertyAttribute(4);
|
||||
|
||||
impl PropertyAttribute {
|
||||
/// No property attributes.
|
||||
pub const NONE: Self = Self(0);
|
||||
|
||||
/// Not writable. Corresponds to
|
||||
/// `Object.defineProperty(o, "p", { writable: false })`.
|
||||
pub const READ_ONLY: Self = Self(1 << 0);
|
||||
|
||||
/// Not enumerable. Corresponds to
|
||||
/// `Object.defineProperty(o, "p", { enumerable: false })`.
|
||||
pub const DONT_ENUM: Self = Self(1 << 1);
|
||||
|
||||
/// Not configurable. Corresponds to
|
||||
/// `Object.defineProperty(o, "p", { configurable: false })`.
|
||||
pub const DONT_DELETE: Self = Self(1 << 2);
|
||||
|
||||
/// Test if no property attributes are set.
|
||||
#[inline(always)]
|
||||
pub fn is_none(&self) -> bool {
|
||||
*self == NONE
|
||||
*self == PropertyAttribute::NONE
|
||||
}
|
||||
|
||||
/// Test if the read-only property attribute is set.
|
||||
#[inline(always)]
|
||||
pub fn is_read_only(&self) -> bool {
|
||||
self.has(READ_ONLY)
|
||||
self.has(Self::READ_ONLY)
|
||||
}
|
||||
|
||||
/// Test if the non-enumerable property attribute is set.
|
||||
#[inline(always)]
|
||||
pub fn is_dont_enum(&self) -> bool {
|
||||
self.has(DONT_ENUM)
|
||||
self.has(Self::DONT_ENUM)
|
||||
}
|
||||
|
||||
/// Test if the non-configurable property attribute is set.
|
||||
#[inline(always)]
|
||||
pub fn is_dont_delete(&self) -> bool {
|
||||
self.has(DONT_DELETE)
|
||||
self.has(Self::DONT_DELETE)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@ -58,7 +58,7 @@ impl PropertyAttribute {
|
||||
// Identical to #[derive(Default)] but arguably clearer when made explicit.
|
||||
impl Default for PropertyAttribute {
|
||||
fn default() -> Self {
|
||||
NONE
|
||||
Self::NONE
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,36 +73,41 @@ impl std::ops::BitOr for PropertyAttribute {
|
||||
|
||||
#[test]
|
||||
fn test_attr() {
|
||||
assert!(NONE.is_none());
|
||||
assert!(!NONE.is_read_only());
|
||||
assert!(!NONE.is_dont_enum());
|
||||
assert!(!NONE.is_dont_delete());
|
||||
assert!(PropertyAttribute::NONE.is_none());
|
||||
assert!(!PropertyAttribute::NONE.is_read_only());
|
||||
assert!(!PropertyAttribute::NONE.is_dont_enum());
|
||||
assert!(!PropertyAttribute::NONE.is_dont_delete());
|
||||
|
||||
assert!(!READ_ONLY.is_none());
|
||||
assert!(READ_ONLY.is_read_only());
|
||||
assert!(!READ_ONLY.is_dont_enum());
|
||||
assert!(!READ_ONLY.is_dont_delete());
|
||||
assert!(!PropertyAttribute::READ_ONLY.is_none());
|
||||
assert!(PropertyAttribute::READ_ONLY.is_read_only());
|
||||
assert!(!PropertyAttribute::READ_ONLY.is_dont_enum());
|
||||
assert!(!PropertyAttribute::READ_ONLY.is_dont_delete());
|
||||
|
||||
assert!(!DONT_ENUM.is_none());
|
||||
assert!(!DONT_ENUM.is_read_only());
|
||||
assert!(DONT_ENUM.is_dont_enum());
|
||||
assert!(!DONT_ENUM.is_dont_delete());
|
||||
assert!(!PropertyAttribute::DONT_ENUM.is_none());
|
||||
assert!(!PropertyAttribute::DONT_ENUM.is_read_only());
|
||||
assert!(PropertyAttribute::DONT_ENUM.is_dont_enum());
|
||||
assert!(!PropertyAttribute::DONT_ENUM.is_dont_delete());
|
||||
|
||||
assert!(!DONT_DELETE.is_none());
|
||||
assert!(!DONT_DELETE.is_read_only());
|
||||
assert!(!DONT_DELETE.is_dont_enum());
|
||||
assert!(DONT_DELETE.is_dont_delete());
|
||||
assert!(!PropertyAttribute::DONT_DELETE.is_none());
|
||||
assert!(!PropertyAttribute::DONT_DELETE.is_read_only());
|
||||
assert!(!PropertyAttribute::DONT_DELETE.is_dont_enum());
|
||||
assert!(PropertyAttribute::DONT_DELETE.is_dont_delete());
|
||||
|
||||
assert_eq!(NONE, Default::default());
|
||||
assert_eq!(READ_ONLY, NONE | READ_ONLY);
|
||||
assert_eq!(PropertyAttribute::NONE, Default::default());
|
||||
assert_eq!(
|
||||
PropertyAttribute::READ_ONLY,
|
||||
PropertyAttribute::NONE | PropertyAttribute::READ_ONLY
|
||||
);
|
||||
|
||||
let attr = READ_ONLY | DONT_ENUM;
|
||||
let attr = PropertyAttribute::READ_ONLY | PropertyAttribute::DONT_ENUM;
|
||||
assert!(!attr.is_none());
|
||||
assert!(attr.is_read_only());
|
||||
assert!(attr.is_dont_enum());
|
||||
assert!(!attr.is_dont_delete());
|
||||
|
||||
let attr = READ_ONLY | READ_ONLY | DONT_ENUM;
|
||||
let attr = PropertyAttribute::READ_ONLY
|
||||
| PropertyAttribute::READ_ONLY
|
||||
| PropertyAttribute::DONT_ENUM;
|
||||
assert!(!attr.is_none());
|
||||
assert!(attr.is_read_only());
|
||||
assert!(attr.is_dont_enum());
|
||||
|
@ -21,6 +21,35 @@ extern "C" {
|
||||
set: *const Value,
|
||||
);
|
||||
fn v8__PropertyDescriptor__DESTRUCT(this: *mut PropertyDescriptor);
|
||||
fn v8__PropertyDescriptor__configurable(
|
||||
this: *const PropertyDescriptor,
|
||||
) -> bool;
|
||||
fn v8__PropertyDescriptor__enumerable(
|
||||
this: *const PropertyDescriptor,
|
||||
) -> bool;
|
||||
fn v8__PropertyDescriptor__writable(this: *const PropertyDescriptor) -> bool;
|
||||
fn v8__PropertyDescriptor__value(
|
||||
this: *const PropertyDescriptor,
|
||||
) -> *const Value;
|
||||
fn v8__PropertyDescriptor__get(
|
||||
this: *const PropertyDescriptor,
|
||||
) -> *const Value;
|
||||
fn v8__PropertyDescriptor__set(
|
||||
this: *const PropertyDescriptor,
|
||||
) -> *const Value;
|
||||
fn v8__PropertyDescriptor__has_configurable(
|
||||
this: *const PropertyDescriptor,
|
||||
) -> bool;
|
||||
fn v8__PropertyDescriptor__has_enumerable(
|
||||
this: *const PropertyDescriptor,
|
||||
) -> bool;
|
||||
fn v8__PropertyDescriptor__has_writable(
|
||||
this: *const PropertyDescriptor,
|
||||
) -> bool;
|
||||
fn v8__PropertyDescriptor__has_value(this: *const PropertyDescriptor)
|
||||
-> bool;
|
||||
fn v8__PropertyDescriptor__has_get(this: *const PropertyDescriptor) -> bool;
|
||||
fn v8__PropertyDescriptor__has_set(this: *const PropertyDescriptor) -> bool;
|
||||
fn v8__PropertyDescriptor__set_enumerable(
|
||||
this: *mut PropertyDescriptor,
|
||||
enumerable: bool,
|
||||
@ -88,6 +117,54 @@ impl PropertyDescriptor {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn configurable(&self) -> bool {
|
||||
unsafe { v8__PropertyDescriptor__configurable(self) }
|
||||
}
|
||||
|
||||
pub fn enumerable(&self) -> bool {
|
||||
unsafe { v8__PropertyDescriptor__enumerable(self) }
|
||||
}
|
||||
|
||||
pub fn writable(&self) -> bool {
|
||||
unsafe { v8__PropertyDescriptor__writable(self) }
|
||||
}
|
||||
|
||||
pub fn value(&self) -> Local<Value> {
|
||||
unsafe { Local::from_raw(v8__PropertyDescriptor__value(self)) }.unwrap()
|
||||
}
|
||||
|
||||
pub fn get(&self) -> Local<Value> {
|
||||
unsafe { Local::from_raw(v8__PropertyDescriptor__get(self)) }.unwrap()
|
||||
}
|
||||
|
||||
pub fn set(&self) -> Local<Value> {
|
||||
unsafe { Local::from_raw(v8__PropertyDescriptor__set(self)) }.unwrap()
|
||||
}
|
||||
|
||||
pub fn has_configurable(&self) -> bool {
|
||||
unsafe { v8__PropertyDescriptor__has_configurable(self) }
|
||||
}
|
||||
|
||||
pub fn has_enumerable(&self) -> bool {
|
||||
unsafe { v8__PropertyDescriptor__has_enumerable(self) }
|
||||
}
|
||||
|
||||
pub fn has_writable(&self) -> bool {
|
||||
unsafe { v8__PropertyDescriptor__has_writable(self) }
|
||||
}
|
||||
|
||||
pub fn has_value(&self) -> bool {
|
||||
unsafe { v8__PropertyDescriptor__has_value(self) }
|
||||
}
|
||||
|
||||
pub fn has_get(&self) -> bool {
|
||||
unsafe { v8__PropertyDescriptor__has_get(self) }
|
||||
}
|
||||
|
||||
pub fn has_set(&self) -> bool {
|
||||
unsafe { v8__PropertyDescriptor__has_set(self) }
|
||||
}
|
||||
|
||||
pub fn set_enumerable(&mut self, enumerable: bool) {
|
||||
unsafe { v8__PropertyDescriptor__set_enumerable(self, enumerable) }
|
||||
}
|
||||
|
@ -2,53 +2,53 @@
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||
pub struct PropertyFilter(u32);
|
||||
|
||||
pub const ALL_PROPERTIES: PropertyFilter = PropertyFilter(0);
|
||||
|
||||
pub const ONLY_WRITABLE: PropertyFilter = PropertyFilter(1);
|
||||
|
||||
pub const ONLY_ENUMERABLE: PropertyFilter = PropertyFilter(2);
|
||||
|
||||
pub const ONLY_CONFIGURABLE: PropertyFilter = PropertyFilter(4);
|
||||
|
||||
pub const SKIP_STRINGS: PropertyFilter = PropertyFilter(8);
|
||||
|
||||
pub const SKIP_SYMBOLS: PropertyFilter = PropertyFilter(16);
|
||||
|
||||
impl PropertyFilter {
|
||||
pub const ALL_PROPERTIES: PropertyFilter = PropertyFilter(0);
|
||||
|
||||
pub const ONLY_WRITABLE: PropertyFilter = PropertyFilter(1 << 0);
|
||||
|
||||
pub const ONLY_ENUMERABLE: PropertyFilter = PropertyFilter(1 << 1);
|
||||
|
||||
pub const ONLY_CONFIGURABLE: PropertyFilter = PropertyFilter(1 << 2);
|
||||
|
||||
pub const SKIP_STRINGS: PropertyFilter = PropertyFilter(1 << 3);
|
||||
|
||||
pub const SKIP_SYMBOLS: PropertyFilter = PropertyFilter(1 << 4);
|
||||
|
||||
/// Test if all property filters are set.
|
||||
#[inline(always)]
|
||||
pub fn is_all_properties(&self) -> bool {
|
||||
*self == ALL_PROPERTIES
|
||||
*self == Self::ALL_PROPERTIES
|
||||
}
|
||||
|
||||
/// Test if the only-writable property filter is set.
|
||||
#[inline(always)]
|
||||
pub fn is_only_writable(&self) -> bool {
|
||||
self.has(ONLY_WRITABLE)
|
||||
self.has(Self::ONLY_WRITABLE)
|
||||
}
|
||||
|
||||
/// Test if the only-enumerable property filter is set.
|
||||
#[inline(always)]
|
||||
pub fn is_only_enumerable(&self) -> bool {
|
||||
self.has(ONLY_ENUMERABLE)
|
||||
self.has(Self::ONLY_ENUMERABLE)
|
||||
}
|
||||
|
||||
/// Test if the only-configurable property filter is set.
|
||||
#[inline(always)]
|
||||
pub fn is_only_configurable(&self) -> bool {
|
||||
self.has(ONLY_CONFIGURABLE)
|
||||
self.has(Self::ONLY_CONFIGURABLE)
|
||||
}
|
||||
|
||||
/// Test if the skip-strings property filter is set.
|
||||
#[inline(always)]
|
||||
pub fn is_skip_strings(&self) -> bool {
|
||||
self.has(SKIP_STRINGS)
|
||||
self.has(Self::SKIP_STRINGS)
|
||||
}
|
||||
|
||||
/// Test if the skip-symbols property filter is set.
|
||||
#[inline(always)]
|
||||
pub fn is_skip_symbols(&self) -> bool {
|
||||
self.has(SKIP_SYMBOLS)
|
||||
self.has(Self::SKIP_SYMBOLS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@ -62,7 +62,7 @@ impl PropertyFilter {
|
||||
// Identical to #[derive(Default)] but arguably clearer when made explicit.
|
||||
impl Default for PropertyFilter {
|
||||
fn default() -> Self {
|
||||
ALL_PROPERTIES
|
||||
Self::ALL_PROPERTIES
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,52 +77,57 @@ impl std::ops::BitOr for PropertyFilter {
|
||||
|
||||
#[test]
|
||||
fn test_attr() {
|
||||
assert!(ALL_PROPERTIES.is_all_properties());
|
||||
assert!(!ALL_PROPERTIES.is_only_writable());
|
||||
assert!(!ALL_PROPERTIES.is_only_enumerable());
|
||||
assert!(!ALL_PROPERTIES.is_only_configurable());
|
||||
assert!(!ALL_PROPERTIES.is_skip_strings());
|
||||
assert!(!ALL_PROPERTIES.is_skip_symbols());
|
||||
assert!(PropertyFilter::ALL_PROPERTIES.is_all_properties());
|
||||
assert!(!PropertyFilter::ALL_PROPERTIES.is_only_writable());
|
||||
assert!(!PropertyFilter::ALL_PROPERTIES.is_only_enumerable());
|
||||
assert!(!PropertyFilter::ALL_PROPERTIES.is_only_configurable());
|
||||
assert!(!PropertyFilter::ALL_PROPERTIES.is_skip_strings());
|
||||
assert!(!PropertyFilter::ALL_PROPERTIES.is_skip_symbols());
|
||||
|
||||
assert!(!ONLY_WRITABLE.is_all_properties());
|
||||
assert!(ONLY_WRITABLE.is_only_writable());
|
||||
assert!(!ONLY_WRITABLE.is_only_enumerable());
|
||||
assert!(!ONLY_WRITABLE.is_only_configurable());
|
||||
assert!(!ONLY_WRITABLE.is_skip_strings());
|
||||
assert!(!ONLY_WRITABLE.is_skip_symbols());
|
||||
assert!(!PropertyFilter::ONLY_WRITABLE.is_all_properties());
|
||||
assert!(PropertyFilter::ONLY_WRITABLE.is_only_writable());
|
||||
assert!(!PropertyFilter::ONLY_WRITABLE.is_only_enumerable());
|
||||
assert!(!PropertyFilter::ONLY_WRITABLE.is_only_configurable());
|
||||
assert!(!PropertyFilter::ONLY_WRITABLE.is_skip_strings());
|
||||
assert!(!PropertyFilter::ONLY_WRITABLE.is_skip_symbols());
|
||||
|
||||
assert!(!ONLY_ENUMERABLE.is_all_properties());
|
||||
assert!(!ONLY_ENUMERABLE.is_only_writable());
|
||||
assert!(ONLY_ENUMERABLE.is_only_enumerable());
|
||||
assert!(!ONLY_ENUMERABLE.is_only_configurable());
|
||||
assert!(!ONLY_ENUMERABLE.is_skip_strings());
|
||||
assert!(!ONLY_ENUMERABLE.is_skip_symbols());
|
||||
assert!(!PropertyFilter::ONLY_ENUMERABLE.is_all_properties());
|
||||
assert!(!PropertyFilter::ONLY_ENUMERABLE.is_only_writable());
|
||||
assert!(PropertyFilter::ONLY_ENUMERABLE.is_only_enumerable());
|
||||
assert!(!PropertyFilter::ONLY_ENUMERABLE.is_only_configurable());
|
||||
assert!(!PropertyFilter::ONLY_ENUMERABLE.is_skip_strings());
|
||||
assert!(!PropertyFilter::ONLY_ENUMERABLE.is_skip_symbols());
|
||||
|
||||
assert!(!ONLY_CONFIGURABLE.is_all_properties());
|
||||
assert!(!ONLY_CONFIGURABLE.is_only_writable());
|
||||
assert!(!ONLY_CONFIGURABLE.is_only_enumerable());
|
||||
assert!(ONLY_CONFIGURABLE.is_only_configurable());
|
||||
assert!(!ONLY_CONFIGURABLE.is_skip_strings());
|
||||
assert!(!ONLY_CONFIGURABLE.is_skip_symbols());
|
||||
assert!(!PropertyFilter::ONLY_CONFIGURABLE.is_all_properties());
|
||||
assert!(!PropertyFilter::ONLY_CONFIGURABLE.is_only_writable());
|
||||
assert!(!PropertyFilter::ONLY_CONFIGURABLE.is_only_enumerable());
|
||||
assert!(PropertyFilter::ONLY_CONFIGURABLE.is_only_configurable());
|
||||
assert!(!PropertyFilter::ONLY_CONFIGURABLE.is_skip_strings());
|
||||
assert!(!PropertyFilter::ONLY_CONFIGURABLE.is_skip_symbols());
|
||||
|
||||
assert!(!SKIP_STRINGS.is_all_properties());
|
||||
assert!(!SKIP_STRINGS.is_only_writable());
|
||||
assert!(!SKIP_STRINGS.is_only_enumerable());
|
||||
assert!(!SKIP_STRINGS.is_only_configurable());
|
||||
assert!(SKIP_STRINGS.is_skip_strings());
|
||||
assert!(!SKIP_STRINGS.is_skip_symbols());
|
||||
assert!(!PropertyFilter::SKIP_STRINGS.is_all_properties());
|
||||
assert!(!PropertyFilter::SKIP_STRINGS.is_only_writable());
|
||||
assert!(!PropertyFilter::SKIP_STRINGS.is_only_enumerable());
|
||||
assert!(!PropertyFilter::SKIP_STRINGS.is_only_configurable());
|
||||
assert!(PropertyFilter::SKIP_STRINGS.is_skip_strings());
|
||||
assert!(!PropertyFilter::SKIP_STRINGS.is_skip_symbols());
|
||||
|
||||
assert!(!SKIP_SYMBOLS.is_all_properties());
|
||||
assert!(!SKIP_SYMBOLS.is_only_writable());
|
||||
assert!(!SKIP_SYMBOLS.is_only_enumerable());
|
||||
assert!(!SKIP_SYMBOLS.is_only_configurable());
|
||||
assert!(!SKIP_SYMBOLS.is_skip_strings());
|
||||
assert!(SKIP_SYMBOLS.is_skip_symbols());
|
||||
assert!(!PropertyFilter::SKIP_SYMBOLS.is_all_properties());
|
||||
assert!(!PropertyFilter::SKIP_SYMBOLS.is_only_writable());
|
||||
assert!(!PropertyFilter::SKIP_SYMBOLS.is_only_enumerable());
|
||||
assert!(!PropertyFilter::SKIP_SYMBOLS.is_only_configurable());
|
||||
assert!(!PropertyFilter::SKIP_SYMBOLS.is_skip_strings());
|
||||
assert!(PropertyFilter::SKIP_SYMBOLS.is_skip_symbols());
|
||||
|
||||
assert_eq!(ALL_PROPERTIES, Default::default());
|
||||
assert_eq!(ONLY_WRITABLE, ALL_PROPERTIES | ONLY_WRITABLE);
|
||||
assert_eq!(PropertyFilter::ALL_PROPERTIES, Default::default());
|
||||
assert_eq!(
|
||||
PropertyFilter::ONLY_WRITABLE,
|
||||
PropertyFilter::ALL_PROPERTIES | PropertyFilter::ONLY_WRITABLE
|
||||
);
|
||||
|
||||
let attr = ONLY_WRITABLE | ONLY_WRITABLE | SKIP_STRINGS;
|
||||
let attr = PropertyFilter::ONLY_WRITABLE
|
||||
| PropertyFilter::ONLY_WRITABLE
|
||||
| PropertyFilter::SKIP_STRINGS;
|
||||
assert!(!attr.is_all_properties());
|
||||
assert!(attr.is_only_writable());
|
||||
assert!(!attr.is_only_enumerable());
|
||||
|
136
src/property_handler_flags.rs
Normal file
136
src/property_handler_flags.rs
Normal file
@ -0,0 +1,136 @@
|
||||
// Copyright 2019-2021 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct PropertyHandlerFlags(u32);
|
||||
|
||||
impl PropertyHandlerFlags {
|
||||
/// None.
|
||||
pub const NONE: Self = Self(0);
|
||||
|
||||
/// See ALL_CAN_READ above.
|
||||
pub const ALL_CAN_READ: Self = Self(1 << 0);
|
||||
|
||||
/// Will not call into interceptor for properties on the receiver or prototype
|
||||
/// chain, i.e., only call into interceptor for properties that do not exist.
|
||||
/// Currently only valid for named interceptors.
|
||||
pub const NON_MASKING: Self = Self(1 << 1);
|
||||
|
||||
/// Will not call into interceptor for symbol lookup. Only meaningful for
|
||||
/// named interceptors.
|
||||
pub const ONLY_INTERCEPT_STRINGS: Self = Self(1 << 2);
|
||||
|
||||
/// The getter, query, enumerator callbacks do not produce side effects.
|
||||
pub const HAS_NO_SIDE_EFFECT: Self = Self(1 << 3);
|
||||
|
||||
/// Test if no property handler flags are set.
|
||||
#[inline(always)]
|
||||
pub fn is_none(&self) -> bool {
|
||||
*self == Self::NONE
|
||||
}
|
||||
|
||||
/// Test if the all-can-read property handler flag is set.
|
||||
#[inline(always)]
|
||||
pub fn is_all_can_read(&self) -> bool {
|
||||
self.has(Self::ALL_CAN_READ)
|
||||
}
|
||||
|
||||
/// Test if the non-masking property handler flag is set.
|
||||
#[inline(always)]
|
||||
pub fn is_non_masking(&self) -> bool {
|
||||
self.has(Self::NON_MASKING)
|
||||
}
|
||||
|
||||
/// Test if the only-intercept-strings property handler flag is set.
|
||||
#[inline(always)]
|
||||
pub fn is_only_intercept_strings(&self) -> bool {
|
||||
self.has(Self::ONLY_INTERCEPT_STRINGS)
|
||||
}
|
||||
|
||||
/// Test if the has-no-side-effect property handler flag is set.
|
||||
#[inline(always)]
|
||||
pub fn is_has_no_side_effect(&self) -> bool {
|
||||
self.has(Self::HAS_NO_SIDE_EFFECT)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn has(&self, that: Self) -> bool {
|
||||
let Self(lhs) = self;
|
||||
let Self(rhs) = that;
|
||||
0 != lhs & rhs
|
||||
}
|
||||
}
|
||||
|
||||
// Identical to #[derive(Default)] but arguably clearer when made explicit.
|
||||
impl Default for PropertyHandlerFlags {
|
||||
fn default() -> Self {
|
||||
Self::NONE
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::BitOr for PropertyHandlerFlags {
|
||||
type Output = Self;
|
||||
|
||||
fn bitor(self, Self(rhs): Self) -> Self {
|
||||
let Self(lhs) = self;
|
||||
Self(lhs | rhs)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_attr() {
|
||||
assert!(PropertyHandlerFlags::NONE.is_none());
|
||||
assert!(!PropertyHandlerFlags::NONE.is_all_can_read());
|
||||
assert!(!PropertyHandlerFlags::NONE.is_non_masking());
|
||||
assert!(!PropertyHandlerFlags::NONE.is_only_intercept_strings());
|
||||
assert!(!PropertyHandlerFlags::NONE.is_has_no_side_effect());
|
||||
|
||||
assert!(!PropertyHandlerFlags::ALL_CAN_READ.is_none());
|
||||
assert!(PropertyHandlerFlags::ALL_CAN_READ.is_all_can_read());
|
||||
assert!(!PropertyHandlerFlags::ALL_CAN_READ.is_non_masking());
|
||||
assert!(!PropertyHandlerFlags::ALL_CAN_READ.is_only_intercept_strings());
|
||||
assert!(!PropertyHandlerFlags::ALL_CAN_READ.is_has_no_side_effect());
|
||||
|
||||
assert!(!PropertyHandlerFlags::NON_MASKING.is_none());
|
||||
assert!(!PropertyHandlerFlags::NON_MASKING.is_all_can_read());
|
||||
assert!(PropertyHandlerFlags::NON_MASKING.is_non_masking());
|
||||
assert!(!PropertyHandlerFlags::NON_MASKING.is_only_intercept_strings());
|
||||
assert!(!PropertyHandlerFlags::NON_MASKING.is_has_no_side_effect());
|
||||
|
||||
assert!(!PropertyHandlerFlags::ONLY_INTERCEPT_STRINGS.is_none());
|
||||
assert!(!PropertyHandlerFlags::ONLY_INTERCEPT_STRINGS.is_all_can_read());
|
||||
assert!(!PropertyHandlerFlags::ONLY_INTERCEPT_STRINGS.is_non_masking());
|
||||
assert!(
|
||||
PropertyHandlerFlags::ONLY_INTERCEPT_STRINGS.is_only_intercept_strings()
|
||||
);
|
||||
assert!(!PropertyHandlerFlags::ONLY_INTERCEPT_STRINGS.is_has_no_side_effect());
|
||||
|
||||
assert!(!PropertyHandlerFlags::HAS_NO_SIDE_EFFECT.is_none());
|
||||
assert!(!PropertyHandlerFlags::HAS_NO_SIDE_EFFECT.is_all_can_read());
|
||||
assert!(!PropertyHandlerFlags::HAS_NO_SIDE_EFFECT.is_non_masking());
|
||||
assert!(!PropertyHandlerFlags::HAS_NO_SIDE_EFFECT.is_only_intercept_strings());
|
||||
assert!(PropertyHandlerFlags::HAS_NO_SIDE_EFFECT.is_has_no_side_effect());
|
||||
|
||||
assert_eq!(PropertyHandlerFlags::NONE, Default::default());
|
||||
assert_eq!(
|
||||
PropertyHandlerFlags::ALL_CAN_READ,
|
||||
PropertyHandlerFlags::NONE | PropertyHandlerFlags::ALL_CAN_READ
|
||||
);
|
||||
|
||||
let attr =
|
||||
PropertyHandlerFlags::ALL_CAN_READ | PropertyHandlerFlags::NON_MASKING;
|
||||
assert!(!attr.is_none());
|
||||
assert!(attr.is_all_can_read());
|
||||
assert!(attr.is_non_masking());
|
||||
assert!(!attr.is_only_intercept_strings());
|
||||
assert!(!attr.is_has_no_side_effect());
|
||||
|
||||
let attr = PropertyHandlerFlags::ONLY_INTERCEPT_STRINGS
|
||||
| PropertyHandlerFlags::HAS_NO_SIDE_EFFECT
|
||||
| PropertyHandlerFlags::NON_MASKING;
|
||||
assert!(!attr.is_none());
|
||||
assert!(!attr.is_all_can_read());
|
||||
assert!(attr.is_non_masking());
|
||||
assert!(attr.is_only_intercept_strings());
|
||||
assert!(attr.is_has_no_side_effect());
|
||||
}
|
244
src/template.rs
244
src/template.rs
@ -9,25 +9,27 @@ use crate::fast_api::FastFunction;
|
||||
use crate::isolate::Isolate;
|
||||
use crate::support::int;
|
||||
use crate::support::MapFnTo;
|
||||
use crate::AccessorNameGetterCallback;
|
||||
use crate::AccessorNameSetterCallback;
|
||||
use crate::ConstructorBehavior;
|
||||
use crate::Context;
|
||||
use crate::Function;
|
||||
use crate::FunctionBuilder;
|
||||
use crate::FunctionCallback;
|
||||
use crate::HandleScope;
|
||||
use crate::IndexedPropertyGetterCallback;
|
||||
use crate::IndexedPropertySetterCallback;
|
||||
use crate::IndexedDefinerCallback;
|
||||
use crate::IndexedGetterCallback;
|
||||
use crate::IndexedSetterCallback;
|
||||
use crate::Local;
|
||||
use crate::NamedDefinerCallback;
|
||||
use crate::NamedGetterCallback;
|
||||
use crate::NamedSetterCallback;
|
||||
use crate::Object;
|
||||
use crate::PropertyAttribute;
|
||||
use crate::PropertyEnumeratorCallback;
|
||||
use crate::PropertyHandlerFlags;
|
||||
use crate::SideEffectType;
|
||||
use crate::Signature;
|
||||
use crate::String;
|
||||
use crate::Value;
|
||||
use crate::NONE;
|
||||
use std::convert::TryFrom;
|
||||
use std::ffi::c_void;
|
||||
use std::ptr::null;
|
||||
@ -110,29 +112,143 @@ extern "C" {
|
||||
|
||||
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>,
|
||||
getter: Option<GenericNamedPropertyGetterCallback>,
|
||||
setter: Option<GenericNamedPropertySetterCallback>,
|
||||
query: Option<GenericNamedPropertyQueryCallback>,
|
||||
deleter: Option<GenericNamedPropertyDeleterCallback>,
|
||||
enumerator: Option<GenericNamedPropertyEnumeratorCallback>,
|
||||
definer: Option<GenericNamedPropertyDefinerCallback>,
|
||||
descriptor: Option<GenericNamedPropertyDescriptorCallback>,
|
||||
data_or_null: *const Value,
|
||||
flags: PropertyHandlerFlags,
|
||||
);
|
||||
|
||||
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>,
|
||||
query: Option<IndexedPropertyQueryCallback>,
|
||||
deleter: Option<IndexedPropertyDeleterCallback>,
|
||||
enumerator: Option<IndexedPropertyEnumeratorCallback>,
|
||||
definer: Option<IndexedPropertyDefinerCallback>,
|
||||
descriptor: Option<IndexedPropertyDescriptorCallback>,
|
||||
data_or_null: *const Value,
|
||||
);
|
||||
|
||||
fn v8__ObjectTemplate__SetImmutableProto(this: *const ObjectTemplate);
|
||||
}
|
||||
|
||||
pub type AccessorNameGetterCallback<'s> = NamedGetterCallback<'s>;
|
||||
|
||||
/// Note: [ReturnValue] is ignored for accessors.
|
||||
pub type AccessorNameSetterCallback<'s> = NamedSetterCallback<'s>;
|
||||
|
||||
/// Interceptor for get requests on an object.
|
||||
///
|
||||
/// Use [ReturnValue] to set the return value of the intercepted get request. If
|
||||
/// the property does not exist the callback should not set the result and must
|
||||
/// not produce side effects.
|
||||
///
|
||||
/// See also [ObjectTemplate::set_handler].
|
||||
pub type GenericNamedPropertyGetterCallback<'s> = NamedGetterCallback<'s>;
|
||||
|
||||
/// Interceptor for set requests on an object.
|
||||
///
|
||||
/// Use [ReturnValue] to indicate whether the request was intercepted or not. If
|
||||
/// the setter successfully intercepts the request, i.e., if the request should
|
||||
/// not be further executed, call [ReturnValue::set]. If the setter did not
|
||||
/// intercept the request, i.e., if the request should be handled as if no
|
||||
/// interceptor is present, do not not call set() and do not produce side
|
||||
/// effects.
|
||||
///
|
||||
/// See also [ObjectTemplate::set_named_property_handler].
|
||||
pub type GenericNamedPropertySetterCallback<'s> = NamedSetterCallback<'s>;
|
||||
|
||||
/// Intercepts all requests that query the attributes of the property, e.g.,
|
||||
/// getOwnPropertyDescriptor(), propertyIsEnumerable(), and defineProperty().
|
||||
///
|
||||
/// Use [ReturnValue::set] to set the property attributes. The value is an
|
||||
/// integer encoding a [PropertyAttribute]. If the property does not exist the
|
||||
/// callback should not set the result and must not produce side effects.
|
||||
///
|
||||
/// Note: Some functions query the property attributes internally, even though
|
||||
/// they do not return the attributes. For example, hasOwnProperty() can trigger
|
||||
/// this interceptor depending on the state of the object.
|
||||
///
|
||||
/// See also [ObjectTemplate::set_named_property_handler].
|
||||
pub type GenericNamedPropertyQueryCallback<'s> = NamedGetterCallback<'s>;
|
||||
|
||||
/// Interceptor for delete requests on an object.
|
||||
///
|
||||
/// Use [ReturnValue] 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 [ReturnValue::set] with a boolean value. The
|
||||
/// value is used as the return value of delete. If the deleter does not
|
||||
/// intercept the request then it should not set the result and must not produce
|
||||
/// side effects.
|
||||
///
|
||||
/// Note: If you need to mimic the behavior of delete, i.e., throw in strict
|
||||
/// mode instead of returning false, use
|
||||
/// [PropertyCallbackArguments::should_throw_on_error] to determine if you are
|
||||
/// in strict mode.
|
||||
///
|
||||
/// See also [ObjectTemplate::set_named_property_handler].
|
||||
pub type GenericNamedPropertyDeleterCallback<'s> = NamedGetterCallback<'s>;
|
||||
|
||||
/// Returns an array containing the names of the properties the named property getter intercepts.
|
||||
///
|
||||
/// Note: The values in the array must be of type v8::Name.
|
||||
///
|
||||
/// See also [ObjectTemplate::set_named_property_handler].
|
||||
pub type GenericNamedPropertyEnumeratorCallback<'s> =
|
||||
PropertyEnumeratorCallback<'s>;
|
||||
|
||||
/// Interceptor for defineProperty requests on an object.
|
||||
///
|
||||
/// Use [ReturnValue] to indicate whether the request was intercepted or not. If
|
||||
/// the definer successfully intercepts the request, i.e., if the request should
|
||||
/// not be further executed, call [ReturnValue::set]. If the definer did not
|
||||
/// intercept the request, i.e., if the request should be handled as if no
|
||||
/// interceptor is present, do not not call set() and do not produce side
|
||||
/// effects.
|
||||
///
|
||||
/// See also [ObjectTemplate::set_named_property_handler].
|
||||
pub type GenericNamedPropertyDefinerCallback<'s> = NamedDefinerCallback<'s>;
|
||||
|
||||
/// Interceptor for getOwnPropertyDescriptor requests on an object.
|
||||
///
|
||||
/// Use [ReturnValue::set] to set the return value of the intercepted request.
|
||||
/// The return value must be an object that can be converted to a
|
||||
/// [PropertyDescriptor], e.g., a [Value] returned from
|
||||
/// `Object.getOwnPropertyDescriptor()`.
|
||||
///
|
||||
/// Note: If GetOwnPropertyDescriptor is intercepted, it will always return
|
||||
/// true, i.e., indicate that the property was found.
|
||||
///
|
||||
/// See also [ObjectTemplate::set_named_property_handler].
|
||||
pub type GenericNamedPropertyDescriptorCallback<'s> = NamedGetterCallback<'s>;
|
||||
|
||||
/// See [GenericNamedPropertyGetterCallback].
|
||||
pub type IndexedPropertyGetterCallback<'s> = IndexedGetterCallback<'s>;
|
||||
|
||||
/// See [GenericNamedPropertySetterCallback].
|
||||
pub type IndexedPropertySetterCallback<'s> = IndexedSetterCallback<'s>;
|
||||
|
||||
/// See [GenericNamedPropertyQueryCallback].
|
||||
pub type IndexedPropertyQueryCallback<'s> = IndexedGetterCallback<'s>;
|
||||
|
||||
/// See [GenericNamedPropertyDeleterCallback].
|
||||
pub type IndexedPropertyDeleterCallback<'s> = IndexedGetterCallback<'s>;
|
||||
|
||||
/// See [GenericNamedPropertyEnumeratorCallback].
|
||||
pub type IndexedPropertyEnumeratorCallback<'s> = PropertyEnumeratorCallback<'s>;
|
||||
|
||||
/// See [GenericNamedPropertyDefinerCallback].
|
||||
pub type IndexedPropertyDefinerCallback<'s> = IndexedDefinerCallback<'s>;
|
||||
|
||||
/// See [GenericNamedPropertyDescriptorCallback].
|
||||
pub type IndexedPropertyDescriptorCallback<'s> = IndexedGetterCallback<'s>;
|
||||
|
||||
pub struct AccessorConfiguration<'s> {
|
||||
pub(crate) getter: AccessorNameGetterCallback<'s>,
|
||||
pub(crate) setter: Option<AccessorNameSetterCallback<'s>>,
|
||||
@ -146,7 +262,7 @@ impl<'s> AccessorConfiguration<'s> {
|
||||
getter: getter.map_fn_to(),
|
||||
setter: None,
|
||||
data: None,
|
||||
property_attribute: NONE,
|
||||
property_attribute: PropertyAttribute::NONE,
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,13 +291,15 @@ impl<'s> AccessorConfiguration<'s> {
|
||||
|
||||
#[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) getter: Option<GenericNamedPropertyGetterCallback<'s>>,
|
||||
pub(crate) setter: Option<GenericNamedPropertySetterCallback<'s>>,
|
||||
pub(crate) query: Option<GenericNamedPropertyQueryCallback<'s>>,
|
||||
pub(crate) deleter: Option<GenericNamedPropertyDeleterCallback<'s>>,
|
||||
pub(crate) enumerator: Option<GenericNamedPropertyEnumeratorCallback<'s>>,
|
||||
pub(crate) definer: Option<GenericNamedPropertyDefinerCallback<'s>>,
|
||||
pub(crate) descriptor: Option<GenericNamedPropertyDescriptorCallback<'s>>,
|
||||
pub(crate) data: Option<Local<'s, Value>>,
|
||||
pub(crate) flags: PropertyHandlerFlags,
|
||||
}
|
||||
|
||||
impl<'s> NamedPropertyHandlerConfiguration<'s> {
|
||||
@ -192,8 +310,10 @@ impl<'s> NamedPropertyHandlerConfiguration<'s> {
|
||||
query: None,
|
||||
deleter: None,
|
||||
enumerator: None,
|
||||
definer: None,
|
||||
descriptor: None,
|
||||
data: None,
|
||||
flags: PropertyHandlerFlags::NONE,
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,12 +323,14 @@ impl<'s> NamedPropertyHandlerConfiguration<'s> {
|
||||
|| self.query.is_some()
|
||||
|| self.deleter.is_some()
|
||||
|| self.enumerator.is_some()
|
||||
|| self.definer.is_some()
|
||||
|| self.descriptor.is_some()
|
||||
|| !self.flags.is_none()
|
||||
}
|
||||
|
||||
pub fn getter(
|
||||
mut self,
|
||||
getter: impl MapFnTo<AccessorNameGetterCallback<'s>>,
|
||||
getter: impl MapFnTo<GenericNamedPropertyGetterCallback<'s>>,
|
||||
) -> Self {
|
||||
self.getter = Some(getter.map_fn_to());
|
||||
self
|
||||
@ -216,46 +338,47 @@ impl<'s> NamedPropertyHandlerConfiguration<'s> {
|
||||
|
||||
pub fn setter(
|
||||
mut self,
|
||||
setter: impl MapFnTo<AccessorNameSetterCallback<'s>>,
|
||||
setter: impl MapFnTo<GenericNamedPropertySetterCallback<'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>>,
|
||||
query: impl MapFnTo<GenericNamedPropertyQueryCallback<'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>>,
|
||||
deleter: impl MapFnTo<GenericNamedPropertyDeleterCallback<'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>>,
|
||||
enumerator: impl MapFnTo<GenericNamedPropertyEnumeratorCallback<'s>>,
|
||||
) -> Self {
|
||||
self.enumerator = Some(enumerator.map_fn_to());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn definer(
|
||||
mut self,
|
||||
definer: impl MapFnTo<GenericNamedPropertyDefinerCallback<'s>>,
|
||||
) -> Self {
|
||||
self.definer = Some(definer.map_fn_to());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn descriptor(
|
||||
mut self,
|
||||
descriptor: impl MapFnTo<AccessorNameGetterCallback<'s>>,
|
||||
descriptor: impl MapFnTo<GenericNamedPropertyDescriptorCallback<'s>>,
|
||||
) -> Self {
|
||||
self.descriptor = Some(descriptor.map_fn_to());
|
||||
self
|
||||
@ -266,17 +389,25 @@ impl<'s> NamedPropertyHandlerConfiguration<'s> {
|
||||
self.data = Some(data);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the property handler flags. The default is PropertyHandlerFlags::NONE.
|
||||
pub fn flags(mut self, flags: PropertyHandlerFlags) -> Self {
|
||||
self.flags = flags;
|
||||
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) query: Option<IndexedPropertyQueryCallback<'s>>,
|
||||
pub(crate) deleter: Option<IndexedPropertyDeleterCallback<'s>>,
|
||||
pub(crate) enumerator: Option<IndexedPropertyEnumeratorCallback<'s>>,
|
||||
pub(crate) definer: Option<IndexedPropertyDefinerCallback<'s>>,
|
||||
pub(crate) descriptor: Option<IndexedPropertyDescriptorCallback<'s>>,
|
||||
pub(crate) data: Option<Local<'s, Value>>,
|
||||
pub(crate) flags: PropertyHandlerFlags,
|
||||
}
|
||||
|
||||
impl<'s> IndexedPropertyHandlerConfiguration<'s> {
|
||||
@ -287,8 +418,10 @@ impl<'s> IndexedPropertyHandlerConfiguration<'s> {
|
||||
query: None,
|
||||
deleter: None,
|
||||
enumerator: None,
|
||||
definer: None,
|
||||
descriptor: None,
|
||||
data: None,
|
||||
flags: PropertyHandlerFlags::NONE,
|
||||
}
|
||||
}
|
||||
|
||||
@ -298,7 +431,9 @@ impl<'s> IndexedPropertyHandlerConfiguration<'s> {
|
||||
|| self.query.is_some()
|
||||
|| self.deleter.is_some()
|
||||
|| self.enumerator.is_some()
|
||||
|| self.definer.is_some()
|
||||
|| self.descriptor.is_some()
|
||||
|| !self.flags.is_none()
|
||||
}
|
||||
|
||||
pub fn getter(
|
||||
@ -319,7 +454,7 @@ impl<'s> IndexedPropertyHandlerConfiguration<'s> {
|
||||
|
||||
pub fn query(
|
||||
mut self,
|
||||
query: impl MapFnTo<IndexedPropertyGetterCallback<'s>>,
|
||||
query: impl MapFnTo<IndexedPropertyQueryCallback<'s>>,
|
||||
) -> Self {
|
||||
self.query = Some(query.map_fn_to());
|
||||
self
|
||||
@ -327,7 +462,7 @@ impl<'s> IndexedPropertyHandlerConfiguration<'s> {
|
||||
|
||||
pub fn deleter(
|
||||
mut self,
|
||||
deleter: impl MapFnTo<IndexedPropertyGetterCallback<'s>>,
|
||||
deleter: impl MapFnTo<IndexedPropertyDeleterCallback<'s>>,
|
||||
) -> Self {
|
||||
self.deleter = Some(deleter.map_fn_to());
|
||||
self
|
||||
@ -335,15 +470,23 @@ impl<'s> IndexedPropertyHandlerConfiguration<'s> {
|
||||
|
||||
pub fn enumerator(
|
||||
mut self,
|
||||
enumerator: impl MapFnTo<PropertyEnumeratorCallback<'s>>,
|
||||
enumerator: impl MapFnTo<IndexedPropertyEnumeratorCallback<'s>>,
|
||||
) -> Self {
|
||||
self.enumerator = Some(enumerator.map_fn_to());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn definer(
|
||||
mut self,
|
||||
definer: impl MapFnTo<IndexedPropertyDefinerCallback<'s>>,
|
||||
) -> Self {
|
||||
self.definer = Some(definer.map_fn_to());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn descriptor(
|
||||
mut self,
|
||||
descriptor: impl MapFnTo<IndexedPropertyGetterCallback<'s>>,
|
||||
descriptor: impl MapFnTo<IndexedPropertyDescriptorCallback<'s>>,
|
||||
) -> Self {
|
||||
self.descriptor = Some(descriptor.map_fn_to());
|
||||
self
|
||||
@ -354,13 +497,19 @@ impl<'s> IndexedPropertyHandlerConfiguration<'s> {
|
||||
self.data = Some(data);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the property handler flags. The default is PropertyHandlerFlags::NONE.
|
||||
pub fn flags(mut self, flags: PropertyHandlerFlags) -> Self {
|
||||
self.flags = flags;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Template {
|
||||
/// Adds a property to each instance created by this template.
|
||||
#[inline(always)]
|
||||
pub fn set(&self, key: Local<Name>, value: Local<Data>) {
|
||||
self.set_with_attr(key, value, NONE)
|
||||
self.set_with_attr(key, value, PropertyAttribute::NONE)
|
||||
}
|
||||
|
||||
/// Adds a property to each instance created by this template with
|
||||
@ -708,8 +857,10 @@ impl ObjectTemplate {
|
||||
configuration.query,
|
||||
configuration.deleter,
|
||||
configuration.enumerator,
|
||||
configuration.definer,
|
||||
configuration.descriptor,
|
||||
configuration.data.map_or_else(null, |p| &*p),
|
||||
configuration.flags,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -727,6 +878,7 @@ impl ObjectTemplate {
|
||||
configuration.query,
|
||||
configuration.deleter,
|
||||
configuration.enumerator,
|
||||
configuration.definer,
|
||||
configuration.descriptor,
|
||||
configuration.data.map_or_else(null, |p| &*p),
|
||||
)
|
||||
|
@ -1507,7 +1507,9 @@ fn object_template() {
|
||||
let object_templ = v8::ObjectTemplate::new(scope);
|
||||
let function_templ = v8::FunctionTemplate::new(scope, fortytwo_callback);
|
||||
let name = v8::String::new(scope, "f").unwrap();
|
||||
let attr = v8::READ_ONLY | v8::DONT_ENUM | v8::DONT_DELETE;
|
||||
let attr = v8::PropertyAttribute::READ_ONLY
|
||||
| v8::PropertyAttribute::DONT_ENUM
|
||||
| v8::PropertyAttribute::DONT_DELETE;
|
||||
object_templ.set_internal_field_count(1);
|
||||
object_templ.set_with_attr(name.into(), function_templ.into(), attr);
|
||||
let context = v8::Context::new(scope);
|
||||
@ -1530,7 +1532,7 @@ fn object_template() {
|
||||
scope,
|
||||
name.into(),
|
||||
object.into(),
|
||||
v8::DONT_ENUM,
|
||||
v8::PropertyAttribute::DONT_ENUM,
|
||||
);
|
||||
let source = r#"
|
||||
{
|
||||
@ -1787,7 +1789,8 @@ fn object_template_set_accessor() {
|
||||
let setter = |scope: &mut v8::HandleScope,
|
||||
key: v8::Local<v8::Name>,
|
||||
value: v8::Local<v8::Value>,
|
||||
args: v8::PropertyCallbackArguments| {
|
||||
args: v8::PropertyCallbackArguments,
|
||||
_rv: v8::ReturnValue| {
|
||||
let this = args.this();
|
||||
|
||||
assert_eq!(args.holder(), this);
|
||||
@ -1819,24 +1822,24 @@ fn object_template_set_accessor() {
|
||||
rv.set(this.get_internal_field(scope, 0).unwrap());
|
||||
};
|
||||
|
||||
let setter_with_data =
|
||||
|scope: &mut v8::HandleScope,
|
||||
key: v8::Local<v8::Name>,
|
||||
value: v8::Local<v8::Value>,
|
||||
args: v8::PropertyCallbackArguments| {
|
||||
let this = args.this();
|
||||
let setter_with_data = |scope: &mut v8::HandleScope,
|
||||
key: v8::Local<v8::Name>,
|
||||
value: v8::Local<v8::Value>,
|
||||
args: v8::PropertyCallbackArguments,
|
||||
_rv: v8::ReturnValue| {
|
||||
let this = args.this();
|
||||
|
||||
assert_eq!(args.holder(), this);
|
||||
assert!(args.data().is_string());
|
||||
assert!(!args.should_throw_on_error());
|
||||
assert_eq!(args.data().to_rust_string_lossy(scope), "data");
|
||||
assert_eq!(args.holder(), this);
|
||||
assert!(args.data().is_string());
|
||||
assert!(!args.should_throw_on_error());
|
||||
assert_eq!(args.data().to_rust_string_lossy(scope), "data");
|
||||
|
||||
let expected_key = v8::String::new(scope, "key").unwrap();
|
||||
assert!(key.strict_equals(expected_key.into()));
|
||||
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));
|
||||
};
|
||||
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();
|
||||
@ -1972,6 +1975,11 @@ fn object_template_set_named_property_handler() {
|
||||
key: v8::Local<v8::Name>,
|
||||
args: v8::PropertyCallbackArguments,
|
||||
mut rv: v8::ReturnValue| {
|
||||
let fallthrough_key = v8::String::new(scope, "fallthrough").unwrap();
|
||||
if key.strict_equals(fallthrough_key.into()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let this = args.this();
|
||||
|
||||
assert_eq!(args.holder(), this);
|
||||
@ -1987,7 +1995,18 @@ fn object_template_set_named_property_handler() {
|
||||
let setter = |scope: &mut v8::HandleScope,
|
||||
key: v8::Local<v8::Name>,
|
||||
value: v8::Local<v8::Value>,
|
||||
args: v8::PropertyCallbackArguments| {
|
||||
args: v8::PropertyCallbackArguments,
|
||||
mut rv: v8::ReturnValue| {
|
||||
let fallthrough_key = v8::String::new(scope, "fallthrough").unwrap();
|
||||
if key.strict_equals(fallthrough_key.into()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let panic_on_get = v8::String::new(scope, "panicOnGet").unwrap();
|
||||
if key.strict_equals(panic_on_get.into()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let this = args.this();
|
||||
|
||||
assert_eq!(args.holder(), this);
|
||||
@ -1999,12 +2018,24 @@ fn object_template_set_named_property_handler() {
|
||||
|
||||
assert!(value.is_int32());
|
||||
assert!(this.set_internal_field(0, value));
|
||||
|
||||
rv.set_undefined();
|
||||
};
|
||||
|
||||
let query = |scope: &mut v8::HandleScope,
|
||||
key: v8::Local<v8::Name>,
|
||||
args: v8::PropertyCallbackArguments,
|
||||
mut rv: v8::ReturnValue| {
|
||||
let fallthrough_key = v8::String::new(scope, "fallthrough").unwrap();
|
||||
if key.strict_equals(fallthrough_key.into()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let panic_on_get = v8::String::new(scope, "panicOnGet").unwrap();
|
||||
if key.strict_equals(panic_on_get.into()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let this = args.this();
|
||||
|
||||
assert_eq!(args.holder(), this);
|
||||
@ -2013,7 +2044,7 @@ fn object_template_set_named_property_handler() {
|
||||
|
||||
let expected_key = v8::String::new(scope, "key").unwrap();
|
||||
assert!(key.strict_equals(expected_key.into()));
|
||||
//PropertyAttribute::READ_ONLY
|
||||
// PropertyAttribute::READ_ONLY
|
||||
rv.set_int32(1);
|
||||
let expected_value = v8::Integer::new(scope, 42);
|
||||
assert!(this
|
||||
@ -2021,13 +2052,23 @@ fn object_template_set_named_property_handler() {
|
||||
.unwrap()
|
||||
.strict_equals(expected_value.into()));
|
||||
};
|
||||
|
||||
let deleter = |scope: &mut v8::HandleScope,
|
||||
key: v8::Local<v8::Name>,
|
||||
_args: v8::PropertyCallbackArguments,
|
||||
args: v8::PropertyCallbackArguments,
|
||||
mut rv: v8::ReturnValue| {
|
||||
let fallthrough_key = v8::String::new(scope, "fallthrough").unwrap();
|
||||
if key.strict_equals(fallthrough_key.into()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let this = args.this();
|
||||
|
||||
let expected_key = v8::String::new(scope, "key").unwrap();
|
||||
assert!(key.strict_equals(expected_key.into()));
|
||||
|
||||
assert!(this.set_internal_field(0, v8::undefined(scope).into()));
|
||||
|
||||
rv.set_bool(true);
|
||||
};
|
||||
|
||||
@ -2047,11 +2088,77 @@ fn object_template_set_named_property_handler() {
|
||||
.unwrap()
|
||||
.strict_equals(expected_value.into()));
|
||||
|
||||
let key = v8::String::new(scope, "key").unwrap();
|
||||
let key: v8::Local<v8::Name> =
|
||||
v8::String::new(scope, "key").unwrap().into();
|
||||
let result = v8::Array::new_with_elements(scope, &[key.into()]);
|
||||
rv.set(result.into());
|
||||
};
|
||||
|
||||
let definer = |scope: &mut v8::HandleScope,
|
||||
key: v8::Local<v8::Name>,
|
||||
desc: &v8::PropertyDescriptor,
|
||||
args: v8::PropertyCallbackArguments,
|
||||
mut rv: v8::ReturnValue| {
|
||||
let fallthrough_key = v8::String::new(scope, "fallthrough").unwrap();
|
||||
if key.strict_equals(fallthrough_key.into()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let this = args.this();
|
||||
|
||||
let expected_key = v8::String::new(scope, "key").unwrap();
|
||||
assert!(key.strict_equals(expected_key.into()));
|
||||
|
||||
assert!(desc.has_enumerable());
|
||||
assert!(desc.has_configurable());
|
||||
assert!(desc.has_writable());
|
||||
assert!(desc.has_value());
|
||||
assert!(!desc.has_get());
|
||||
assert!(!desc.has_set());
|
||||
|
||||
assert!(desc.enumerable());
|
||||
assert!(desc.configurable());
|
||||
assert!(desc.writable());
|
||||
|
||||
let value = desc.value();
|
||||
|
||||
assert!(value.is_int32());
|
||||
assert!(this.set_internal_field(0, value));
|
||||
|
||||
rv.set_undefined();
|
||||
};
|
||||
|
||||
let descriptor = |scope: &mut v8::HandleScope,
|
||||
key: v8::Local<v8::Name>,
|
||||
args: v8::PropertyCallbackArguments,
|
||||
mut rv: v8::ReturnValue| {
|
||||
let fallthrough_key = v8::String::new(scope, "fallthrough").unwrap();
|
||||
if key.strict_equals(fallthrough_key.into()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let this = args.this();
|
||||
|
||||
let expected_key = v8::String::new(scope, "key").unwrap();
|
||||
assert!(key.strict_equals(expected_key.into()));
|
||||
|
||||
let descriptor = v8::Object::new(scope);
|
||||
let value_key = v8::String::new(scope, "value").unwrap();
|
||||
let value = this.get_internal_field(scope, 0).unwrap();
|
||||
descriptor.set(scope, value_key.into(), value);
|
||||
let enumerable_key = v8::String::new(scope, "enumerable").unwrap();
|
||||
let enumerable = v8::Boolean::new(scope, true);
|
||||
descriptor.set(scope, enumerable_key.into(), enumerable.into());
|
||||
let configurable_key = v8::String::new(scope, "configurable").unwrap();
|
||||
let configurable = v8::Boolean::new(scope, true);
|
||||
descriptor.set(scope, configurable_key.into(), configurable.into());
|
||||
let writable_key = v8::String::new(scope, "writable").unwrap();
|
||||
let writable = v8::Boolean::new(scope, true);
|
||||
descriptor.set(scope, writable_key.into(), writable.into());
|
||||
|
||||
rv.set(descriptor.into());
|
||||
};
|
||||
|
||||
let name = v8::String::new(scope, "obj").unwrap();
|
||||
|
||||
// Lone getter
|
||||
@ -2070,6 +2177,14 @@ fn object_template_set_named_property_handler() {
|
||||
obj.into(),
|
||||
);
|
||||
assert!(eval(scope, "obj.key").unwrap().strict_equals(int.into()));
|
||||
assert!(eval(scope, "obj.fallthrough").unwrap().is_undefined());
|
||||
assert!(eval(scope, "obj.fallthrough = 'a'; obj.fallthrough")
|
||||
.unwrap()
|
||||
.is_string());
|
||||
assert!(obj
|
||||
.get_internal_field(scope, 0)
|
||||
.unwrap()
|
||||
.strict_equals(int.into()));
|
||||
|
||||
// Getter + setter + deleter
|
||||
let templ = v8::ObjectTemplate::new(scope);
|
||||
@ -2094,8 +2209,18 @@ fn object_template_set_named_property_handler() {
|
||||
.get_internal_field(scope, 0)
|
||||
.unwrap()
|
||||
.strict_equals(new_int.into()));
|
||||
|
||||
assert!(eval(scope, "delete obj.key").unwrap().boolean_value(scope));
|
||||
assert!(obj.get_internal_field(scope, 0).unwrap().is_undefined());
|
||||
assert!(eval(scope, "delete obj.key").unwrap().boolean_value(scope));
|
||||
|
||||
assert!(eval(scope, "obj.fallthrough = 'a'; obj.fallthrough")
|
||||
.unwrap()
|
||||
.is_string());
|
||||
assert!(obj.get_internal_field(scope, 0).unwrap().is_undefined());
|
||||
assert!(eval(scope, "delete obj.fallthrough")
|
||||
.unwrap()
|
||||
.boolean_value(scope));
|
||||
assert!(eval(scope, "obj.fallthrough").unwrap().is_undefined());
|
||||
|
||||
// query descriptor
|
||||
let templ = v8::ObjectTemplate::new(scope);
|
||||
@ -2111,16 +2236,16 @@ fn object_template_set_named_property_handler() {
|
||||
name.into(),
|
||||
obj.into(),
|
||||
);
|
||||
let result =
|
||||
eval(scope, "Object.getOwnPropertyDescriptor(obj, 'key')").unwrap();
|
||||
let object = result.to_object(scope).unwrap();
|
||||
let key = v8::String::new(scope, "writable").unwrap();
|
||||
let value = object.get(scope, key.into()).unwrap();
|
||||
assert!(eval(scope, "'key' in obj").unwrap().boolean_value(scope));
|
||||
assert!(!eval(scope, "'fallthrough' in obj")
|
||||
.unwrap()
|
||||
.boolean_value(scope));
|
||||
eval(scope, "obj.fallthrough = 'a'").unwrap();
|
||||
assert!(eval(scope, "'fallthrough' in obj")
|
||||
.unwrap()
|
||||
.boolean_value(scope));
|
||||
|
||||
let non_writable = v8::Boolean::new(scope, false);
|
||||
assert!(value.strict_equals(non_writable.into()));
|
||||
|
||||
//enumerator
|
||||
// enumerator
|
||||
let templ = v8::ObjectTemplate::new(scope);
|
||||
templ.set_internal_field_count(1);
|
||||
templ.set_named_property_handler(
|
||||
@ -2142,7 +2267,113 @@ fn object_template_set_named_property_handler() {
|
||||
let index = v8::Integer::new(scope, 0);
|
||||
let result = arr.get(scope, index.into()).unwrap();
|
||||
let expected = v8::String::new(scope, "key").unwrap();
|
||||
assert!(expected.strict_equals(result))
|
||||
assert!(expected.strict_equals(result));
|
||||
eval(scope, "obj.fallthrough = 'a'").unwrap();
|
||||
let arr = v8::Local::<v8::Array>::try_from(
|
||||
eval(scope, "Object.keys(obj)").unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(arr.length(), 2);
|
||||
|
||||
// definer
|
||||
let templ = v8::ObjectTemplate::new(scope);
|
||||
templ.set_internal_field_count(1);
|
||||
templ.set_named_property_handler(
|
||||
v8::NamedPropertyHandlerConfiguration::new().definer(definer),
|
||||
);
|
||||
|
||||
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(),
|
||||
);
|
||||
eval(
|
||||
scope,
|
||||
"Object.defineProperty(obj, 'key', { value: 9, enumerable: true, configurable: true, writable: true })",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(obj
|
||||
.get_internal_field(scope, 0)
|
||||
.unwrap()
|
||||
.strict_equals(new_int.into()));
|
||||
assert!(eval(
|
||||
scope,
|
||||
"Object.defineProperty(obj, 'fallthrough', { value: 'a' }); obj.fallthrough"
|
||||
)
|
||||
.unwrap()
|
||||
.is_string());
|
||||
|
||||
// descriptor
|
||||
let templ = v8::ObjectTemplate::new(scope);
|
||||
templ.set_internal_field_count(1);
|
||||
templ.set_named_property_handler(
|
||||
v8::NamedPropertyHandlerConfiguration::new().descriptor(descriptor),
|
||||
);
|
||||
|
||||
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 desc = eval(scope, "Object.getOwnPropertyDescriptor(obj, 'key')")
|
||||
.unwrap()
|
||||
.to_object(scope)
|
||||
.unwrap();
|
||||
let expected_value = v8::Integer::new(scope, 42);
|
||||
let value_key = v8::String::new(scope, "value").unwrap().into();
|
||||
assert!(desc
|
||||
.get(scope, value_key)
|
||||
.unwrap()
|
||||
.strict_equals(expected_value.into()));
|
||||
let enumerable_key = v8::String::new(scope, "enumerable").unwrap().into();
|
||||
assert!(desc
|
||||
.get(scope, enumerable_key)
|
||||
.unwrap()
|
||||
.boolean_value(scope));
|
||||
let configurable_key =
|
||||
v8::String::new(scope, "configurable").unwrap().into();
|
||||
assert!(desc
|
||||
.get(scope, configurable_key)
|
||||
.unwrap()
|
||||
.boolean_value(scope));
|
||||
let writable_key = v8::String::new(scope, "writable").unwrap().into();
|
||||
assert!(desc.get(scope, writable_key).unwrap().boolean_value(scope));
|
||||
assert!(
|
||||
eval(scope, "Object.getOwnPropertyDescriptor(obj, 'fallthrough')")
|
||||
.unwrap()
|
||||
.is_undefined()
|
||||
);
|
||||
|
||||
// Getter + Setter + Query + NON_MASKING
|
||||
let templ = v8::ObjectTemplate::new(scope);
|
||||
templ.set_internal_field_count(1);
|
||||
templ.set_named_property_handler(
|
||||
v8::NamedPropertyHandlerConfiguration::new()
|
||||
.getter(getter)
|
||||
.setter(setter)
|
||||
.query(query)
|
||||
.flags(v8::PropertyHandlerFlags::NON_MASKING),
|
||||
);
|
||||
|
||||
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(),
|
||||
);
|
||||
assert!(!eval(scope, "'panicOnGet' in obj")
|
||||
.unwrap()
|
||||
.boolean_value(scope));
|
||||
eval(scope, "obj.panicOnGet = 'x'").unwrap();
|
||||
assert!(eval(scope, "'panicOnGet' in obj")
|
||||
.unwrap()
|
||||
.boolean_value(scope));
|
||||
assert!(eval(scope, "obj.panicOnGet").unwrap().is_string());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2172,7 +2403,8 @@ fn object_template_set_indexed_property_handler() {
|
||||
let setter = |_scope: &mut v8::HandleScope,
|
||||
index: u32,
|
||||
value: v8::Local<v8::Value>,
|
||||
args: v8::PropertyCallbackArguments| {
|
||||
args: v8::PropertyCallbackArguments,
|
||||
mut rv: v8::ReturnValue| {
|
||||
let this = args.this();
|
||||
|
||||
assert_eq!(args.holder(), this);
|
||||
@ -2183,6 +2415,22 @@ fn object_template_set_indexed_property_handler() {
|
||||
|
||||
assert!(value.is_int32());
|
||||
assert!(this.set_internal_field(0, value));
|
||||
|
||||
rv.set_undefined();
|
||||
};
|
||||
|
||||
let query = |_scope: &mut v8::HandleScope,
|
||||
index: u32,
|
||||
_args: v8::PropertyCallbackArguments,
|
||||
mut rv: v8::ReturnValue| {
|
||||
if index == 12 {
|
||||
return;
|
||||
}
|
||||
|
||||
assert_eq!(index, 37);
|
||||
|
||||
// PropertyAttribute::READ_ONLY
|
||||
rv.set_int32(1);
|
||||
};
|
||||
|
||||
let deleter = |_scope: &mut v8::HandleScope,
|
||||
@ -2215,6 +2463,53 @@ fn object_template_set_indexed_property_handler() {
|
||||
rv.set(result.into());
|
||||
};
|
||||
|
||||
let definer = |_scope: &mut v8::HandleScope,
|
||||
index: u32,
|
||||
desc: &v8::PropertyDescriptor,
|
||||
args: v8::PropertyCallbackArguments,
|
||||
mut rv: v8::ReturnValue| {
|
||||
let this = args.this();
|
||||
|
||||
assert_eq!(index, 37);
|
||||
|
||||
assert!(!desc.has_enumerable());
|
||||
assert!(!desc.has_configurable());
|
||||
assert!(!desc.has_writable());
|
||||
assert!(desc.has_value());
|
||||
assert!(!desc.has_get());
|
||||
assert!(!desc.has_set());
|
||||
|
||||
let value = desc.value();
|
||||
this.set_internal_field(0, value);
|
||||
|
||||
rv.set_undefined();
|
||||
};
|
||||
|
||||
let descriptor = |scope: &mut v8::HandleScope,
|
||||
index: u32,
|
||||
args: v8::PropertyCallbackArguments,
|
||||
mut rv: v8::ReturnValue| {
|
||||
let this = args.this();
|
||||
|
||||
assert_eq!(index, 37);
|
||||
|
||||
let descriptor = v8::Object::new(scope);
|
||||
let value_key = v8::String::new(scope, "value").unwrap();
|
||||
let value = this.get_internal_field(scope, 0).unwrap();
|
||||
descriptor.set(scope, value_key.into(), value);
|
||||
let enumerable_key = v8::String::new(scope, "enumerable").unwrap();
|
||||
let enumerable = v8::Boolean::new(scope, true);
|
||||
descriptor.set(scope, enumerable_key.into(), enumerable.into());
|
||||
let configurable_key = v8::String::new(scope, "configurable").unwrap();
|
||||
let configurable = v8::Boolean::new(scope, true);
|
||||
descriptor.set(scope, configurable_key.into(), configurable.into());
|
||||
let writable_key = v8::String::new(scope, "writable").unwrap();
|
||||
let writable = v8::Boolean::new(scope, true);
|
||||
descriptor.set(scope, writable_key.into(), writable.into());
|
||||
|
||||
rv.set(descriptor.into());
|
||||
};
|
||||
|
||||
let name = v8::String::new(scope, "obj").unwrap();
|
||||
|
||||
// Lone getter
|
||||
@ -2258,7 +2553,22 @@ fn object_template_set_indexed_property_handler() {
|
||||
|
||||
assert!(!eval(scope, "delete obj[37]").unwrap().boolean_value(scope));
|
||||
|
||||
//Enumerator
|
||||
// Query
|
||||
let templ = v8::ObjectTemplate::new(scope);
|
||||
templ.set_internal_field_count(1);
|
||||
templ.set_indexed_property_handler(
|
||||
v8::IndexedPropertyHandlerConfiguration::new().query(query),
|
||||
);
|
||||
|
||||
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());
|
||||
assert!(eval(scope, "'37' in obj").unwrap().boolean_value(scope));
|
||||
|
||||
// Enumerator
|
||||
let templ = v8::ObjectTemplate::new(scope);
|
||||
templ.set_internal_field_count(1);
|
||||
templ.set_indexed_property_handler(
|
||||
@ -2285,8 +2595,61 @@ fn object_template_set_indexed_property_handler() {
|
||||
",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(value.strict_equals(int.into()));
|
||||
|
||||
// Definer
|
||||
let templ = v8::ObjectTemplate::new(scope);
|
||||
templ.set_internal_field_count(1);
|
||||
templ.set_indexed_property_handler(
|
||||
v8::IndexedPropertyHandlerConfiguration::new().definer(definer),
|
||||
);
|
||||
|
||||
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());
|
||||
eval(scope, "Object.defineProperty(obj, 37, { value: 9 })").unwrap();
|
||||
assert!(obj
|
||||
.get_internal_field(scope, 0)
|
||||
.unwrap()
|
||||
.strict_equals(new_int.into()));
|
||||
|
||||
// Descriptor
|
||||
let templ = v8::ObjectTemplate::new(scope);
|
||||
templ.set_internal_field_count(1);
|
||||
templ.set_indexed_property_handler(
|
||||
v8::IndexedPropertyHandlerConfiguration::new().descriptor(descriptor),
|
||||
);
|
||||
|
||||
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 desc = eval(scope, "Object.getOwnPropertyDescriptor(obj, 37)")
|
||||
.unwrap()
|
||||
.to_object(scope)
|
||||
.unwrap();
|
||||
let value_key = v8::String::new(scope, "value").unwrap().into();
|
||||
assert!(desc
|
||||
.get(scope, value_key)
|
||||
.unwrap()
|
||||
.strict_equals(int.into()));
|
||||
let enumerable_key = v8::String::new(scope, "enumerable").unwrap().into();
|
||||
assert!(desc
|
||||
.get(scope, enumerable_key)
|
||||
.unwrap()
|
||||
.boolean_value(scope));
|
||||
let configurable_key = v8::String::new(scope, "configurable").unwrap().into();
|
||||
assert!(desc
|
||||
.get(scope, configurable_key)
|
||||
.unwrap()
|
||||
.boolean_value(scope));
|
||||
let writable_key = v8::String::new(scope, "writable").unwrap().into();
|
||||
assert!(desc.get(scope, writable_key).unwrap().boolean_value(scope));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -2624,7 +2987,8 @@ fn object_set_accessor_with_setter() {
|
||||
let setter = |scope: &mut v8::HandleScope,
|
||||
key: v8::Local<v8::Name>,
|
||||
value: v8::Local<v8::Value>,
|
||||
args: v8::PropertyCallbackArguments| {
|
||||
args: v8::PropertyCallbackArguments,
|
||||
_rv: v8::ReturnValue| {
|
||||
println!("setter called");
|
||||
|
||||
let this = args.this();
|
||||
@ -2725,7 +3089,8 @@ fn object_set_accessor_with_setter_with_property() {
|
||||
let setter = |scope: &mut v8::HandleScope,
|
||||
key: v8::Local<v8::Name>,
|
||||
value: v8::Local<v8::Value>,
|
||||
args: v8::PropertyCallbackArguments| {
|
||||
args: v8::PropertyCallbackArguments,
|
||||
_rv: v8::ReturnValue| {
|
||||
println!("setter called");
|
||||
|
||||
let this = args.this();
|
||||
@ -2757,7 +3122,7 @@ fn object_set_accessor_with_setter_with_property() {
|
||||
getter_setter_key.into(),
|
||||
AccessorConfiguration::new(getter)
|
||||
.setter(setter)
|
||||
.property_attribute(v8::READ_ONLY),
|
||||
.property_attribute(v8::PropertyAttribute::READ_ONLY),
|
||||
);
|
||||
|
||||
let int_key = v8::String::new(scope, "int_key").unwrap();
|
||||
@ -2830,7 +3195,8 @@ fn object_set_accessor_with_data() {
|
||||
let setter = |scope: &mut v8::HandleScope,
|
||||
key: v8::Local<v8::Name>,
|
||||
value: v8::Local<v8::Value>,
|
||||
args: v8::PropertyCallbackArguments| {
|
||||
args: v8::PropertyCallbackArguments,
|
||||
_rv: v8::ReturnValue| {
|
||||
println!("setter called");
|
||||
|
||||
let this = args.this();
|
||||
@ -6363,7 +6729,8 @@ fn test_object_get_property_names() {
|
||||
scope,
|
||||
v8::GetPropertyNamesArgs {
|
||||
mode: v8::KeyCollectionMode::IncludePrototypes,
|
||||
property_filter: v8::ONLY_ENUMERABLE | v8::SKIP_SYMBOLS,
|
||||
property_filter: v8::PropertyFilter::ONLY_ENUMERABLE
|
||||
| v8::PropertyFilter::SKIP_SYMBOLS,
|
||||
index_filter: v8::IndexFilter::IncludeIndices,
|
||||
key_conversion: v8::KeyConversionMode::KeepNumbers,
|
||||
},
|
||||
@ -9523,7 +9890,7 @@ fn gc_callbacks() {
|
||||
data: *mut c_void,
|
||||
) {
|
||||
// We should get a mark-sweep GC here.
|
||||
assert_eq!(r#type, v8::GC_TYPE_MARK_SWEEP_COMPACT);
|
||||
assert_eq!(r#type, v8::GCType::MARK_SWEEP_COMPACT);
|
||||
let state = unsafe { &mut *(data as *mut GCCallbackState) };
|
||||
state.mark_sweep_calls += 1;
|
||||
}
|
||||
@ -9535,7 +9902,7 @@ fn gc_callbacks() {
|
||||
data: *mut c_void,
|
||||
) {
|
||||
// We should get a mark-sweep GC here.
|
||||
assert_eq!(r#type, v8::GC_TYPE_INCREMENTAL_MARKING);
|
||||
assert_eq!(r#type, v8::GCType::INCREMENTAL_MARKING);
|
||||
let state = unsafe { &mut *(data as *mut GCCallbackState) };
|
||||
state.incremental_marking_calls += 1;
|
||||
}
|
||||
@ -9543,11 +9910,11 @@ fn gc_callbacks() {
|
||||
let mut state = GCCallbackState::default();
|
||||
let state_ptr = &mut state as *mut _ as *mut c_void;
|
||||
let isolate = &mut v8::Isolate::new(Default::default());
|
||||
isolate.add_gc_prologue_callback(callback, state_ptr, v8::GC_TYPE_ALL);
|
||||
isolate.add_gc_prologue_callback(callback, state_ptr, v8::GCType::ALL);
|
||||
isolate.add_gc_prologue_callback(
|
||||
callback2,
|
||||
state_ptr,
|
||||
v8::GC_TYPE_INCREMENTAL_MARKING | v8::GC_TYPE_PROCESS_WEAK_CALLBACK,
|
||||
v8::GCType::INCREMENTAL_MARKING | v8::GCType::PROCESS_WEAK_CALLBACKS,
|
||||
);
|
||||
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user