Chromium Code Reviews| 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 8157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8168 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result))); | 8168 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result))); |
| 8169 } else { | 8169 } else { |
| 8170 accumulator->AddKeys( | 8170 accumulator->AddKeys( |
| 8171 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result))); | 8171 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result))); |
| 8172 } | 8172 } |
| 8173 return true; | 8173 return true; |
| 8174 } | 8174 } |
| 8175 | 8175 |
| 8176 | 8176 |
| 8177 static bool GetKeysFromJSObject(Isolate* isolate, Handle<JSReceiver> receiver, | 8177 static bool GetKeysFromJSObject(Isolate* isolate, Handle<JSReceiver> receiver, |
| 8178 Handle<JSObject> object, PropertyFilter filter, | 8178 Handle<JSObject> object, PropertyFilter* filter, |
|
Jakob Kummerow
2015/12/04 13:39:29
If you have any better ideas than passing |filter|
Camillo Bruni
2015/12/04 14:37:16
we might want to push all of this onto the KeyAccu
| |
| 8179 JSReceiver::KeyCollectionType type, | 8179 JSReceiver::KeyCollectionType type, |
| 8180 KeyAccumulator* accumulator) { | 8180 KeyAccumulator* accumulator) { |
| 8181 accumulator->NextPrototype(); | 8181 accumulator->NextPrototype(); |
| 8182 bool keep_going = true; | |
| 8183 // Check access rights if required. | 8182 // Check access rights if required. |
| 8184 if (object->IsAccessCheckNeeded() && | 8183 if (object->IsAccessCheckNeeded() && |
| 8185 !isolate->MayAccess(handle(isolate->context()), object)) { | 8184 !isolate->MayAccess(handle(isolate->context()), object)) { |
| 8186 // The cross-origin spec says that [[Enumerate]] shall return an empty | 8185 // The cross-origin spec says that [[Enumerate]] shall return an empty |
| 8187 // iterator when it doesn't have access... | 8186 // iterator when it doesn't have access... |
| 8188 if (type == JSReceiver::INCLUDE_PROTOS) { | 8187 if (type == JSReceiver::INCLUDE_PROTOS) { |
| 8189 return false; | 8188 return false; |
| 8190 } | 8189 } |
| 8191 // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties. | 8190 // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties. |
| 8192 DCHECK(type == JSReceiver::OWN_ONLY); | 8191 DCHECK(type == JSReceiver::OWN_ONLY); |
| 8193 filter = static_cast<PropertyFilter>(filter | ONLY_ALL_CAN_READ); | 8192 *filter = static_cast<PropertyFilter>(*filter | ONLY_ALL_CAN_READ); |
| 8194 keep_going = false; | |
| 8195 | |
| 8196 // TODO(jkummerow): LayoutTests need adaptation before we can be spec | |
|
Jakob Kummerow
2015/12/04 13:39:29
Waiting for https://codereview.chromium.org/150345
| |
| 8197 // compliant. | |
| 8198 // Let [[OwnPropertyKeys]] also return an empty list for now. | |
| 8199 return false; | |
| 8200 } | 8193 } |
| 8201 | 8194 |
| 8202 JSObject::CollectOwnElementKeys(object, accumulator, filter); | 8195 JSObject::CollectOwnElementKeys(object, accumulator, *filter); |
| 8203 | 8196 |
| 8204 // Add the element keys from the interceptor. | 8197 // Add the element keys from the interceptor. |
| 8205 if (!GetKeysFromInterceptor<v8::IndexedPropertyEnumeratorCallback, kIndexed>( | 8198 if (!GetKeysFromInterceptor<v8::IndexedPropertyEnumeratorCallback, kIndexed>( |
| 8206 isolate, receiver, object, filter, accumulator)) { | 8199 isolate, receiver, object, *filter, accumulator)) { |
| 8207 DCHECK(isolate->has_pending_exception()); | 8200 DCHECK(isolate->has_pending_exception()); |
| 8208 return false; | 8201 return false; |
| 8209 } | 8202 } |
| 8210 | 8203 |
| 8211 if (filter == ENUMERABLE_STRINGS) { | 8204 if (*filter == ENUMERABLE_STRINGS) { |
| 8212 // We can cache the computed property keys if access checks are | 8205 // We can cache the computed property keys if access checks are |
| 8213 // not needed and no interceptors are involved. | 8206 // not needed and no interceptors are involved. |
| 8214 // | 8207 // |
| 8215 // We do not use the cache if the object has elements and | 8208 // We do not use the cache if the object has elements and |
| 8216 // therefore it does not make sense to cache the property names | 8209 // therefore it does not make sense to cache the property names |
| 8217 // for arguments objects. Arguments objects will always have | 8210 // for arguments objects. Arguments objects will always have |
| 8218 // elements. | 8211 // elements. |
| 8219 // Wrapped strings have elements, but don't have an elements | 8212 // Wrapped strings have elements, but don't have an elements |
| 8220 // array or dictionary. So the fast inline test for whether to | 8213 // array or dictionary. So the fast inline test for whether to |
| 8221 // use the cache says yes, so we should not create a cache. | 8214 // use the cache says yes, so we should not create a cache. |
| 8222 Handle<JSFunction> arguments_function( | 8215 Handle<JSFunction> arguments_function( |
| 8223 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); | 8216 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); |
| 8224 bool cache_enum_length = | 8217 bool cache_enum_length = |
| 8225 ((object->map()->GetConstructor() != *arguments_function) && | 8218 ((object->map()->GetConstructor() != *arguments_function) && |
| 8226 !object->IsJSValue() && !object->IsAccessCheckNeeded() && | 8219 !object->IsJSValue() && !object->IsAccessCheckNeeded() && |
| 8227 !object->HasNamedInterceptor() && !object->HasIndexedInterceptor()); | 8220 !object->HasNamedInterceptor() && !object->HasIndexedInterceptor()); |
| 8228 // Compute the property keys and cache them if possible. | 8221 // Compute the property keys and cache them if possible. |
| 8229 Handle<FixedArray> enum_keys = | 8222 Handle<FixedArray> enum_keys = |
| 8230 JSObject::GetEnumPropertyKeys(object, cache_enum_length); | 8223 JSObject::GetEnumPropertyKeys(object, cache_enum_length); |
| 8231 accumulator->AddKeys(enum_keys); | 8224 accumulator->AddKeys(enum_keys); |
| 8232 } else { | 8225 } else { |
| 8233 object->CollectOwnPropertyNames(accumulator, filter); | 8226 object->CollectOwnPropertyNames(accumulator, *filter); |
| 8234 } | 8227 } |
| 8235 | 8228 |
| 8236 // Add the property keys from the interceptor. | 8229 // Add the property keys from the interceptor. |
| 8237 if (!GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback, | 8230 if (!GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback, |
| 8238 kNamed>(isolate, receiver, object, filter, | 8231 kNamed>(isolate, receiver, object, *filter, |
| 8239 accumulator)) { | 8232 accumulator)) { |
| 8240 DCHECK(isolate->has_pending_exception()); | 8233 DCHECK(isolate->has_pending_exception()); |
| 8241 return false; | 8234 return false; |
| 8242 } | 8235 } |
| 8243 return keep_going; | 8236 return true; |
| 8244 } | 8237 } |
| 8245 | 8238 |
| 8246 | 8239 |
| 8247 // Helper function for JSReceiver::GetKeys() below. Can be called recursively. | 8240 // Helper function for JSReceiver::GetKeys() below. Can be called recursively. |
| 8248 // Returns false iff an exception was thrown. | 8241 // Returns false iff an exception was thrown. |
| 8249 static bool GetKeys_Internal(Isolate* isolate, Handle<JSReceiver> receiver, | 8242 static bool GetKeys_Internal(Isolate* isolate, Handle<JSReceiver> receiver, |
| 8250 Handle<JSReceiver> object, | 8243 Handle<JSReceiver> object, |
| 8251 JSReceiver::KeyCollectionType type, | 8244 JSReceiver::KeyCollectionType type, |
| 8252 PropertyFilter filter, | 8245 PropertyFilter filter, |
| 8253 KeyAccumulator* accumulator) { | 8246 KeyAccumulator* accumulator) { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 8266 Handle<JSProxy>::cast(current), | 8259 Handle<JSProxy>::cast(current), |
| 8267 filter, accumulator); | 8260 filter, accumulator); |
| 8268 } else { | 8261 } else { |
| 8269 DCHECK(type == JSReceiver::INCLUDE_PROTOS); | 8262 DCHECK(type == JSReceiver::INCLUDE_PROTOS); |
| 8270 result = JSProxy::Enumerate( | 8263 result = JSProxy::Enumerate( |
| 8271 isolate, receiver, Handle<JSProxy>::cast(current), accumulator); | 8264 isolate, receiver, Handle<JSProxy>::cast(current), accumulator); |
| 8272 } | 8265 } |
| 8273 } else { | 8266 } else { |
| 8274 DCHECK(current->IsJSObject()); | 8267 DCHECK(current->IsJSObject()); |
| 8275 result = GetKeysFromJSObject(isolate, receiver, | 8268 result = GetKeysFromJSObject(isolate, receiver, |
| 8276 Handle<JSObject>::cast(current), filter, | 8269 Handle<JSObject>::cast(current), &filter, |
| 8277 type, accumulator); | 8270 type, accumulator); |
| 8278 } | 8271 } |
| 8279 if (!result) { | 8272 if (!result) { |
| 8280 if (isolate->has_pending_exception()) { | 8273 if (isolate->has_pending_exception()) { |
| 8281 return false; | 8274 return false; |
| 8282 } | 8275 } |
| 8283 // If there was no exception, then "false" means "stop iterating". | 8276 // If there was no exception, then "false" means "stop iterating". |
| 8284 break; | 8277 break; |
| 8285 } | 8278 } |
| 8286 } | 8279 } |
| (...skipping 7360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 15647 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 15640 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 15648 if (result.IsEmpty()) return isolate->factory()->undefined_value(); | 15641 if (result.IsEmpty()) return isolate->factory()->undefined_value(); |
| 15649 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | 15642 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
| 15650 result_internal->VerifyApiCallResultType(); | 15643 result_internal->VerifyApiCallResultType(); |
| 15651 *done = true; | 15644 *done = true; |
| 15652 // Rebox handle before return | 15645 // Rebox handle before return |
| 15653 return handle(*result_internal, isolate); | 15646 return handle(*result_internal, isolate); |
| 15654 } | 15647 } |
| 15655 | 15648 |
| 15656 | 15649 |
| 15657 // Compute the property keys from the interceptor. | |
| 15658 // TODO(jkummerow): Deprecated. | |
| 15659 MaybeHandle<JSObject> JSObject::GetKeysForNamedInterceptor( | |
| 15660 Handle<JSObject> object, Handle<JSReceiver> receiver) { | |
| 15661 Isolate* isolate = receiver->GetIsolate(); | |
| 15662 Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor()); | |
| 15663 PropertyCallbackArguments | |
| 15664 args(isolate, interceptor->data(), *receiver, *object); | |
| 15665 v8::Local<v8::Object> result; | |
| 15666 if (!interceptor->enumerator()->IsUndefined()) { | |
| 15667 v8::GenericNamedPropertyEnumeratorCallback enum_fun = | |
| 15668 v8::ToCData<v8::GenericNamedPropertyEnumeratorCallback>( | |
| 15669 interceptor->enumerator()); | |
| 15670 LOG(isolate, ApiObjectAccess("interceptor-named-enum", *object)); | |
| 15671 result = args.Call(enum_fun); | |
| 15672 } | |
| 15673 if (result.IsEmpty()) return MaybeHandle<JSObject>(); | |
| 15674 DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() || | |
| 15675 (v8::Utils::OpenHandle(*result)->IsJSObject() && | |
| 15676 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result)) | |
| 15677 ->HasSloppyArgumentsElements())); | |
| 15678 // Rebox before returning. | |
| 15679 return handle(JSObject::cast(*v8::Utils::OpenHandle(*result)), isolate); | |
| 15680 } | |
| 15681 | |
| 15682 | |
| 15683 // Compute the element keys from the interceptor. | |
| 15684 // TODO(jkummerow): Deprecated. | |
| 15685 MaybeHandle<JSObject> JSObject::GetKeysForIndexedInterceptor( | |
| 15686 Handle<JSObject> object, Handle<JSReceiver> receiver) { | |
| 15687 Isolate* isolate = receiver->GetIsolate(); | |
| 15688 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor()); | |
| 15689 PropertyCallbackArguments | |
| 15690 args(isolate, interceptor->data(), *receiver, *object); | |
| 15691 v8::Local<v8::Object> result; | |
| 15692 if (!interceptor->enumerator()->IsUndefined()) { | |
| 15693 v8::IndexedPropertyEnumeratorCallback enum_fun = | |
| 15694 v8::ToCData<v8::IndexedPropertyEnumeratorCallback>( | |
| 15695 interceptor->enumerator()); | |
| 15696 LOG(isolate, ApiObjectAccess("interceptor-indexed-enum", *object)); | |
| 15697 result = args.Call(enum_fun); | |
| 15698 } | |
| 15699 if (result.IsEmpty()) return MaybeHandle<JSObject>(); | |
| 15700 DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() || | |
| 15701 (v8::Utils::OpenHandle(*result)->IsJSObject() && | |
| 15702 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result)) | |
| 15703 ->HasSloppyArgumentsElements())); | |
| 15704 // Rebox before returning. | |
| 15705 return handle(JSObject::cast(*v8::Utils::OpenHandle(*result)), isolate); | |
| 15706 } | |
| 15707 | |
| 15708 | |
| 15709 Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object, | 15650 Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object, |
| 15710 Handle<Name> name) { | 15651 Handle<Name> name) { |
| 15711 LookupIterator it = LookupIterator::PropertyOrElement( | 15652 LookupIterator it = LookupIterator::PropertyOrElement( |
| 15712 name->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); | 15653 name->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); |
| 15713 return HasProperty(&it); | 15654 return HasProperty(&it); |
| 15714 } | 15655 } |
| 15715 | 15656 |
| 15716 | 15657 |
| 15717 Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject> object, | 15658 Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject> object, |
| 15718 uint32_t index) { | 15659 uint32_t index) { |
| (...skipping 2183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 17902 Dictionary<Derived, Shape, Key>* raw_dict = *dictionary; | 17843 Dictionary<Derived, Shape, Key>* raw_dict = *dictionary; |
| 17903 for (int i = 0; i < capacity; i++) { | 17844 for (int i = 0; i < capacity; i++) { |
| 17904 Object* k = raw_dict->KeyAt(i); | 17845 Object* k = raw_dict->KeyAt(i); |
| 17905 if (!raw_dict->IsKey(k) || k->FilterKey(filter)) continue; | 17846 if (!raw_dict->IsKey(k) || k->FilterKey(filter)) continue; |
| 17906 if (raw_dict->IsDeleted(i)) continue; | 17847 if (raw_dict->IsDeleted(i)) continue; |
| 17907 PropertyDetails details = raw_dict->DetailsAt(i); | 17848 PropertyDetails details = raw_dict->DetailsAt(i); |
| 17908 if ((details.attributes() & filter) != 0) continue; | 17849 if ((details.attributes() & filter) != 0) continue; |
| 17909 if (filter & ONLY_ALL_CAN_READ) { | 17850 if (filter & ONLY_ALL_CAN_READ) { |
| 17910 if (details.kind() != kAccessor) continue; | 17851 if (details.kind() != kAccessor) continue; |
| 17911 Object* accessors = raw_dict->ValueAt(i); | 17852 Object* accessors = raw_dict->ValueAt(i); |
| 17853 if (accessors->IsPropertyCell()) { | |
|
Jakob Kummerow
2015/12/04 13:39:29
cf. line 17883.
| |
| 17854 accessors = PropertyCell::cast(accessors)->value(); | |
| 17855 } | |
| 17912 if (!accessors->IsAccessorInfo()) continue; | 17856 if (!accessors->IsAccessorInfo()) continue; |
| 17913 if (!AccessorInfo::cast(accessors)->all_can_read()) continue; | 17857 if (!AccessorInfo::cast(accessors)->all_can_read()) continue; |
| 17914 } | 17858 } |
| 17915 array->set(array_size++, Smi::FromInt(i)); | 17859 array->set(array_size++, Smi::FromInt(i)); |
| 17916 } | 17860 } |
| 17917 | 17861 |
| 17918 EnumIndexComparator<Derived> cmp(static_cast<Derived*>(raw_dict)); | 17862 EnumIndexComparator<Derived> cmp(static_cast<Derived*>(raw_dict)); |
| 17919 Smi** start = reinterpret_cast<Smi**>(array->GetFirstElementAddress()); | 17863 Smi** start = reinterpret_cast<Smi**>(array->GetFirstElementAddress()); |
| 17920 std::sort(start, start + array_size, cmp); | 17864 std::sort(start, start + array_size, cmp); |
| 17921 } | 17865 } |
| (...skipping 1207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 19129 if (cell->value() != *new_value) { | 19073 if (cell->value() != *new_value) { |
| 19130 cell->set_value(*new_value); | 19074 cell->set_value(*new_value); |
| 19131 Isolate* isolate = cell->GetIsolate(); | 19075 Isolate* isolate = cell->GetIsolate(); |
| 19132 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19076 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 19133 isolate, DependentCode::kPropertyCellChangedGroup); | 19077 isolate, DependentCode::kPropertyCellChangedGroup); |
| 19134 } | 19078 } |
| 19135 } | 19079 } |
| 19136 | 19080 |
| 19137 } // namespace internal | 19081 } // namespace internal |
| 19138 } // namespace v8 | 19082 } // namespace v8 |
| OLD | NEW |