LCOV - code coverage report
Current view: top level - src/debug - debug-property-iterator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 96 98 98.0 %
Date: 2019-04-18 Functions: 17 18 94.4 %

          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       79268 : std::unique_ptr<debug::PropertyIterator> debug::PropertyIterator::Create(
      17             :     v8::Local<v8::Object> v8_object) {
      18             :   internal::Isolate* isolate =
      19       79268 :       reinterpret_cast<internal::Isolate*>(v8_object->GetIsolate());
      20             :   return std::unique_ptr<debug::PropertyIterator>(
      21             :       new internal::DebugPropertyIterator(isolate,
      22      158536 :                                           Utils::OpenHandle(*v8_object)));
      23             : }
      24             : 
      25             : namespace internal {
      26             : 
      27       79268 : DebugPropertyIterator::DebugPropertyIterator(Isolate* isolate,
      28             :                                              Handle<JSReceiver> receiver)
      29             :     : isolate_(isolate),
      30             :       prototype_iterator_(isolate, receiver, kStartAtReceiver,
      31      237804 :                           PrototypeIterator::END_AT_NULL) {
      32       79268 :   if (receiver->IsJSProxy()) {
      33          20 :     is_own_ = false;
      34          20 :     prototype_iterator_.AdvanceIgnoringProxies();
      35             :   }
      36       79268 :   if (prototype_iterator_.IsAtEnd()) return;
      37       79248 :   FillKeysForCurrentPrototypeAndStage();
      38       79248 :   if (should_move_to_next_stage()) Advance();
      39             : }
      40             : 
      41     4550501 : bool DebugPropertyIterator::Done() const {
      42     4550501 :   return prototype_iterator_.IsAtEnd();
      43             : }
      44             : 
      45     4550376 : void DebugPropertyIterator::Advance() {
      46     4550376 :   ++current_key_index_;
      47     4550376 :   calculated_native_accessor_flags_ = false;
      48     5213512 :   while (should_move_to_next_stage()) {
      49      331568 :     switch (stage_) {
      50             :       case Stage::kExoticIndices:
      51      124042 :         stage_ = Stage::kEnumerableStrings;
      52      124042 :         break;
      53             :       case Stage::kEnumerableStrings:
      54      106134 :         stage_ = Stage::kAllProperties;
      55      106134 :         break;
      56             :       case Stage::kAllProperties:
      57      101392 :         stage_ = kExoticIndices;
      58      101392 :         is_own_ = false;
      59      101392 :         prototype_iterator_.AdvanceIgnoringProxies();
      60      101392 :         break;
      61             :     }
      62      331568 :     FillKeysForCurrentPrototypeAndStage();
      63             :   }
      64     4550376 : }
      65             : 
      66     2995303 : bool DebugPropertyIterator::is_native_accessor() {
      67     2995303 :   if (stage_ == kExoticIndices) return false;
      68     2993922 :   CalculateNativeAccessorFlags();
      69     2993922 :   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    16449688 : Handle<Name> DebugPropertyIterator::raw_name() const {
      87             :   DCHECK(!Done());
      88    16449688 :   if (stage_ == kExoticIndices) {
      89        4143 :     return isolate_->factory()->Uint32ToString(current_key_index_);
      90             :   } else {
      91             :     return Handle<Name>::cast(
      92    32891090 :         FixedArray::get(*keys_, current_key_index_, isolate_));
      93             :   }
      94             : }
      95             : 
      96     4471278 : v8::Local<v8::Name> DebugPropertyIterator::name() const {
      97     4471278 :   return Utils::ToLocal(raw_name());
      98             : }
      99             : 
     100     2995303 : v8::Maybe<v8::PropertyAttribute> DebugPropertyIterator::attributes() {
     101             :   Handle<JSReceiver> receiver =
     102     2995303 :       PrototypeIterator::GetCurrent<JSReceiver>(prototype_iterator_);
     103     2995303 :   auto result = JSReceiver::GetPropertyAttributes(receiver, raw_name());
     104     2995303 :   if (result.IsNothing()) return Nothing<v8::PropertyAttribute>();
     105             :   DCHECK(result.FromJust() != ABSENT);
     106             :   return Just(static_cast<v8::PropertyAttribute>(result.FromJust()));
     107             : }
     108             : 
     109     2995283 : v8::Maybe<v8::debug::PropertyDescriptor> DebugPropertyIterator::descriptor() {
     110             :   Handle<JSReceiver> receiver =
     111     2995283 :       PrototypeIterator::GetCurrent<JSReceiver>(prototype_iterator_);
     112             : 
     113             :   PropertyDescriptor descriptor;
     114             :   Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
     115     5990566 :       isolate_, receiver, raw_name(), &descriptor);
     116     2995283 :   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     8985849 :   });
     131             : }
     132             : 
     133     4493893 : bool DebugPropertyIterator::is_own() { return is_own_; }
     134             : 
     135     2995283 : bool DebugPropertyIterator::is_array_index() {
     136     2995283 :   if (stage_ == kExoticIndices) return true;
     137     2993902 :   uint32_t index = 0;
     138     5987804 :   return raw_name()->AsArrayIndex(&index);
     139             : }
     140             : 
     141      410816 : void DebugPropertyIterator::FillKeysForCurrentPrototypeAndStage() {
     142      410816 :   current_key_index_ = 0;
     143      410816 :   exotic_length_ = 0;
     144      410816 :   keys_ = Handle<FixedArray>::null();
     145      410816 :   if (prototype_iterator_.IsAtEnd()) return;
     146             :   Handle<JSReceiver> receiver =
     147             :       PrototypeIterator::GetCurrent<JSReceiver>(prototype_iterator_);
     148             :   bool has_exotic_indices = receiver->IsJSTypedArray();
     149      354228 :   if (stage_ == kExoticIndices) {
     150      124052 :     if (!has_exotic_indices) return;
     151             :     // TODO(bmeurer, v8:4153): Change this to size_t later.
     152             :     exotic_length_ =
     153         123 :         static_cast<uint32_t>(Handle<JSTypedArray>::cast(receiver)->length());
     154         123 :     return;
     155             :   }
     156             :   bool skip_indices = has_exotic_indices;
     157             :   PropertyFilter filter =
     158      230176 :       stage_ == kEnumerableStrings ? ENUMERABLE_STRINGS : ALL_PROPERTIES;
     159      460352 :   if (!KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly, filter,
     160             :                                GetKeysConversion::kConvertToString, false,
     161      230176 :                                skip_indices)
     162             :            .ToHandle(&keys_)) {
     163           0 :     keys_ = Handle<FixedArray>::null();
     164             :   }
     165             : }
     166             : 
     167           0 : bool DebugPropertyIterator::should_move_to_next_stage() const {
     168     4961192 :   if (prototype_iterator_.IsAtEnd()) return false;
     169     4904604 :   if (stage_ == kExoticIndices) return current_key_index_ >= exotic_length_;
     170     9400076 :   return keys_.is_null() ||
     171     9400076 :          current_key_index_ >= static_cast<uint32_t>(keys_->length());
     172             : }
     173             : 
     174             : namespace {
     175     2993922 : base::Flags<debug::NativeAccessorType, int> GetNativeAccessorDescriptorInternal(
     176             :     Handle<JSReceiver> object, Handle<Name> name) {
     177             :   uint32_t index;
     178     2993922 :   if (name->AsArrayIndex(&index)) return debug::NativeAccessorType::None;
     179             :   LookupIterator it =
     180     2962416 :       LookupIterator(object->GetIsolate(), object, name, LookupIterator::OWN);
     181     2962416 :   if (!it.IsFound()) return debug::NativeAccessorType::None;
     182     2962416 :   if (it.state() != LookupIterator::ACCESSOR) {
     183     2919477 :     return debug::NativeAccessorType::None;
     184             :   }
     185       42939 :   Handle<Object> structure = it.GetAccessors();
     186       42939 :   if (!structure->IsAccessorInfo()) return debug::NativeAccessorType::None;
     187             :   auto isolate = object->GetIsolate();
     188             :   base::Flags<debug::NativeAccessorType, int> result;
     189             : #define IS_BUILTIN_ACESSOR(_, name, ...)                    \
     190             :   if (*structure == *isolate->factory()->name##_accessor()) \
     191             :     return debug::NativeAccessorType::None;
     192       25089 :   ACCESSOR_INFO_LIST_GENERATOR(IS_BUILTIN_ACESSOR, /* not used */)
     193             : #undef IS_BUILTIN_ACESSOR
     194             :   Handle<AccessorInfo> accessor_info = Handle<AccessorInfo>::cast(structure);
     195          20 :   if (accessor_info->getter() != Object()) {
     196             :     result |= debug::NativeAccessorType::HasGetter;
     197             :   }
     198          20 :   if (accessor_info->setter() != Object()) {
     199             :     result |= debug::NativeAccessorType::HasSetter;
     200             :   }
     201          20 :   return result;
     202             : }
     203             : }  // anonymous namespace
     204             : 
     205     2993962 : void DebugPropertyIterator::CalculateNativeAccessorFlags() {
     206     2994002 :   if (calculated_native_accessor_flags_) return;
     207             :   Handle<JSReceiver> receiver =
     208     2993922 :       PrototypeIterator::GetCurrent<JSReceiver>(prototype_iterator_);
     209             :   native_accessor_flags_ =
     210     5987844 :       GetNativeAccessorDescriptorInternal(receiver, raw_name());
     211     2993922 :   calculated_native_accessor_flags_ = true;
     212             : }
     213             : }  // namespace internal
     214      122036 : }  // namespace v8

Generated by: LCOV version 1.10