5 #include "src/debug/debug-property-iterator.h" 7 #include "src/api-inl.h" 8 #include "src/base/flags.h" 10 #include "src/objects/js-array-buffer-inl.h" 11 #include "src/property-descriptor.h" 12 #include "src/property-details.h" 16 std::unique_ptr<debug::PropertyIterator> debug::PropertyIterator::Create(
18 internal::Isolate* isolate =
19 reinterpret_cast<internal::Isolate*
>(v8_object->
GetIsolate());
20 return std::unique_ptr<debug::PropertyIterator>(
21 new internal::DebugPropertyIterator(isolate,
22 Utils::OpenHandle(*v8_object)));
27 DebugPropertyIterator::DebugPropertyIterator(Isolate* isolate,
28 Handle<JSReceiver> receiver)
30 prototype_iterator_(isolate, receiver, kStartAtReceiver,
31 PrototypeIterator::END_AT_NULL) {
32 if (receiver->IsJSProxy()) {
34 prototype_iterator_.AdvanceIgnoringProxies();
36 if (prototype_iterator_.IsAtEnd())
return;
37 FillKeysForCurrentPrototypeAndStage();
38 if (should_move_to_next_stage()) Advance();
41 bool DebugPropertyIterator::Done()
const {
42 return prototype_iterator_.IsAtEnd();
45 void DebugPropertyIterator::Advance() {
47 calculated_native_accessor_flags_ =
false;
48 while (should_move_to_next_stage()) {
50 case Stage::kExoticIndices:
51 stage_ = Stage::kEnumerableStrings;
53 case Stage::kEnumerableStrings:
54 stage_ = Stage::kAllProperties;
56 case Stage::kAllProperties:
57 stage_ = kExoticIndices;
59 prototype_iterator_.AdvanceIgnoringProxies();
62 FillKeysForCurrentPrototypeAndStage();
66 bool DebugPropertyIterator::is_native_accessor() {
67 if (stage_ == kExoticIndices)
return false;
68 CalculateNativeAccessorFlags();
69 return native_accessor_flags_;
72 bool DebugPropertyIterator::has_native_getter() {
73 if (stage_ == kExoticIndices)
return false;
74 CalculateNativeAccessorFlags();
75 return native_accessor_flags_ &
76 static_cast<int>(debug::NativeAccessorType::HasGetter);
79 bool DebugPropertyIterator::has_native_setter() {
80 if (stage_ == kExoticIndices)
return false;
81 CalculateNativeAccessorFlags();
82 return native_accessor_flags_ &
83 static_cast<int>(debug::NativeAccessorType::HasSetter);
86 Handle<Name> DebugPropertyIterator::raw_name()
const {
88 if (stage_ == kExoticIndices) {
89 return isolate_->factory()->Uint32ToString(current_key_index_);
91 return Handle<Name>::cast(
92 FixedArray::get(*keys_, current_key_index_, isolate_));
97 return Utils::ToLocal(raw_name());
101 Handle<JSReceiver> receiver =
102 PrototypeIterator::GetCurrent<JSReceiver>(prototype_iterator_);
103 auto result = JSReceiver::GetPropertyAttributes(receiver, raw_name());
104 if (result.IsNothing())
return Nothing<v8::PropertyAttribute>();
105 DCHECK(result.FromJust() != ABSENT);
106 return Just(static_cast<v8::PropertyAttribute>(result.FromJust()));
110 Handle<JSReceiver> receiver =
111 PrototypeIterator::GetCurrent<JSReceiver>(prototype_iterator_);
113 PropertyDescriptor descriptor;
114 Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
115 isolate_, receiver, raw_name(), &descriptor);
116 if (did_get_descriptor.IsNothing()) {
117 return Nothing<v8::debug::PropertyDescriptor>();
119 DCHECK(did_get_descriptor.FromJust());
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())
126 descriptor.has_get() ? Utils::ToLocal(descriptor.get())
128 descriptor.has_set() ? Utils::ToLocal(descriptor.set())
133 bool DebugPropertyIterator::is_own() {
return is_own_; }
135 bool DebugPropertyIterator::is_array_index() {
136 if (stage_ == kExoticIndices)
return true;
138 return raw_name()->AsArrayIndex(&index);
141 void DebugPropertyIterator::FillKeysForCurrentPrototypeAndStage() {
142 current_key_index_ = 0;
144 keys_ = Handle<FixedArray>::null();
145 if (prototype_iterator_.IsAtEnd())
return;
146 Handle<JSReceiver> receiver =
147 PrototypeIterator::GetCurrent<JSReceiver>(prototype_iterator_);
148 bool has_exotic_indices = receiver->IsJSTypedArray();
149 if (stage_ == kExoticIndices) {
150 if (!has_exotic_indices)
return;
151 exotic_length_ =
static_cast<uint32_t>(
152 Handle<JSTypedArray>::cast(receiver)->length_value());
155 bool skip_indices = has_exotic_indices;
157 stage_ == kEnumerableStrings ? ENUMERABLE_STRINGS : ALL_PROPERTIES;
158 if (!KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly, filter,
159 GetKeysConversion::kConvertToString,
false,
162 keys_ = Handle<FixedArray>::null();
166 bool DebugPropertyIterator::should_move_to_next_stage()
const {
167 if (prototype_iterator_.IsAtEnd())
return false;
168 if (stage_ == kExoticIndices)
return current_key_index_ >= exotic_length_;
169 return keys_.is_null() ||
170 current_key_index_ >=
static_cast<uint32_t>(keys_->length());
174 base::Flags<debug::NativeAccessorType, int> GetNativeAccessorDescriptorInternal(
175 Handle<JSReceiver>
object, Handle<Name> name) {
177 if (name->AsArrayIndex(&index))
return debug::NativeAccessorType::None;
179 LookupIterator(object->GetIsolate(), object, name, LookupIterator::OWN);
180 if (!it.IsFound())
return debug::NativeAccessorType::None;
181 if (it.state() != LookupIterator::ACCESSOR) {
182 return debug::NativeAccessorType::None;
184 Handle<Object> structure = it.GetAccessors();
185 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 ACCESSOR_INFO_LIST_GENERATOR(IS_BUILTIN_ACESSOR, )
192 #undef IS_BUILTIN_ACESSOR 193 Handle<AccessorInfo> accessor_info = Handle<AccessorInfo>::cast(structure);
194 if (accessor_info->getter()) {
195 result |= debug::NativeAccessorType::HasGetter;
197 if (accessor_info->setter()) {
198 result |= debug::NativeAccessorType::HasSetter;
204 void DebugPropertyIterator::CalculateNativeAccessorFlags() {
205 if (calculated_native_accessor_flags_)
return;
206 Handle<JSReceiver> receiver =
207 PrototypeIterator::GetCurrent<JSReceiver>(prototype_iterator_);
208 native_accessor_flags_ =
209 GetNativeAccessorDescriptorInternal(receiver, raw_name());
210 calculated_native_accessor_flags_ =
true;