Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Object::get_property_names() and Object::get_own_property_names() #1049

Merged
merged 3 commits into from
Sep 3, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion examples/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,9 @@ where
.to_object(scope)
.unwrap();

let props = output.get_property_names(scope).unwrap();
let props = output
.get_property_names(scope, v8::GetPropertyNamesArgsBuilder::new().build())
.unwrap();
for i in 0..props.length() {
let key = props.get_index(scope, i).unwrap();
let value = output.get(scope, key).unwrap();
Expand Down
52 changes: 42 additions & 10 deletions src/binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1244,16 +1244,48 @@ const v8::Context* v8__Object__GetCreationContext(const v8::Object& self) {
return maybe_local_to_ptr(ptr_to_local(&self)->GetCreationContext());
}

const v8::Array* v8__Object__GetOwnPropertyNames(const v8::Object* self,
const v8::Context* context) {
return maybe_local_to_ptr(
ptr_to_local(self)->GetOwnPropertyNames(ptr_to_local(context)));
}

const v8::Array* v8__Object__GetPropertyNames(const v8::Object* self,
const v8::Context* context) {
return maybe_local_to_ptr(
ptr_to_local(self)->GetPropertyNames(ptr_to_local(context)));
// v8::PropertyFilter
static_assert(v8::ALL_PROPERTIES == 0, "v8::ALL_PROPERTIES is not 0");
static_assert(v8::ONLY_WRITABLE == 1, "v8::ONLY_WRITABLE is not 1");
static_assert(v8::ONLY_ENUMERABLE == 2, "v8::ONLY_ENUMERABLE is not 2");
static_assert(v8::ONLY_CONFIGURABLE == 4, "v8::ONLY_CONFIGURABLE is not 4");
static_assert(v8::SKIP_STRINGS == 8, "v8::SKIP_STRINGS is not 8");
static_assert(v8::SKIP_SYMBOLS == 16, "v8::SKIP_SYMBOLS is not 16");

// v8::KeyConversionMode
static_assert(static_cast<int>(v8::KeyConversionMode::kConvertToString) == 0,
"v8::KeyConversionMode::kConvertToString is not 0");
static_assert(static_cast<int>(v8::KeyConversionMode::kKeepNumbers) == 1,
"v8::KeyConversionMode::kKeepNumbers is not 1");
static_assert(static_cast<int>(v8::KeyConversionMode::kNoNumbers) == 2,
"v8::KeyConversionMode::kNoNumbers is not 2");

// v8::KeyCollectionMode
static_assert(static_cast<int>(v8::KeyCollectionMode::kOwnOnly) == 0,
"v8::KeyCollectionMode::kOwnOnly is not 0");
static_assert(static_cast<int>(v8::KeyCollectionMode::kIncludePrototypes) == 1,
"v8::KeyCollectionMode::kIncludePrototypes is not 1");

// v8::IndexFilter
static_assert(static_cast<int>(v8::IndexFilter::kIncludeIndices) == 0,
"v8::IndexFilter::kIncludeIndices is not 0");
static_assert(static_cast<int>(v8::IndexFilter::kSkipIndices) == 1,
"v8::IndexFilter::kSkipIndices is not 1");

const v8::Array* v8__Object__GetOwnPropertyNames(
const v8::Object* self, const v8::Context* context,
v8::PropertyFilter filter, v8::KeyConversionMode key_conversion) {
return maybe_local_to_ptr(ptr_to_local(self)->GetOwnPropertyNames(
ptr_to_local(context), filter, key_conversion));
}

const v8::Array* v8__Object__GetPropertyNames(
const v8::Object* self, const v8::Context* context,
v8::KeyCollectionMode mode, v8::PropertyFilter property_filter,
v8::IndexFilter index_filter, v8::KeyConversionMode key_conversion) {
return maybe_local_to_ptr(ptr_to_local(self)->GetPropertyNames(
ptr_to_local(context), mode, property_filter, index_filter,
key_conversion));
}

MaybeBool v8__Object__Has(const v8::Object& self, const v8::Context& context,
Expand Down
109 changes: 109 additions & 0 deletions src/get_property_names_args_builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use crate::PropertyFilter;
use crate::ONLY_ENUMERABLE;
use crate::SKIP_SYMBOLS;

#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub enum KeyConversionMode {
/// kConvertToString will convert integer indices to strings.
ConvertToString,
/// kKeepNumbers will return numbers for integer indices.
KeepNumbers,
NoNumbers,
}

/// Keys/Properties filter enums:
///
/// KeyCollectionMode limits the range of collected properties. kOwnOnly limits
/// the collected properties to the given Object only. kIncludesPrototypes will
/// include all keys of the objects's prototype chain as well.
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub enum KeyCollectionMode {
/// OwnOnly limits the collected properties to the given Object only.
OwnOnly,
/// kIncludesPrototypes will include all keys of the objects's prototype chain
/// as well.
IncludePrototypes,
}

#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub enum IndexFilter {
/// kIncludesIndices allows for integer indices to be collected.
IncludeIndices,
/// kSkipIndices will exclude integer indices from being collected.
SkipIndices,
}

pub struct GetPropertyNamesArgs {
pub mode: KeyCollectionMode,
pub property_filter: PropertyFilter,
pub index_filter: IndexFilter,
pub key_conversion: KeyConversionMode,
}

pub struct GetPropertyNamesArgsBuilder {
mode: KeyCollectionMode,
property_filter: PropertyFilter,
index_filter: IndexFilter,
key_conversion: KeyConversionMode,
}

impl Default for GetPropertyNamesArgsBuilder {
fn default() -> Self {
Self::new()
}
}

impl GetPropertyNamesArgsBuilder {
pub fn new() -> Self {
Self {
mode: KeyCollectionMode::IncludePrototypes,
property_filter: ONLY_ENUMERABLE | SKIP_SYMBOLS,
index_filter: IndexFilter::IncludeIndices,
key_conversion: KeyConversionMode::KeepNumbers,
}
}

pub fn build(&self) -> GetPropertyNamesArgs {
GetPropertyNamesArgs {
mode: self.mode,
property_filter: self.property_filter,
index_filter: self.index_filter,
key_conversion: self.key_conversion,
}
}

pub fn mode(
&mut self,
mode: KeyCollectionMode,
) -> &mut GetPropertyNamesArgsBuilder {
self.mode = mode;
self
}

pub fn property_filter(
&mut self,
property_filter: PropertyFilter,
) -> &mut GetPropertyNamesArgsBuilder {
self.property_filter = property_filter;
self
}

pub fn index_filter(
&mut self,
index_filter: IndexFilter,
) -> &mut GetPropertyNamesArgsBuilder {
self.index_filter = index_filter;
self
}

pub fn key_conversion(
&mut self,
key_conversion: KeyConversionMode,
) -> &mut Self {
self.key_conversion = key_conversion;
self
}
}
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ mod external_references;
pub mod fast_api;
mod fixed_array;
mod function;
mod get_property_names_args_builder;
mod handle;
pub mod icu;
mod isolate;
Expand All @@ -55,6 +56,7 @@ mod primitives;
mod private;
mod promise;
mod property_attribute;
mod property_filter;
mod proxy;
mod scope;
mod script;
Expand Down Expand Up @@ -88,6 +90,7 @@ pub use exception::*;
pub use external_references::ExternalReference;
pub use external_references::ExternalReferences;
pub use function::*;
pub use get_property_names_args_builder::*;
pub use handle::Global;
pub use handle::Handle;
pub use handle::Local;
Expand Down Expand Up @@ -118,6 +121,7 @@ pub use primitives::*;
pub use private::*;
pub use promise::{PromiseRejectEvent, PromiseRejectMessage, PromiseState};
pub use property_attribute::*;
pub use property_filter::*;
pub use proxy::*;
pub use scope::CallbackScope;
pub use scope::ContextScope;
Expand Down
29 changes: 27 additions & 2 deletions src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@ use crate::AccessorNameGetterCallback;
use crate::AccessorNameSetterCallback;
use crate::Array;
use crate::Context;
use crate::GetPropertyNamesArgs;
use crate::HandleScope;
use crate::IndexFilter;
use crate::KeyCollectionMode;
use crate::KeyConversionMode;
use crate::Local;
use crate::Map;
use crate::Name;
use crate::Object;
use crate::Private;
use crate::PropertyAttribute;
use crate::PropertyFilter;
use crate::Value;
use std::convert::TryFrom;
use std::num::NonZeroI32;
Expand Down Expand Up @@ -87,10 +92,16 @@ extern "C" {
fn v8__Object__GetOwnPropertyNames(
this: *const Object,
context: *const Context,
filter: PropertyFilter,
key_conversion: KeyConversionMode,
) -> *const Array;
fn v8__Object__GetPropertyNames(
this: *const Object,
context: *const Context,
mode: KeyCollectionMode,
property_filter: PropertyFilter,
index_filter: IndexFilter,
key_conversion: KeyConversionMode,
) -> *const Array;
fn v8__Object__Has(
this: *const Object,
Expand Down Expand Up @@ -414,10 +425,16 @@ impl Object {
pub fn get_own_property_names<'s>(
&self,
scope: &mut HandleScope<'s>,
args: GetPropertyNamesArgs,
) -> Option<Local<'s, Array>> {
unsafe {
scope.cast_local(|sd| {
v8__Object__GetOwnPropertyNames(self, sd.get_current_context())
v8__Object__GetOwnPropertyNames(
self,
sd.get_current_context(),
args.property_filter,
args.key_conversion,
)
})
}
}
Expand All @@ -429,10 +446,18 @@ impl Object {
pub fn get_property_names<'s>(
&self,
scope: &mut HandleScope<'s>,
args: GetPropertyNamesArgs,
) -> Option<Local<'s, Array>> {
unsafe {
scope.cast_local(|sd| {
v8__Object__GetPropertyNames(self, sd.get_current_context())
v8__Object__GetPropertyNames(
self,
sd.get_current_context(),
args.mode,
args.property_filter,
args.index_filter,
args.key_conversion,
)
})
}
}
Expand Down
Loading