OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/objects.h" | 5 #include "src/objects.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <iomanip> | 8 #include <iomanip> |
9 #include <sstream> | 9 #include <sstream> |
10 | 10 |
(...skipping 7947 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7958 if (length == 0) { | 7958 if (length == 0) { |
7959 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); | 7959 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); |
7960 } | 7960 } |
7961 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); | 7961 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); |
7962 dictionary->CopyEnumKeysTo(*storage); | 7962 dictionary->CopyEnumKeysTo(*storage); |
7963 return storage; | 7963 return storage; |
7964 } | 7964 } |
7965 } | 7965 } |
7966 | 7966 |
7967 | 7967 |
7968 static bool GetKeysFromJSObject(Isolate* isolate, Handle<JSReceiver> receiver, | |
7969 Handle<JSObject> object, KeyFilter filter, | |
7970 Enumerability enum_policy, | |
7971 KeyAccumulator* accumulator) { | |
7972 // Check access rights if required. | |
7973 if (object->IsAccessCheckNeeded() && | |
7974 !isolate->MayAccess(handle(isolate->context()), object)) { | |
7975 // TODO(jkummerow): Get whitelisted (all-can-read) keys. | |
7976 // It's probably best to implement a "GetKeysWithFailedAccessCheck" | |
7977 // helper, which will need to look at both interceptors and accessors. | |
7978 return false; | |
7979 } | |
7980 | |
7981 PropertyAttributes attr_filter = static_cast<PropertyAttributes>( | |
7982 (enum_policy == RESPECT_ENUMERABILITY ? DONT_ENUM : NONE) | | |
7983 PRIVATE_SYMBOL); | |
7984 | |
7985 JSObject::CollectOwnElementKeys(object, accumulator, attr_filter); | |
7986 | |
7987 // Add the element keys from the interceptor. | |
7988 if (object->HasIndexedInterceptor()) { | |
7989 Handle<JSObject> result; | |
7990 if (JSObject::GetKeysForIndexedInterceptor(object, receiver) | |
7991 .ToHandle(&result)) { | |
7992 accumulator->AddElementKeysFromInterceptor(result); | |
7993 } | |
7994 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, false); | |
7995 } | |
7996 | |
7997 if (filter == SKIP_SYMBOLS) { | |
7998 if (enum_policy == IGNORE_ENUMERABILITY) UNIMPLEMENTED(); | |
7999 | |
8000 // We can cache the computed property keys if access checks are | |
8001 // not needed and no interceptors are involved. | |
8002 // | |
8003 // We do not use the cache if the object has elements and | |
8004 // therefore it does not make sense to cache the property names | |
8005 // for arguments objects. Arguments objects will always have | |
8006 // elements. | |
8007 // Wrapped strings have elements, but don't have an elements | |
8008 // array or dictionary. So the fast inline test for whether to | |
8009 // use the cache says yes, so we should not create a cache. | |
8010 Handle<JSFunction> arguments_function( | |
8011 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); | |
8012 bool cache_enum_length = | |
8013 ((object->map()->GetConstructor() != *arguments_function) && | |
8014 !object->IsJSValue() && !object->IsAccessCheckNeeded() && | |
8015 !object->HasNamedInterceptor() && !object->HasIndexedInterceptor()); | |
8016 // Compute the property keys and cache them if possible. | |
8017 Handle<FixedArray> enum_keys = | |
8018 JSObject::GetEnumPropertyKeys(object, cache_enum_length); | |
8019 accumulator->AddKeys(enum_keys); | |
8020 } else { | |
8021 DCHECK(filter == INCLUDE_SYMBOLS); | |
8022 object->CollectOwnPropertyNames(accumulator, attr_filter); | |
8023 } | |
8024 | |
8025 // Add the property keys from the interceptor. | |
8026 if (object->HasNamedInterceptor()) { | |
8027 Handle<JSObject> result; | |
8028 if (JSObject::GetKeysForNamedInterceptor(object, receiver) | |
8029 .ToHandle(&result)) { | |
8030 accumulator->AddKeys(result); | |
8031 } | |
8032 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, false); | |
8033 } | |
8034 return true; | |
8035 } | |
8036 | |
8037 | |
8038 static bool GetKeysFromJSProxy(Isolate* isolate, Handle<JSReceiver> receiver, | |
8039 Handle<JSProxy> proxy, KeyFilter filter, | |
8040 Enumerability enum_policy, | |
8041 KeyAccumulator* accumulator) { | |
8042 Handle<Object> args[] = {proxy}; | |
8043 Handle<Object> names; | |
8044 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
8045 isolate, names, Execution::Call(isolate, isolate->proxy_enumerate(), | |
8046 proxy, arraysize(args), args), | |
8047 false); | |
8048 accumulator->AddKeysFromProxy(Handle<JSObject>::cast(names)); | |
8049 return true; | |
8050 } | |
8051 | |
8052 | |
8053 // Returns false if an exception was thrown, or if prototype iteration | |
8054 // should not continue. | |
8055 static bool GetKeysFromJSReceiver(Isolate* isolate, Handle<JSReceiver> receiver, | |
Jakob Kummerow
2015/11/25 11:33:47
We'll need this entry point so that the new GetKey
| |
8056 Handle<JSReceiver> object, KeyFilter filter, | |
8057 Enumerability enum_policy, | |
8058 KeyAccumulator* accumulator) { | |
8059 if (object->IsJSProxy()) { | |
8060 return GetKeysFromJSProxy(isolate, receiver, Handle<JSProxy>::cast(object), | |
8061 filter, enum_policy, accumulator); | |
8062 } | |
8063 return GetKeysFromJSObject(isolate, receiver, Handle<JSObject>::cast(object), | |
8064 filter, enum_policy, accumulator); | |
8065 } | |
8066 | |
8067 | |
7968 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, | 8068 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
7969 KeyCollectionType type, | 8069 KeyCollectionType type, |
7970 KeyFilter filter, | 8070 KeyFilter filter, |
7971 GetKeysConversion getConversion, | 8071 GetKeysConversion keys_conversion, |
7972 Enumerability enum_policy) { | 8072 Enumerability enum_policy) { |
7973 USE(ContainsOnlyValidKeys); | 8073 USE(ContainsOnlyValidKeys); |
7974 Isolate* isolate = object->GetIsolate(); | 8074 Isolate* isolate = object->GetIsolate(); |
7975 KeyAccumulator accumulator(isolate, filter); | 8075 KeyAccumulator accumulator(isolate, filter); |
7976 Handle<JSFunction> arguments_function( | |
7977 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); | |
7978 PrototypeIterator::WhereToEnd end = type == OWN_ONLY | 8076 PrototypeIterator::WhereToEnd end = type == OWN_ONLY |
7979 ? PrototypeIterator::END_AT_NON_HIDDEN | 8077 ? PrototypeIterator::END_AT_NON_HIDDEN |
7980 : PrototypeIterator::END_AT_NULL; | 8078 : PrototypeIterator::END_AT_NULL; |
7981 PropertyAttributes attr_filter = static_cast<PropertyAttributes>( | |
7982 (enum_policy == RESPECT_ENUMERABILITY ? DONT_ENUM : NONE) | | |
7983 PRIVATE_SYMBOL); | |
7984 | |
7985 // Only collect keys if access is permitted. | |
7986 for (PrototypeIterator iter(isolate, object, | 8079 for (PrototypeIterator iter(isolate, object, |
7987 PrototypeIterator::START_AT_RECEIVER); | 8080 PrototypeIterator::START_AT_RECEIVER); |
7988 !iter.IsAtEnd(end); iter.Advance()) { | 8081 !iter.IsAtEnd(end); iter.Advance()) { |
7989 accumulator.NextPrototype(); | 8082 accumulator.NextPrototype(); |
7990 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { | 8083 if (!GetKeysFromJSReceiver(isolate, object, |
7991 Handle<JSProxy> proxy = PrototypeIterator::GetCurrent<JSProxy>(iter); | 8084 PrototypeIterator::GetCurrent<JSReceiver>(iter), |
7992 Handle<Object> args[] = { proxy }; | 8085 filter, enum_policy, &accumulator)) { |
7993 Handle<Object> names; | 8086 if (isolate->has_pending_exception()) { |
7994 ASSIGN_RETURN_ON_EXCEPTION( | 8087 return MaybeHandle<FixedArray>(); |
7995 isolate, names, | 8088 } |
7996 Execution::Call(isolate, | 8089 // If there was no exception, then "false" means "stop iterating". |
7997 isolate->proxy_enumerate(), | |
7998 object, | |
7999 arraysize(args), | |
8000 args), | |
8001 FixedArray); | |
8002 accumulator.AddKeysFromProxy(Handle<JSObject>::cast(names)); | |
8003 break; | 8090 break; |
8004 } | 8091 } |
8005 | |
8006 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter); | |
8007 | |
8008 // Check access rights if required. | |
8009 if (current->IsAccessCheckNeeded() && | |
8010 !isolate->MayAccess(handle(isolate->context()), current)) { | |
8011 if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { | |
Jakob Kummerow
2015/11/25 11:33:47
I've dropped this condition as discussed, because
| |
8012 isolate->ReportFailedAccessCheck(current); | |
8013 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); | |
8014 } | |
8015 break; | |
8016 } | |
8017 | |
8018 JSObject::CollectOwnElementKeys(current, &accumulator, attr_filter); | |
8019 | |
8020 // Add the element keys from the interceptor. | |
8021 if (current->HasIndexedInterceptor()) { | |
8022 Handle<JSObject> result; | |
8023 if (JSObject::GetKeysForIndexedInterceptor(current, object) | |
8024 .ToHandle(&result)) { | |
8025 accumulator.AddElementKeysFromInterceptor(result); | |
8026 } | |
8027 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); | |
8028 } | |
8029 | |
8030 if (filter == SKIP_SYMBOLS) { | |
8031 if (enum_policy == IGNORE_ENUMERABILITY) UNIMPLEMENTED(); | |
8032 | |
8033 // We can cache the computed property keys if access checks are | |
8034 // not needed and no interceptors are involved. | |
8035 // | |
8036 // We do not use the cache if the object has elements and | |
8037 // therefore it does not make sense to cache the property names | |
8038 // for arguments objects. Arguments objects will always have | |
8039 // elements. | |
8040 // Wrapped strings have elements, but don't have an elements | |
8041 // array or dictionary. So the fast inline test for whether to | |
8042 // use the cache says yes, so we should not create a cache. | |
8043 bool cache_enum_length = | |
8044 ((current->map()->GetConstructor() != *arguments_function) && | |
8045 !current->IsJSValue() && !current->IsAccessCheckNeeded() && | |
8046 !current->HasNamedInterceptor() && | |
8047 !current->HasIndexedInterceptor()); | |
8048 // Compute the property keys and cache them if possible. | |
8049 Handle<FixedArray> enum_keys = | |
8050 JSObject::GetEnumPropertyKeys(current, cache_enum_length); | |
8051 accumulator.AddKeys(enum_keys); | |
8052 } else { | |
8053 DCHECK(filter == INCLUDE_SYMBOLS); | |
8054 current->CollectOwnPropertyNames(&accumulator, attr_filter); | |
8055 } | |
8056 | |
8057 // Add the property keys from the interceptor. | |
8058 if (current->HasNamedInterceptor()) { | |
8059 Handle<JSObject> result; | |
8060 if (JSObject::GetKeysForNamedInterceptor(current, object) | |
8061 .ToHandle(&result)) { | |
8062 accumulator.AddKeys(result); | |
8063 } | |
8064 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); | |
8065 } | |
8066 } | 8092 } |
8067 | 8093 |
8068 Handle<FixedArray> keys = accumulator.GetKeys(getConversion); | 8094 Handle<FixedArray> keys = accumulator.GetKeys(keys_conversion); |
8069 DCHECK(ContainsOnlyValidKeys(keys)); | 8095 DCHECK(ContainsOnlyValidKeys(keys)); |
8070 return keys; | 8096 return keys; |
8071 } | 8097 } |
8072 | 8098 |
8073 | 8099 |
8074 bool Map::DictionaryElementsInPrototypeChainOnly() { | 8100 bool Map::DictionaryElementsInPrototypeChainOnly() { |
8075 if (IsDictionaryElementsKind(elements_kind())) { | 8101 if (IsDictionaryElementsKind(elements_kind())) { |
8076 return false; | 8102 return false; |
8077 } | 8103 } |
8078 | 8104 |
(...skipping 10469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
18548 if (cell->value() != *new_value) { | 18574 if (cell->value() != *new_value) { |
18549 cell->set_value(*new_value); | 18575 cell->set_value(*new_value); |
18550 Isolate* isolate = cell->GetIsolate(); | 18576 Isolate* isolate = cell->GetIsolate(); |
18551 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 18577 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
18552 isolate, DependentCode::kPropertyCellChangedGroup); | 18578 isolate, DependentCode::kPropertyCellChangedGroup); |
18553 } | 18579 } |
18554 } | 18580 } |
18555 | 18581 |
18556 } // namespace internal | 18582 } // namespace internal |
18557 } // namespace v8 | 18583 } // namespace v8 |
OLD | NEW |