LCOV - code coverage report
Current view: top level - src/debug - debug-property-iterator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 101 102 99.0 %
Date: 2019-02-19 Functions: 19 19 100.0 %

          Line data    Source code
       1             : // Copyright 2018 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/debug/debug-property-iterator.h"
       6             : 
       7             : #include "src/api-inl.h"
       8             : #include "src/base/flags.h"
       9             : #include "src/keys.h"
      10             : #include "src/objects/js-array-buffer-inl.h"
      11             : #include "src/property-descriptor.h"
      12             : #include "src/property-details.h"
      13             : 
      14             : namespace v8 {
      15             : 
      16       79158 : std::unique_ptr<debug::PropertyIterator> debug::PropertyIterator::Create(
      17             :     v8::Local<v8::Object> v8_object) {
      18             :   internal::Isolate* isolate =
      19       79158 :       reinterpret_cast<internal::Isolate*>(v8_object->GetIsolate());
      20             :   return std::unique_ptr<debug::PropertyIterator>(
      21             :       new internal::DebugPropertyIterator(isolate,
      22      158316 :                                           Utils::OpenHandle(*v8_object)));
      23             : }
      24             : 
      25             : namespace internal {
      26             : 
      27       79158 : DebugPropertyIterator::DebugPropertyIterator(Isolate* isolate,
      28             :                                              Handle<JSReceiver> receiver)
      29             :     : isolate_(isolate),
      30             :       prototype_iterator_(isolate, receiver, kStartAtReceiver,
      31      237474 :                           PrototypeIterator::END_AT_NULL) {
      32      158316 :   if (receiver->IsJSProxy()) {
      33          15 :     is_own_ = false;
      34          15 :     prototype_iterator_.AdvanceIgnoringProxies();
      35             :   }
      36      158316 :   if (prototype_iterator_.IsAtEnd()) return;
      37       79143 :   FillKeysForCurrentPrototypeAndStage();
      38       79143 :   if (should_move_to_next_stage()) Advance();
      39             : }
      40             : 
      41     4548691 : bool DebugPropertyIterator::Done() const {
      42     4548691 :   return prototype_iterator_.IsAtEnd();
      43             : }
      44             : 
      45     4548591 : void DebugPropertyIterator::Advance() {
      46     4548591 :   ++current_key_index_;
      47     4548591 :   calculated_native_accessor_flags_ = false;
      48     9428145 :   while (should_move_to_next_stage()) {
      49      330963 :     switch (stage_) {
      50             :       case Stage::kExoticIndices:
      51      123812 :         stage_ = Stage::kEnumerableStrings;
      52      123812 :         break;
      53             :       case Stage::kEnumerableStrings:
      54      105904 :         stage_ = Stage::kAllProperties;
      55      105904 :         break;
      56             :       case Stage::kAllProperties:
      57      101247 :         stage_ = kExoticIndices;
      58      101247 :         is_own_ = false;
      59      101247 :         prototype_iterator_.AdvanceIgnoringProxies();
      60      101247 :         break;
      61             :     }
      62      330963 :     FillKeysForCurrentPrototypeAndStage();
      63             :   }
      64     4548591 : }
      65             : 
      66     2993733 : bool DebugPropertyIterator::is_native_accessor() {
      67     2993733 :   if (stage_ == kExoticIndices) return false;
      68     2992462 :   CalculateNativeAccessorFlags();
      69     2992462 :   return native_accessor_flags_;
      70             : }
      71             : 
      72          20 : bool DebugPropertyIterator::has_native_getter() {
      73          20 :   if (stage_ == kExoticIndices) return false;
      74          20 :   CalculateNativeAccessorFlags();
      75          20 :   return native_accessor_flags_ &
      76          20 :          static_cast<int>(debug::NativeAccessorType::HasGetter);
      77             : }
      78             : 
      79          20 : bool DebugPropertyIterator::has_native_setter() {
      80          20 :   if (stage_ == kExoticIndices) return false;
      81          20 :   CalculateNativeAccessorFlags();
      82          20 :   return native_accessor_flags_ &
      83          20 :          static_cast<int>(debug::NativeAccessorType::HasSetter);
      84             : }
      85             : 
      86    16441938 : Handle<Name> DebugPropertyIterator::raw_name() const {
      87             :   DCHECK(!Done());
      88    16441938 :   if (stage_ == kExoticIndices) {
      89        3813 :     return isolate_->factory()->Uint32ToString(current_key_index_);
      90             :   } else {
      91             :     return Handle<Name>::cast(
      92    32876250 :         FixedArray::get(*keys_, current_key_index_, isolate_));
      93             :   }
      94             : }
      95             : 
      96     4469578 : v8::Local<v8::Name> DebugPropertyIterator::name() const {
      97     4469578 :   return Utils::ToLocal(raw_name());
      98             : }
      99             : 
     100     2993733 : v8::Maybe<v8::PropertyAttribute> DebugPropertyIterator::attributes() {
     101             :   Handle<JSReceiver> receiver =
     102     2993733 :       PrototypeIterator::GetCurrent<JSReceiver>(prototype_iterator_);
     103     2993733 :   auto result = JSReceiver::GetPropertyAttributes(receiver, raw_name());
     104     2993733 :   if (result.IsNothing()) return Nothing<v8::PropertyAttribute>();
     105             :   DCHECK(result.FromJust() != ABSENT);
     106             :   return Just(static_cast<v8::PropertyAttribute>(result.FromJust()));
     107             : }
     108             : 
     109     2993713 : v8::Maybe<v8::debug::PropertyDescriptor> DebugPropertyIterator::descriptor() {
     110             :   Handle<JSReceiver> receiver =
     111     2993713 :       PrototypeIterator::GetCurrent<JSReceiver>(prototype_iterator_);
     112             : 
     113             :   PropertyDescriptor descriptor;
     114             :   Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
     115     5987426 :       isolate_, receiver, raw_name(), &descriptor);
     116     2993713 :   if (did_get_descriptor.IsNothing()) {
     117             :     return Nothing<v8::debug::PropertyDescriptor>();
     118             :   }
     119             :   DCHECK(did_get_descriptor.FromJust());
     120             :   return Just(v8::debug::PropertyDescriptor{
     121             :       descriptor.enumerable(), descriptor.has_enumerable(),
     122             :       descriptor.configurable(), descriptor.has_configurable(),
     123             :       descriptor.writable(), descriptor.has_writable(),
     124             :       descriptor.has_value() ? Utils::ToLocal(descriptor.value())
     125             :                              : v8::Local<v8::Value>(),
     126             :       descriptor.has_get() ? Utils::ToLocal(descriptor.get())
     127             :                            : v8::Local<v8::Value>(),
     128             :       descriptor.has_set() ? Utils::ToLocal(descriptor.set())
     129             :                            : v8::Local<v8::Value>(),
     130     8981139 :   });
     131             : }
     132             : 
     133     4492108 : bool DebugPropertyIterator::is_own() { return is_own_; }
     134             : 
     135     2993723 : bool DebugPropertyIterator::is_array_index() {
     136     2993723 :   if (stage_ == kExoticIndices) return true;
     137     2992452 :   uint32_t index = 0;
     138     5984904 :   return raw_name()->AsArrayIndex(&index);
     139             : }
     140             : 
     141      410106 : void DebugPropertyIterator::FillKeysForCurrentPrototypeAndStage() {
     142      410106 :   current_key_index_ = 0;
     143      410106 :   exotic_length_ = 0;
     144      410106 :   keys_ = Handle<FixedArray>::null();
     145      410106 :   if (prototype_iterator_.IsAtEnd()) return;
     146             :   Handle<JSReceiver> receiver =
     147             :       PrototypeIterator::GetCurrent<JSReceiver>(prototype_iterator_);
     148      707076 :   bool has_exotic_indices = receiver->IsJSTypedArray();
     149      353538 :   if (stage_ == kExoticIndices) {
     150      123822 :     if (!has_exotic_indices) return;
     151             :     exotic_length_ = static_cast<uint32_t>(
     152         206 :         Handle<JSTypedArray>::cast(receiver)->length_value());
     153         103 :     return;
     154             :   }
     155             :   bool skip_indices = has_exotic_indices;
     156             :   PropertyFilter filter =
     157      229716 :       stage_ == kEnumerableStrings ? ENUMERABLE_STRINGS : ALL_PROPERTIES;
     158      229716 :   if (!KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly, filter,
     159             :                                GetKeysConversion::kConvertToString, false,
     160      229716 :                                skip_indices)
     161      689148 :            .ToHandle(&keys_)) {
     162           0 :     keys_ = Handle<FixedArray>::null();
     163             :   }
     164             : }
     165             : 
     166     4958697 : bool DebugPropertyIterator::should_move_to_next_stage() const {
     167     4958697 :   if (prototype_iterator_.IsAtEnd()) return false;
     168     4902129 :   if (stage_ == kExoticIndices) return current_key_index_ >= exotic_length_;
     169     9395976 :   return keys_.is_null() ||
     170    14093964 :          current_key_index_ >= static_cast<uint32_t>(keys_->length());
     171             : }
     172             : 
     173             : namespace {
     174     2992462 : base::Flags<debug::NativeAccessorType, int> GetNativeAccessorDescriptorInternal(
     175             :     Handle<JSReceiver> object, Handle<Name> name) {
     176             :   uint32_t index;
     177     2992462 :   if (name->AsArrayIndex(&index)) return debug::NativeAccessorType::None;
     178             :   LookupIterator it =
     179     2960986 :       LookupIterator(object->GetIsolate(), object, name, LookupIterator::OWN);
     180     2960986 :   if (!it.IsFound()) return debug::NativeAccessorType::None;
     181     2960986 :   if (it.state() != LookupIterator::ACCESSOR) {
     182     2919449 :     return debug::NativeAccessorType::None;
     183             :   }
     184       41537 :   Handle<Object> structure = it.GetAccessors();
     185       83074 :   if (!structure->IsAccessorInfo()) return debug::NativeAccessorType::None;
     186             :   auto isolate = object->GetIsolate();
     187             :   base::Flags<debug::NativeAccessorType, int> result;
     188             : #define IS_BUILTIN_ACESSOR(_, name, ...)                    \
     189             :   if (*structure == *isolate->factory()->name##_accessor()) \
     190             :     return debug::NativeAccessorType::None;
     191       23899 :   ACCESSOR_INFO_LIST_GENERATOR(IS_BUILTIN_ACESSOR, /* not used */)
     192             : #undef IS_BUILTIN_ACESSOR
     193          20 :   Handle<AccessorInfo> accessor_info = Handle<AccessorInfo>::cast(structure);
     194          20 :   if (accessor_info->getter() != Object()) {
     195             :     result |= debug::NativeAccessorType::HasGetter;
     196             :   }
     197          20 :   if (accessor_info->setter() != Object()) {
     198             :     result |= debug::NativeAccessorType::HasSetter;
     199             :   }
     200          20 :   return result;
     201             : }
     202             : }  // anonymous namespace
     203             : 
     204     2992502 : void DebugPropertyIterator::CalculateNativeAccessorFlags() {
     205     2992542 :   if (calculated_native_accessor_flags_) return;
     206             :   Handle<JSReceiver> receiver =
     207     2992462 :       PrototypeIterator::GetCurrent<JSReceiver>(prototype_iterator_);
     208     5984924 :   native_accessor_flags_ =
     209     5984924 :       GetNativeAccessorDescriptorInternal(receiver, raw_name());
     210     2992462 :   calculated_native_accessor_flags_ = true;
     211             : }
     212             : }  // namespace internal
     213      178779 : }  // namespace v8

Generated by: LCOV version 1.10