• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 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 #ifndef V8_TOOLS_V8WINDBG_SRC_OBJECT_INSPECTION_H_
6 #define V8_TOOLS_V8WINDBG_SRC_OBJECT_INSPECTION_H_
7 
8 #include <comutil.h>
9 #include <wrl/implements.h>
10 
11 #include <sstream>
12 #include <string>
13 #include <vector>
14 
15 #include "tools/v8windbg/base/dbgext.h"
16 #include "tools/v8windbg/src/v8-debug-helper-interop.h"
17 #include "tools/v8windbg/src/v8windbg-extension.h"
18 
19 // The representation of the underlying V8 object that will be cached on the
20 // DataModel representation. (Needs to implement IUnknown).
21 class __declspec(uuid("6392E072-37BB-4220-A5FF-114098923A02")) IV8CachedObject
22     : public IUnknown {
23  public:
24   virtual HRESULT __stdcall GetCachedV8HeapObject(
25       V8HeapObject** pp_heap_object) = 0;
26 };
27 
28 class V8CachedObject
29     : public WRL::RuntimeClass<
30           WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>,
31           IV8CachedObject> {
32  public:
33   V8CachedObject(Location location, std::string uncompressed_type_name,
34                  WRL::ComPtr<IDebugHostContext> context, bool is_compressed);
35   V8CachedObject(V8HeapObject heap_object);
36   ~V8CachedObject() override;
37 
38   static HRESULT Create(IModelObject* p_v8_object_instance,
39                         IV8CachedObject** result);
40 
41   IFACEMETHOD(GetCachedV8HeapObject)(V8HeapObject** pp_heap_object);
42 
43  private:
44   // The properties and description of the object, if already read.
45   V8HeapObject heap_object_;
46   bool heap_object_initialized_ = false;
47 
48   // Data that is necessary for reading the object.
49   Location location_;
50   std::string uncompressed_type_name_;
51   WRL::ComPtr<IDebugHostContext> context_;
52   bool is_compressed_ = false;
53 };
54 
55 // A simple COM wrapper class to hold data required for IndexedFieldParent.
56 // (Needs to implement IUnknown).
57 class __declspec(uuid("6392E072-37BB-4220-A5FF-114098923A03")) IIndexedFieldData
58     : public IUnknown {
59  public:
60   // Get a pointer to the Property object held by this IIndexedFieldData. The
61   // pointer returned in this way is valid only while the containing
62   // IIndexedFieldData is alive.
63   virtual HRESULT __stdcall GetProperty(Property** property) = 0;
64 };
65 
66 class IndexedFieldData
67     : public WRL::RuntimeClass<
68           WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>,
69           IIndexedFieldData> {
70  public:
71   IndexedFieldData(Property property);
72   ~IndexedFieldData() override;
73 
74   // Get a pointer to the Property object held by this IndexedFieldData. The
75   // pointer returned in this way is valid only while the containing
76   // IndexedFieldData is alive.
77   IFACEMETHOD(GetProperty)(Property** property);
78 
79  private:
80   Property property_;
81 };
82 
83 // A parent model that provides indexing support for fields that contain arrays
84 // of something more complicated than basic native types.
85 class IndexedFieldParent
86     : public WRL::RuntimeClass<
87           WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>,
88           IDataModelConcept, IIterableConcept, IIndexableConcept> {
89  public:
90   // IDataModelConcept
91   IFACEMETHOD(InitializeObject)
92   (IModelObject* model_object, IDebugHostTypeSignature* matching_type_signature,
93    IDebugHostSymbolEnumerator* wildcard_matches);
94 
95   // IDataModelConcept
96   IFACEMETHOD(GetName)(BSTR* model_name);
97 
98   // IIndexableConcept
99   IFACEMETHOD(GetAt)
100   (IModelObject* context_object, ULONG64 indexer_count, IModelObject** indexers,
101    _COM_Errorptr_ IModelObject** object, IKeyStore** metadata);
102 
103   // IIndexableConcept
104   IFACEMETHOD(GetDimensionality)
105   (IModelObject* context_object, ULONG64* dimensionality);
106 
107   // IIndexableConcept
108   IFACEMETHOD(SetAt)
109   (IModelObject* context_object, ULONG64 indexer_count, IModelObject** indexers,
110    IModelObject* value);
111 
112   // IIterableConcept
113   IFACEMETHOD(GetDefaultIndexDimensionality)
114   (IModelObject* context_object, ULONG64* dimensionality);
115 
116   // IIterableConcept
117   IFACEMETHOD(GetIterator)
118   (IModelObject* context_object, IModelIterator** iterator);
119 };
120 
121 // An iterator for the values within an array field.
122 class IndexedFieldIterator
123     : public WRL::RuntimeClass<
124           WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>,
125           IModelIterator> {
126  public:
127   IndexedFieldIterator(IModelObject* context_object);
128   ~IndexedFieldIterator() override;
129 
130   IFACEMETHOD(Reset)();
131 
132   IFACEMETHOD(GetNext)
133   (IModelObject** object, ULONG64 dimensions, IModelObject** indexers,
134    IKeyStore** metadata);
135 
136  private:
137   size_t next_ = 0;
138   WRL::ComPtr<IModelObject> context_object_;
139 };
140 
141 // Enumerates the names of fields on V8 objects.
142 class V8ObjectKeyEnumerator
143     : public WRL::RuntimeClass<
144           WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>,
145           IKeyEnumerator> {
146  public:
147   V8ObjectKeyEnumerator(WRL::ComPtr<IV8CachedObject>& v8_cached_object);
148   ~V8ObjectKeyEnumerator() override;
149 
150   IFACEMETHOD(Reset)();
151 
152   // This method will be called with a nullptr 'value' for each key if returned
153   // from an IDynamicKeyProviderConcept. It will call GetKey on the
154   // IDynamicKeyProviderConcept interface after each key returned.
155   IFACEMETHOD(GetNext)(BSTR* key, IModelObject** value, IKeyStore** metadata);
156 
157  private:
158   int index_ = 0;
159   WRL::ComPtr<IV8CachedObject> sp_v8_cached_object_;
160 };
161 
162 // A parent model for V8 handle types such as v8::internal::Handle<*>.
163 class V8LocalDataModel
164     : public WRL::RuntimeClass<
165           WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>,
166           IDataModelConcept> {
167  public:
168   IFACEMETHOD(InitializeObject)
169   (IModelObject* model_object, IDebugHostTypeSignature* matching_type_signature,
170    IDebugHostSymbolEnumerator* wildcard_matches);
171 
172   IFACEMETHOD(GetName)(BSTR* model_name);
173 };
174 
175 // A parent model for V8 object types such as v8::internal::Object.
176 class V8ObjectDataModel
177     : public WRL::RuntimeClass<
178           WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>,
179           IDataModelConcept, IStringDisplayableConcept,
180           IDynamicKeyProviderConcept> {
181  public:
GetCachedObject(IModelObject * context_object,IV8CachedObject ** result)182   HRESULT GetCachedObject(IModelObject* context_object,
183                           IV8CachedObject** result) {
184     // Get the IModelObject for this parent object. As it is a dynamic provider,
185     // there is only one parent directly on the object.
186     WRL::ComPtr<IModelObject> sp_parent_model, sp_context_adjuster;
187     RETURN_IF_FAIL(context_object->GetParentModel(0, &sp_parent_model,
188                                                   &sp_context_adjuster));
189 
190     // See if the cached object is already present
191     WRL::ComPtr<IUnknown> sp_context;
192     HRESULT hr = context_object->GetContextForDataModel(sp_parent_model.Get(),
193                                                         &sp_context);
194 
195     WRL::ComPtr<IV8CachedObject> sp_v8_cached_object;
196 
197     if (SUCCEEDED(hr)) {
198       RETURN_IF_FAIL(sp_context.As(&sp_v8_cached_object));
199     } else {
200       RETURN_IF_FAIL(
201           V8CachedObject::Create(context_object, &sp_v8_cached_object));
202       RETURN_IF_FAIL(sp_v8_cached_object.As(&sp_context));
203       RETURN_IF_FAIL(context_object->SetContextForDataModel(
204           sp_parent_model.Get(), sp_context.Get()));
205     }
206 
207     *result = sp_v8_cached_object.Detach();
208     return S_OK;
209   }
210 
211   IFACEMETHOD(InitializeObject)
212   (IModelObject* model_object, IDebugHostTypeSignature* matching_type_signature,
213    IDebugHostSymbolEnumerator* wildcard_matches);
214 
215   IFACEMETHOD(GetName)(BSTR* model_name);
216 
217   IFACEMETHOD(ToDisplayString)
218   (IModelObject* context_object, IKeyStore* metadata, BSTR* display_string);
219 
220   // IDynamicKeyProviderConcept
221   IFACEMETHOD(GetKey)
222   (IModelObject* context_object, PCWSTR key, IModelObject** key_value,
223    IKeyStore** metadata, bool* has_key);
224 
225   IFACEMETHOD(SetKey)
226   (IModelObject* context_object, PCWSTR key, IModelObject* key_value,
227    IKeyStore* metadata);
228 
229   IFACEMETHOD(EnumerateKeys)
230   (IModelObject* context_object, IKeyEnumerator** pp_enumerator);
231 };
232 
233 // The implemention of the "Value" getter for V8 handle types.
234 class V8LocalValueProperty
235     : public WRL::RuntimeClass<
236           WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>,
237           IModelPropertyAccessor> {
238  public:
239   IFACEMETHOD(GetValue)
240   (PCWSTR pwsz_key, IModelObject* p_v8_object_instance,
241    IModelObject** pp_value);
242 
243   IFACEMETHOD(SetValue)
244   (PCWSTR /*pwsz_key*/, IModelObject* /*p_process_instance*/,
245    IModelObject* /*p_value*/);
246 };
247 
248 // The implemention of the "NodeId" getter for v8::internal::compiler::Node
249 // type.
250 class V8InternalCompilerNodeIdProperty
251     : public WRL::RuntimeClass<
252           WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>,
253           IModelPropertyAccessor> {
254  public:
255   IFACEMETHOD(GetValue)
256   (PCWSTR pwsz_key, IModelObject* p_v8_object_instance,
257    IModelObject** pp_value);
258 
259   IFACEMETHOD(SetValue)
260   (PCWSTR /*pwsz_key*/, IModelObject* /*p_process_instance*/,
261    IModelObject* /*p_value*/);
262 };
263 
264 // The implemention of the "bitset_name" getter for v8::internal::compiler::Type
265 // type.
266 class V8InternalCompilerBitsetNameProperty
267     : public WRL::RuntimeClass<
268           WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>,
269           IModelPropertyAccessor> {
270  public:
271   IFACEMETHOD(GetValue)
272   (PCWSTR pwsz_key, IModelObject* p_v8_compiler_type_instance,
273    IModelObject** pp_value);
274 
275   IFACEMETHOD(SetValue)
276   (PCWSTR /*pwsz_key*/, IModelObject* /*p_process_instance*/,
277    IModelObject* /*p_value*/);
278 };
279 
280 // A way that someone can directly inspect a tagged value, even if that value
281 // isn't in memory (from a register, or the user's imagination, etc.).
282 class InspectV8ObjectMethod
283     : public WRL::RuntimeClass<
284           WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>,
285           IModelMethod> {
286  public:
287   IFACEMETHOD(Call)
288   (IModelObject* p_context_object, ULONG64 arg_count,
289    _In_reads_(arg_count) IModelObject** pp_arguments, IModelObject** pp_result,
290    IKeyStore** pp_metadata);
291 };
292 
293 HRESULT GetModelForProperty(const Property& prop,
294                             WRL::ComPtr<IDebugHostContext>& sp_ctx,
295                             IModelObject** result);
296 
297 #endif  // V8_TOOLS_V8WINDBG_SRC_OBJECT_INSPECTION_H_
298