Commit f0d27360 authored by kozyatinskiy's avatar kozyatinskiy Committed by Commit bot

Add v8::Object::GetOwnPropertyNames(context, filter) method

This method provides ability to get all properties of the object with passed filter in addition to existing GetOwnPropertyNames(context) method that returns only enumerable properties.

BUG=v8:3861,chromium:581495
R=yangguo@chromium.org
LOG=Y

Review-Url: https://codereview.chromium.org/1943773002
Cr-Commit-Position: refs/heads/master@{#36031}
parent 068791e2
......@@ -2656,6 +2656,18 @@ enum AccessControl {
PROHIBITS_OVERWRITING = 1 << 2
};
/**
* Property filter bits. They can be or'ed to build a composite filter.
*/
enum PropertyFilter {
ALL_PROPERTIES = 0,
ONLY_WRITABLE = 1,
ONLY_ENUMERABLE = 2,
ONLY_CONFIGURABLE = 4,
SKIP_STRINGS = 8,
SKIP_SYMBOLS = 16
};
/**
* Integrity level for objects.
*/
......@@ -2815,6 +2827,15 @@ class V8_EXPORT Object : public Value {
V8_WARN_UNUSED_RESULT MaybeLocal<Array> GetOwnPropertyNames(
Local<Context> context);
/**
* Returns an array containing the names of the filtered properties
* of this object, including properties from prototype objects. The
* array returned by this method contains the same values as would
* be enumerated by a for-in statement over this object.
*/
V8_WARN_UNUSED_RESULT MaybeLocal<Array> GetOwnPropertyNames(
Local<Context> context, PropertyFilter filter);
/**
* Get the prototype object. This does not skip objects marked to
* be skipped by __proto__ and it does not consult the security
......
......@@ -3901,11 +3901,23 @@ Local<Array> v8::Object::GetPropertyNames() {
MaybeLocal<Array> v8::Object::GetOwnPropertyNames(Local<Context> context) {
return GetOwnPropertyNames(
context, static_cast<v8::PropertyFilter>(ONLY_ENUMERABLE | SKIP_SYMBOLS));
}
Local<Array> v8::Object::GetOwnPropertyNames() {
auto context = ContextFromHeapObject(Utils::OpenHandle(this));
RETURN_TO_LOCAL_UNCHECKED(GetOwnPropertyNames(context), Array);
}
MaybeLocal<Array> v8::Object::GetOwnPropertyNames(Local<Context> context,
PropertyFilter filter) {
PREPARE_FOR_EXECUTION(context, "v8::Object::GetOwnPropertyNames()", Array);
auto self = Utils::OpenHandle(this);
i::Handle<i::FixedArray> value;
has_pending_exception =
!i::JSReceiver::GetKeys(self, i::OWN_ONLY, i::ENUMERABLE_STRINGS)
!i::JSReceiver::GetKeys(self, i::OWN_ONLY,
static_cast<i::PropertyFilter>(filter))
.ToHandle(&value);
RETURN_ON_FAILED_EXECUTION(Array);
DCHECK(self->map()->EnumLength() == i::kInvalidEnumCacheSentinel ||
......@@ -3916,12 +3928,6 @@ MaybeLocal<Array> v8::Object::GetOwnPropertyNames(Local<Context> context) {
}
Local<Array> v8::Object::GetOwnPropertyNames() {
auto context = ContextFromHeapObject(Utils::OpenHandle(this));
RETURN_TO_LOCAL_UNCHECKED(GetOwnPropertyNames(context), Array);
}
MaybeLocal<String> v8::Object::ObjectProtoToString(Local<Context> context) {
PREPARE_FOR_EXECUTION(context, "v8::Object::ObjectProtoToString", String);
auto obj = Utils::OpenHandle(this);
......
......@@ -53,7 +53,18 @@ STATIC_ASSERT(ONLY_ENUMERABLE == static_cast<PropertyFilter>(DONT_ENUM));
STATIC_ASSERT(ONLY_CONFIGURABLE == static_cast<PropertyFilter>(DONT_DELETE));
STATIC_ASSERT(((SKIP_STRINGS | SKIP_SYMBOLS | ONLY_ALL_CAN_READ) &
ALL_ATTRIBUTES_MASK) == 0);
STATIC_ASSERT(ALL_PROPERTIES ==
static_cast<PropertyFilter>(v8::PropertyFilter::ALL_PROPERTIES));
STATIC_ASSERT(ONLY_WRITABLE ==
static_cast<PropertyFilter>(v8::PropertyFilter::ONLY_WRITABLE));
STATIC_ASSERT(ONLY_ENUMERABLE ==
static_cast<PropertyFilter>(v8::PropertyFilter::ONLY_ENUMERABLE));
STATIC_ASSERT(ONLY_CONFIGURABLE == static_cast<PropertyFilter>(
v8::PropertyFilter::ONLY_CONFIGURABLE));
STATIC_ASSERT(SKIP_STRINGS ==
static_cast<PropertyFilter>(v8::PropertyFilter::SKIP_STRINGS));
STATIC_ASSERT(SKIP_SYMBOLS ==
static_cast<PropertyFilter>(v8::PropertyFilter::SKIP_SYMBOLS));
class Smi;
class Type;
......
......@@ -10394,6 +10394,69 @@ THREADED_TEST(GlobalObjectInstanceProperties) {
}
}
THREADED_TEST(ObjectGetOwnPropertyNames) {
LocalContext context;
v8::Isolate* isolate = context->GetIsolate();
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Object> value =
v8::Local<v8::Object>::Cast(v8::StringObject::New(v8_str("test")));
v8::Local<v8::Array> properties;
CHECK(value
->GetOwnPropertyNames(context.local(),
static_cast<v8::PropertyFilter>(
v8::PropertyFilter::ALL_PROPERTIES |
v8::PropertyFilter::SKIP_SYMBOLS))
.ToLocal(&properties));
CHECK_EQ(5, properties->Length());
v8::Local<v8::Value> property;
CHECK(properties->Get(context.local(), 4).ToLocal(&property) &&
property->IsString());
CHECK(property.As<v8::String>()
->Equals(context.local(), v8_str("length"))
.FromMaybe(false));
for (int i = 0; i < 4; ++i) {
v8::Local<v8::Value> property;
CHECK(properties->Get(context.local(), i).ToLocal(&property) &&
property->IsInt32());
CHECK_EQ(property.As<v8::Int32>()->Value(), i);
}
CHECK(value->GetOwnPropertyNames(context.local(), v8::ONLY_ENUMERABLE)
.ToLocal(&properties));
CHECK_EQ(4, properties->Length());
for (int i = 0; i < 4; ++i) {
v8::Local<v8::Value> property;
CHECK(properties->Get(context.local(), i).ToLocal(&property) &&
property->IsInt32());
CHECK_EQ(property.As<v8::Int32>()->Value(), i);
}
value = value->GetPrototype().As<v8::Object>();
CHECK(value
->GetOwnPropertyNames(context.local(),
static_cast<v8::PropertyFilter>(
v8::PropertyFilter::ALL_PROPERTIES |
v8::PropertyFilter::SKIP_SYMBOLS))
.ToLocal(&properties));
bool concat_found = false;
bool starts_with_found = false;
for (uint32_t i = 0; i < properties->Length(); ++i) {
v8::Local<v8::Value> property;
CHECK(properties->Get(context.local(), i).ToLocal(&property));
if (!property->IsString()) continue;
if (!concat_found)
concat_found = property.As<v8::String>()
->Equals(context.local(), v8_str("concat"))
.FromMaybe(false);
if (!starts_with_found)
starts_with_found = property.As<v8::String>()
->Equals(context.local(), v8_str("startsWith"))
.FromMaybe(false);
}
CHECK(concat_found && starts_with_found);
}
THREADED_TEST(CallKnownGlobalReceiver) {
v8::Isolate* isolate = CcTest::isolate();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment