Add HasOwnProperty with array indexes
This way embedders don't have to manually convert them to strings
BUG=chromium:619166
R=verwaest@chromium.org
Review-Url: https://codereview.chromium.org/2085223002
Cr-Commit-Position: refs/heads/master@{#37179}
diff --git a/include/v8.h b/include/v8.h
index 86db387..101349c 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -2897,6 +2897,8 @@
V8_DEPRECATED("Use maybe version", bool HasOwnProperty(Local<String> key));
V8_WARN_UNUSED_RESULT Maybe<bool> HasOwnProperty(Local<Context> context,
Local<Name> key);
+ V8_WARN_UNUSED_RESULT Maybe<bool> HasOwnProperty(Local<Context> context,
+ uint32_t index);
V8_DEPRECATE_SOON("Use maybe version",
bool HasRealNamedProperty(Local<String> key));
V8_WARN_UNUSED_RESULT Maybe<bool> HasRealNamedProperty(Local<Context> context,
diff --git a/src/api.cc b/src/api.cc
index 46c923d..18599bf 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -4184,6 +4184,14 @@
return result;
}
+Maybe<bool> v8::Object::HasOwnProperty(Local<Context> context, uint32_t index) {
+ PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, HasOwnProperty, bool);
+ auto self = Utils::OpenHandle(this);
+ auto result = i::JSReceiver::HasOwnProperty(self, index);
+ has_pending_exception = result.IsNothing();
+ RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+ return result;
+}
bool v8::Object::HasOwnProperty(Local<String> key) {
auto context = ContextFromHeapObject(Utils::OpenHandle(this));
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 77a3fcd..095173b 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -7178,6 +7178,19 @@
return Just(attributes.FromJust() != ABSENT);
}
+Maybe<bool> JSReceiver::HasOwnProperty(Handle<JSReceiver> object,
+ uint32_t index) {
+ if (object->IsJSObject()) { // Shortcut
+ LookupIterator it(object->GetIsolate(), object, index, object,
+ LookupIterator::OWN);
+ return HasProperty(&it);
+ }
+
+ Maybe<PropertyAttributes> attributes =
+ JSReceiver::GetOwnPropertyAttributes(object, index);
+ MAYBE_RETURN(attributes, Nothing<bool>());
+ return Just(attributes.FromJust() != ABSENT);
+}
Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
Handle<JSReceiver> object, Handle<Name> name) {
@@ -7194,6 +7207,12 @@
return GetPropertyAttributes(&it);
}
+Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes(
+ Handle<JSReceiver> object, uint32_t index) {
+ LookupIterator it(object->GetIsolate(), object, index, object,
+ LookupIterator::OWN);
+ return GetPropertyAttributes(&it);
+}
Maybe<bool> JSReceiver::HasElement(Handle<JSReceiver> object, uint32_t index) {
LookupIterator it(object->GetIsolate(), object, index, object);
diff --git a/src/objects.h b/src/objects.h
index 19d7ba4..ea38a86 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1854,6 +1854,8 @@
MUST_USE_RESULT static inline Maybe<bool> HasOwnProperty(
Handle<JSReceiver> object, Handle<Name> name);
+ MUST_USE_RESULT static inline Maybe<bool> HasOwnProperty(
+ Handle<JSReceiver> object, uint32_t index);
MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty(
Isolate* isolate, Handle<JSReceiver> receiver, const char* key);
@@ -1951,6 +1953,8 @@
Handle<JSReceiver> object, Handle<Name> name);
MUST_USE_RESULT static inline Maybe<PropertyAttributes>
GetOwnPropertyAttributes(Handle<JSReceiver> object, Handle<Name> name);
+ MUST_USE_RESULT static inline Maybe<PropertyAttributes>
+ GetOwnPropertyAttributes(Handle<JSReceiver> object, uint32_t index);
MUST_USE_RESULT static inline Maybe<PropertyAttributes> GetElementAttributes(
Handle<JSReceiver> object, uint32_t index);
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index a106044..5571e29 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -20478,6 +20478,7 @@
HasOwnPropertyNamedPropertyGetter));
Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
CHECK(!instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
+ CHECK(!instance->HasOwnProperty(env.local(), 42).FromJust());
CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
}
@@ -20487,7 +20488,9 @@
HasOwnPropertyIndexedPropertyGetter));
Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
+ CHECK(instance->HasOwnProperty(env.local(), 42).FromJust());
CHECK(!instance->HasOwnProperty(env.local(), v8_str("43")).FromJust());
+ CHECK(!instance->HasOwnProperty(env.local(), 43).FromJust());
CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
}
{ // Check named query interceptors.
@@ -20504,7 +20507,9 @@
0, 0, HasOwnPropertyIndexedPropertyQuery));
Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
+ CHECK(instance->HasOwnProperty(env.local(), 42).FromJust());
CHECK(!instance->HasOwnProperty(env.local(), v8_str("41")).FromJust());
+ CHECK(!instance->HasOwnProperty(env.local(), 41).FromJust());
}
{ // Check callbacks.
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);