v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
debug-property-iterator.cc
Go to the documentation of this file.
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
6
7#include "src/api/api-inl.h"
8#include "src/base/flags.h"
10#include "src/objects/keys.h"
13
14namespace v8 {
15namespace internal {
16
17std::unique_ptr<DebugPropertyIterator> DebugPropertyIterator::Create(
18 Isolate* isolate, DirectHandle<JSReceiver> receiver, bool skip_indices) {
19 // Can't use std::make_unique as Ctor is private.
20 auto iterator = std::unique_ptr<DebugPropertyIterator>(
21 new DebugPropertyIterator(isolate, receiver, skip_indices));
22
23 if (IsJSProxy(*receiver)) {
24 iterator->AdvanceToPrototype();
25 }
26
27 if (!iterator->FillKeysForCurrentPrototypeAndStage()) return nullptr;
28 if (iterator->should_move_to_next_stage() && !iterator->AdvanceInternal()) {
29 return nullptr;
30 }
31
32 return iterator;
33}
34
37 bool skip_indices)
38 : isolate_(isolate),
39 prototype_iterator_(isolate, receiver, kStartAtReceiver,
40 PrototypeIterator::END_AT_NULL),
41 skip_indices_(skip_indices),
42 current_key_index_(0),
43 current_keys_(isolate_->factory()->empty_fixed_array()),
44 current_keys_length_(0) {}
45
46bool DebugPropertyIterator::Done() const { return is_done_; }
47
55
60 switch (stage_) {
61 case kExoticIndices:
63 break;
66 break;
67 case kAllProperties:
69 break;
70 }
71 if (!FillKeysForCurrentPrototypeAndStage()) return false;
72 }
73 return true;
74}
75
80
86
92
94 DCHECK(!Done());
95 if (stage_ == kExoticIndices) {
97 } else {
99 current_keys_->get(static_cast<int>(current_key_index_)), isolate_));
100 }
101}
102
104 return Utils::ToLocal(raw_name());
105}
106
110 auto result =
112 if (result.IsNothing()) return Nothing<v8::PropertyAttribute>();
113 // This should almost never happen, however we have seen cases where we do
114 // trigger this check. In these rare events, it typically is a
115 // misconfiguration by an embedder (such as Blink) in how the embedder
116 // processes properities.
117 //
118 // In the case of crbug.com/1262066 we discovered that Blink was returning
119 // a list of properties to contain in an object, after which V8 queries each
120 // property individually. But, Blink incorrectly claimed that the property
121 // in question did *not* exist. As such, V8 is instructed to process a
122 // property, requests the embedder for more information and then suddenly the
123 // embedder claims it doesn't exist. In these cases, we hit this DCHECK.
124 //
125 // If you are running into this problem, check your embedder implementation
126 // and verify that the data from both sides matches. If there is a mismatch,
127 // V8 will crash.
128
129#if DEBUG
130 base::ScopedVector<char> property_message(128);
131 base::ScopedVector<char> name_buffer(100);
132 raw_name()->NameShortPrint(name_buffer);
133 v8::base::SNPrintF(property_message, "Invalid result for property \"%s\"\n",
134 name_buffer.begin());
135 DCHECK_WITH_MSG(result.FromJust() != ABSENT, property_message.begin());
136#endif
137 return Just(static_cast<v8::PropertyAttribute>(result.FromJust()));
138}
139
143
147 if (did_get_descriptor.IsNothing()) {
149 }
150 if (!did_get_descriptor.FromJust()) {
152 false, false, /* enumerable */
153 false, false, /* configurable */
154 false, false, /* writable */
155 v8::Local<v8::Value>(), /* value */
156 v8::Local<v8::Value>(), /* get */
157 v8::Local<v8::Value>(), /* set */
158 });
159 }
160 DCHECK(did_get_descriptor.FromJust());
162 descriptor.enumerable(), descriptor.has_enumerable(),
163 descriptor.configurable(), descriptor.has_configurable(),
164 descriptor.writable(), descriptor.has_writable(),
165 descriptor.has_value() ? Utils::ToLocal(descriptor.value())
167 descriptor.has_get() ? Utils::ToLocal(descriptor.get())
169 descriptor.has_set() ? Utils::ToLocal(descriptor.set())
171 });
172}
173
175
177 if (stage_ == kExoticIndices) return true;
179 return key.is_element();
180}
181
184 current_keys_ = isolate_->factory()->empty_fixed_array();
186 if (is_done_) return true;
189 if (stage_ == kExoticIndices) {
190 if (skip_indices_ || !IsJSTypedArray(*receiver)) return true;
191 auto typed_array = Cast<JSTypedArray>(receiver);
193 typed_array->WasDetached() ? 0 : typed_array->GetLength();
194 return true;
195 }
196 PropertyFilter filter =
200 false, skip_indices_ || IsJSTypedArray(*receiver))
201 .ToHandle(&current_keys_)) {
203 return true;
204 }
205 return false;
206}
207
211
212namespace {
213base::Flags<debug::NativeAccessorType, int> GetNativeAccessorDescriptorInternal(
215 Isolate* isolate = object->GetIsolate();
216 PropertyKey key(isolate, name);
217 if (key.is_element()) return debug::NativeAccessorType::None;
218 LookupIterator it(isolate, object, key, LookupIterator::OWN);
219 if (!it.IsFound()) return debug::NativeAccessorType::None;
220 if (it.state() != LookupIterator::ACCESSOR) {
222 }
223 DirectHandle<Object> structure = it.GetAccessors();
224 if (!IsAccessorInfo(*structure)) return debug::NativeAccessorType::None;
226 if (*structure == *isolate->factory()->value_unavailable_accessor()) {
228 }
229#define IS_BUILTIN_ACCESSOR(_, name, ...) \
230 if (*structure == *isolate->factory()->name##_accessor()) \
231 return debug::NativeAccessorType::None;
233#undef IS_BUILTIN_ACCESSOR
234 auto accessor_info = Cast<AccessorInfo>(structure);
235 if (accessor_info->has_getter(isolate)) {
237 }
238 if (accessor_info->has_setter(isolate)) {
240 }
241 return result;
242}
243} // anonymous namespace
244
257} // namespace internal
258} // namespace v8
#define ACCESSOR_INFO_LIST_GENERATOR(V, _)
Definition accessors.h:25
Isolate * isolate_
V8_INLINE T FromJust() const &
Definition v8-maybe.h:64
V8_INLINE bool IsNothing() const
Definition v8-maybe.h:35
constexpr T * begin() const
Definition vector.h:96
static V8_WARN_UNUSED_RESULT std::unique_ptr< DebugPropertyIterator > Create(Isolate *isolate, DirectHandle< JSReceiver > receiver, bool skip_indices)
V8_WARN_UNUSED_RESULT bool FillKeysForCurrentPrototypeAndStage()
v8::Local< v8::Name > name() const override
DebugPropertyIterator(const DebugPropertyIterator &)=delete
enum v8::internal::DebugPropertyIterator::@56 stage_
v8::Maybe< v8::debug::PropertyDescriptor > descriptor() override
v8::Maybe< v8::PropertyAttribute > attributes() override
V8_WARN_UNUSED_RESULT bool AdvanceInternal()
Handle< String > SizeToString(size_t value, bool check_cache=true)
Definition factory.cc:3935
v8::internal::Factory * factory()
Definition isolate.h:1527
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT Maybe< bool > GetOwnPropertyDescriptor(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Object > key, PropertyDescriptor *desc)
static V8_WARN_UNUSED_RESULT Maybe< PropertyAttributes > GetPropertyAttributes(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Name > name)
static MaybeHandle< FixedArray > GetKeys(Isolate *isolate, DirectHandle< JSReceiver > object, KeyCollectionMode mode, PropertyFilter filter, GetKeysConversion keys_conversion=GetKeysConversion::kKeepNumbers, bool is_for_in=false, bool skip_indices=false)
Definition keys.cc:97
Tagged< T > GetCurrent() const
Definition prototype.h:52
#define IS_BUILTIN_ACCESSOR(_, name,...)
TNode< Object > receiver
ZoneVector< RpoNumber > & result
int SNPrintF(Vector< char > str, const char *format,...)
Definition strings.cc:20
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
PropertyAttribute
Definition v8-object.h:139
Maybe< T > Nothing()
Definition v8-maybe.h:112
Maybe< T > Just(const T &t)
Definition v8-maybe.h:117
#define DCHECK_WITH_MSG(condition, msg)
Definition logging.h:182
#define DCHECK(condition)
Definition logging.h:482