Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(794)

Unified Diff: src/objects.cc

Issue 1466243002: [proxies] Refactor JSReceiver::GetKeys() (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: update test-api.cc Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/objects.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 707ace30cac4b67a04843afa564361de485ff8f7..2b321a1c58356332b01c5697ec5ca6e364e09510 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -7965,107 +7965,134 @@ Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object,
}
-MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
- KeyCollectionType type,
- KeyFilter filter,
- GetKeysConversion getConversion,
- Enumerability enum_policy) {
- USE(ContainsOnlyValidKeys);
- Isolate* isolate = object->GetIsolate();
- KeyAccumulator accumulator(isolate, filter);
- Handle<JSFunction> arguments_function(
- JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
- PrototypeIterator::WhereToEnd end = type == OWN_ONLY
- ? PrototypeIterator::END_AT_NON_HIDDEN
- : PrototypeIterator::END_AT_NULL;
+static bool GetKeysFromJSObject(Isolate* isolate, Handle<JSReceiver> receiver,
+ Handle<JSObject> object, KeyFilter filter,
+ Enumerability enum_policy,
+ KeyAccumulator* accumulator) {
+ // Check access rights if required.
+ if (object->IsAccessCheckNeeded() &&
+ !isolate->MayAccess(handle(isolate->context()), object)) {
+ // TODO(jkummerow): Get whitelisted (all-can-read) keys.
+ // It's probably best to implement a "GetKeysWithFailedAccessCheck"
+ // helper, which will need to look at both interceptors and accessors.
+ return false;
+ }
+
PropertyAttributes attr_filter = static_cast<PropertyAttributes>(
(enum_policy == RESPECT_ENUMERABILITY ? DONT_ENUM : NONE) |
PRIVATE_SYMBOL);
- // Only collect keys if access is permitted.
+ JSObject::CollectOwnElementKeys(object, accumulator, attr_filter);
+
+ // Add the element keys from the interceptor.
+ if (object->HasIndexedInterceptor()) {
+ Handle<JSObject> result;
+ if (JSObject::GetKeysForIndexedInterceptor(object, receiver)
+ .ToHandle(&result)) {
+ accumulator->AddElementKeysFromInterceptor(result);
+ }
+ RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, false);
+ }
+
+ if (filter == SKIP_SYMBOLS) {
+ if (enum_policy == IGNORE_ENUMERABILITY) UNIMPLEMENTED();
+
+ // We can cache the computed property keys if access checks are
+ // not needed and no interceptors are involved.
+ //
+ // We do not use the cache if the object has elements and
+ // therefore it does not make sense to cache the property names
+ // for arguments objects. Arguments objects will always have
+ // elements.
+ // Wrapped strings have elements, but don't have an elements
+ // array or dictionary. So the fast inline test for whether to
+ // use the cache says yes, so we should not create a cache.
+ Handle<JSFunction> arguments_function(
+ JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
+ bool cache_enum_length =
+ ((object->map()->GetConstructor() != *arguments_function) &&
+ !object->IsJSValue() && !object->IsAccessCheckNeeded() &&
+ !object->HasNamedInterceptor() && !object->HasIndexedInterceptor());
+ // Compute the property keys and cache them if possible.
+ Handle<FixedArray> enum_keys =
+ JSObject::GetEnumPropertyKeys(object, cache_enum_length);
+ accumulator->AddKeys(enum_keys);
+ } else {
+ DCHECK(filter == INCLUDE_SYMBOLS);
+ object->CollectOwnPropertyNames(accumulator, attr_filter);
+ }
+
+ // Add the property keys from the interceptor.
+ if (object->HasNamedInterceptor()) {
+ Handle<JSObject> result;
+ if (JSObject::GetKeysForNamedInterceptor(object, receiver)
+ .ToHandle(&result)) {
+ accumulator->AddKeys(result);
+ }
+ RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, false);
+ }
+ return true;
+}
+
+
+// Helper function for JSReceiver::GetKeys() below. Can be called recursively.
+// Returns false iff an exception was thrown.
+static bool GetKeys_Internal(Isolate* isolate, Handle<JSReceiver> receiver,
+ Handle<JSReceiver> object,
+ JSReceiver::KeyCollectionType type,
+ KeyFilter filter, Enumerability enum_policy,
+ KeyAccumulator* accumulator) {
+ PrototypeIterator::WhereToEnd end = type == JSReceiver::OWN_ONLY
+ ? PrototypeIterator::END_AT_NON_HIDDEN
+ : PrototypeIterator::END_AT_NULL;
for (PrototypeIterator iter(isolate, object,
PrototypeIterator::START_AT_RECEIVER);
!iter.IsAtEnd(end); iter.Advance()) {
- accumulator.NextPrototype();
- if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
- Handle<JSProxy> proxy = PrototypeIterator::GetCurrent<JSProxy>(iter);
- Handle<Object> args[] = { proxy };
+ accumulator->NextPrototype();
+ Handle<JSReceiver> current =
+ PrototypeIterator::GetCurrent<JSReceiver>(iter);
+ bool result = false;
+ if (current->IsJSProxy()) {
+ Handle<Object> args[] = {current};
Handle<Object> names;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, names,
- Execution::Call(isolate,
- isolate->proxy_enumerate(),
- object,
- arraysize(args),
- args),
- FixedArray);
- accumulator.AddKeysFromProxy(Handle<JSObject>::cast(names));
- break;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, names, Execution::Call(isolate, isolate->proxy_enumerate(),
+ current, arraysize(args), args),
+ false);
+ accumulator->AddKeysFromProxy(Handle<JSObject>::cast(names));
+ } else {
+ DCHECK(current->IsJSObject());
+ result = GetKeysFromJSObject(isolate, receiver,
+ Handle<JSObject>::cast(current), filter,
+ enum_policy, accumulator);
}
-
- Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
-
- // Check access rights if required.
- if (current->IsAccessCheckNeeded() &&
- !isolate->MayAccess(handle(isolate->context()), current)) {
- if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
- isolate->ReportFailedAccessCheck(current);
- RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
+ if (!result) {
+ if (isolate->has_pending_exception()) {
+ return false;
}
+ // If there was no exception, then "false" means "stop iterating".
break;
}
+ }
+ return true;
+}
- JSObject::CollectOwnElementKeys(current, &accumulator, attr_filter);
-
- // Add the element keys from the interceptor.
- if (current->HasIndexedInterceptor()) {
- Handle<JSObject> result;
- if (JSObject::GetKeysForIndexedInterceptor(current, object)
- .ToHandle(&result)) {
- accumulator.AddElementKeysFromInterceptor(result);
- }
- RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
- }
-
- if (filter == SKIP_SYMBOLS) {
- if (enum_policy == IGNORE_ENUMERABILITY) UNIMPLEMENTED();
-
- // We can cache the computed property keys if access checks are
- // not needed and no interceptors are involved.
- //
- // We do not use the cache if the object has elements and
- // therefore it does not make sense to cache the property names
- // for arguments objects. Arguments objects will always have
- // elements.
- // Wrapped strings have elements, but don't have an elements
- // array or dictionary. So the fast inline test for whether to
- // use the cache says yes, so we should not create a cache.
- bool cache_enum_length =
- ((current->map()->GetConstructor() != *arguments_function) &&
- !current->IsJSValue() && !current->IsAccessCheckNeeded() &&
- !current->HasNamedInterceptor() &&
- !current->HasIndexedInterceptor());
- // Compute the property keys and cache them if possible.
- Handle<FixedArray> enum_keys =
- JSObject::GetEnumPropertyKeys(current, cache_enum_length);
- accumulator.AddKeys(enum_keys);
- } else {
- DCHECK(filter == INCLUDE_SYMBOLS);
- current->CollectOwnPropertyNames(&accumulator, attr_filter);
- }
- // Add the property keys from the interceptor.
- if (current->HasNamedInterceptor()) {
- Handle<JSObject> result;
- if (JSObject::GetKeysForNamedInterceptor(current, object)
- .ToHandle(&result)) {
- accumulator.AddKeys(result);
- }
- RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
- }
+MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
+ KeyCollectionType type,
+ KeyFilter filter,
+ GetKeysConversion keys_conversion,
+ Enumerability enum_policy) {
+ USE(ContainsOnlyValidKeys);
+ Isolate* isolate = object->GetIsolate();
+ KeyAccumulator accumulator(isolate, filter);
+ if (!GetKeys_Internal(isolate, object, object, type, filter, enum_policy,
+ &accumulator)) {
+ DCHECK(isolate->has_pending_exception());
+ return MaybeHandle<FixedArray>();
}
- Handle<FixedArray> keys = accumulator.GetKeys(getConversion);
+ Handle<FixedArray> keys = accumulator.GetKeys(keys_conversion);
DCHECK(ContainsOnlyValidKeys(keys));
return keys;
}
« no previous file with comments | « src/objects.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698