| // Copyright 2020 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef V8_TOOLS_V8WINDBG_SRC_OBJECT_INSPECTION_H_ |
| #define V8_TOOLS_V8WINDBG_SRC_OBJECT_INSPECTION_H_ |
| |
| #include <comutil.h> |
| #include <wrl/implements.h> |
| |
| #include <sstream> |
| #include <string> |
| #include <vector> |
| |
| #include "tools/v8windbg/base/dbgext.h" |
| #include "tools/v8windbg/src/v8-debug-helper-interop.h" |
| #include "tools/v8windbg/src/v8windbg-extension.h" |
| |
| // The representation of the underlying V8 object that will be cached on the |
| // DataModel representation. (Needs to implement IUnknown). |
| class __declspec(uuid("6392E072-37BB-4220-A5FF-114098923A02")) IV8CachedObject |
| : public IUnknown { |
| public: |
| virtual HRESULT __stdcall GetCachedV8HeapObject( |
| V8HeapObject** pp_heap_object) = 0; |
| }; |
| |
| class V8CachedObject |
| : public WRL::RuntimeClass< |
| WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, |
| IV8CachedObject> { |
| public: |
| V8CachedObject(Location location, std::string uncompressed_type_name, |
| WRL::ComPtr<IDebugHostContext> context, bool is_compressed); |
| V8CachedObject(V8HeapObject heap_object); |
| ~V8CachedObject() override; |
| |
| static HRESULT Create(IModelObject* p_v8_object_instance, |
| IV8CachedObject** result); |
| |
| IFACEMETHOD(GetCachedV8HeapObject)(V8HeapObject** pp_heap_object); |
| |
| private: |
| // The properties and description of the object, if already read. |
| V8HeapObject heap_object_; |
| bool heap_object_initialized_ = false; |
| |
| // Data that is necessary for reading the object. |
| Location location_; |
| std::string uncompressed_type_name_; |
| WRL::ComPtr<IDebugHostContext> context_; |
| bool is_compressed_ = false; |
| }; |
| |
| // A simple COM wrapper class to hold data required for IndexedFieldParent. |
| // (Needs to implement IUnknown). |
| class __declspec(uuid("6392E072-37BB-4220-A5FF-114098923A03")) IIndexedFieldData |
| : public IUnknown { |
| public: |
| // Get a pointer to the Property object held by this IIndexedFieldData. The |
| // pointer returned in this way is valid only while the containing |
| // IIndexedFieldData is alive. |
| virtual HRESULT __stdcall GetProperty(Property** property) = 0; |
| }; |
| |
| class IndexedFieldData |
| : public WRL::RuntimeClass< |
| WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, |
| IIndexedFieldData> { |
| public: |
| IndexedFieldData(Property property); |
| ~IndexedFieldData() override; |
| |
| // Get a pointer to the Property object held by this IndexedFieldData. The |
| // pointer returned in this way is valid only while the containing |
| // IndexedFieldData is alive. |
| IFACEMETHOD(GetProperty)(Property** property); |
| |
| private: |
| Property property_; |
| }; |
| |
| // A parent model that provides indexing support for fields that contain arrays |
| // of something more complicated than basic native types. |
| class IndexedFieldParent |
| : public WRL::RuntimeClass< |
| WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, |
| IDataModelConcept, IIterableConcept, IIndexableConcept> { |
| public: |
| // IDataModelConcept |
| IFACEMETHOD(InitializeObject) |
| (IModelObject* model_object, IDebugHostTypeSignature* matching_type_signature, |
| IDebugHostSymbolEnumerator* wildcard_matches); |
| |
| // IDataModelConcept |
| IFACEMETHOD(GetName)(BSTR* model_name); |
| |
| // IIndexableConcept |
| IFACEMETHOD(GetAt) |
| (IModelObject* context_object, ULONG64 indexer_count, IModelObject** indexers, |
| _COM_Errorptr_ IModelObject** object, IKeyStore** metadata); |
| |
| // IIndexableConcept |
| IFACEMETHOD(GetDimensionality) |
| (IModelObject* context_object, ULONG64* dimensionality); |
| |
| // IIndexableConcept |
| IFACEMETHOD(SetAt) |
| (IModelObject* context_object, ULONG64 indexer_count, IModelObject** indexers, |
| IModelObject* value); |
| |
| // IIterableConcept |
| IFACEMETHOD(GetDefaultIndexDimensionality) |
| (IModelObject* context_object, ULONG64* dimensionality); |
| |
| // IIterableConcept |
| IFACEMETHOD(GetIterator) |
| (IModelObject* context_object, IModelIterator** iterator); |
| }; |
| |
| // An iterator for the values within an array field. |
| class IndexedFieldIterator |
| : public WRL::RuntimeClass< |
| WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, |
| IModelIterator> { |
| public: |
| IndexedFieldIterator(IModelObject* context_object); |
| ~IndexedFieldIterator() override; |
| |
| IFACEMETHOD(Reset)(); |
| |
| IFACEMETHOD(GetNext) |
| (IModelObject** object, ULONG64 dimensions, IModelObject** indexers, |
| IKeyStore** metadata); |
| |
| private: |
| size_t next_ = 0; |
| WRL::ComPtr<IModelObject> context_object_; |
| }; |
| |
| // Enumerates the names of fields on V8 objects. |
| class V8ObjectKeyEnumerator |
| : public WRL::RuntimeClass< |
| WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, |
| IKeyEnumerator> { |
| public: |
| V8ObjectKeyEnumerator(WRL::ComPtr<IV8CachedObject>& v8_cached_object); |
| ~V8ObjectKeyEnumerator() override; |
| |
| IFACEMETHOD(Reset)(); |
| |
| // This method will be called with a nullptr 'value' for each key if returned |
| // from an IDynamicKeyProviderConcept. It will call GetKey on the |
| // IDynamicKeyProviderConcept interface after each key returned. |
| IFACEMETHOD(GetNext)(BSTR* key, IModelObject** value, IKeyStore** metadata); |
| |
| private: |
| int index_ = 0; |
| WRL::ComPtr<IV8CachedObject> sp_v8_cached_object_; |
| }; |
| |
| // A parent model for V8 handle types such as v8::internal::Handle<*>. |
| class V8LocalDataModel |
| : public WRL::RuntimeClass< |
| WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, |
| IDataModelConcept> { |
| public: |
| IFACEMETHOD(InitializeObject) |
| (IModelObject* model_object, IDebugHostTypeSignature* matching_type_signature, |
| IDebugHostSymbolEnumerator* wildcard_matches); |
| |
| IFACEMETHOD(GetName)(BSTR* model_name); |
| }; |
| |
| // A parent model for V8 object types such as v8::internal::Object. |
| class V8ObjectDataModel |
| : public WRL::RuntimeClass< |
| WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, |
| IDataModelConcept, IStringDisplayableConcept, |
| IDynamicKeyProviderConcept> { |
| public: |
| HRESULT GetCachedObject(IModelObject* context_object, |
| IV8CachedObject** result) { |
| // Get the IModelObject for this parent object. As it is a dynamic provider, |
| // there is only one parent directly on the object. |
| WRL::ComPtr<IModelObject> sp_parent_model, sp_context_adjuster; |
| RETURN_IF_FAIL(context_object->GetParentModel(0, &sp_parent_model, |
| &sp_context_adjuster)); |
| |
| // See if the cached object is already present |
| WRL::ComPtr<IUnknown> sp_context; |
| HRESULT hr = context_object->GetContextForDataModel(sp_parent_model.Get(), |
| &sp_context); |
| |
| WRL::ComPtr<IV8CachedObject> sp_v8_cached_object; |
| |
| if (SUCCEEDED(hr)) { |
| RETURN_IF_FAIL(sp_context.As(&sp_v8_cached_object)); |
| } else { |
| RETURN_IF_FAIL( |
| V8CachedObject::Create(context_object, &sp_v8_cached_object)); |
| RETURN_IF_FAIL(sp_v8_cached_object.As(&sp_context)); |
| RETURN_IF_FAIL(context_object->SetContextForDataModel( |
| sp_parent_model.Get(), sp_context.Get())); |
| } |
| |
| *result = sp_v8_cached_object.Detach(); |
| return S_OK; |
| } |
| |
| IFACEMETHOD(InitializeObject) |
| (IModelObject* model_object, IDebugHostTypeSignature* matching_type_signature, |
| IDebugHostSymbolEnumerator* wildcard_matches); |
| |
| IFACEMETHOD(GetName)(BSTR* model_name); |
| |
| IFACEMETHOD(ToDisplayString) |
| (IModelObject* context_object, IKeyStore* metadata, BSTR* display_string); |
| |
| // IDynamicKeyProviderConcept |
| IFACEMETHOD(GetKey) |
| (IModelObject* context_object, PCWSTR key, IModelObject** key_value, |
| IKeyStore** metadata, bool* has_key); |
| |
| IFACEMETHOD(SetKey) |
| (IModelObject* context_object, PCWSTR key, IModelObject* key_value, |
| IKeyStore* metadata); |
| |
| IFACEMETHOD(EnumerateKeys) |
| (IModelObject* context_object, IKeyEnumerator** pp_enumerator); |
| }; |
| |
| // The implemention of the "Value" getter for V8 handle types. |
| class V8LocalValueProperty |
| : public WRL::RuntimeClass< |
| WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, |
| IModelPropertyAccessor> { |
| public: |
| IFACEMETHOD(GetValue) |
| (PCWSTR pwsz_key, IModelObject* p_v8_object_instance, |
| IModelObject** pp_value); |
| |
| IFACEMETHOD(SetValue) |
| (PCWSTR /*pwsz_key*/, IModelObject* /*p_process_instance*/, |
| IModelObject* /*p_value*/); |
| }; |
| |
| // The implemention of the "NodeId" getter for v8::internal::compiler::Node |
| // type. |
| class V8InternalCompilerNodeIdProperty |
| : public WRL::RuntimeClass< |
| WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, |
| IModelPropertyAccessor> { |
| public: |
| IFACEMETHOD(GetValue) |
| (PCWSTR pwsz_key, IModelObject* p_v8_object_instance, |
| IModelObject** pp_value); |
| |
| IFACEMETHOD(SetValue) |
| (PCWSTR /*pwsz_key*/, IModelObject* /*p_process_instance*/, |
| IModelObject* /*p_value*/); |
| }; |
| |
| // The implemention of the "bitset_name" getter for v8::internal::compiler::Type |
| // type. |
| class V8InternalCompilerBitsetNameProperty |
| : public WRL::RuntimeClass< |
| WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, |
| IModelPropertyAccessor> { |
| public: |
| IFACEMETHOD(GetValue) |
| (PCWSTR pwsz_key, IModelObject* p_v8_compiler_type_instance, |
| IModelObject** pp_value); |
| |
| IFACEMETHOD(SetValue) |
| (PCWSTR /*pwsz_key*/, IModelObject* /*p_process_instance*/, |
| IModelObject* /*p_value*/); |
| }; |
| |
| // A way that someone can directly inspect a tagged value, even if that value |
| // isn't in memory (from a register, or the user's imagination, etc.). |
| class InspectV8ObjectMethod |
| : public WRL::RuntimeClass< |
| WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, |
| IModelMethod> { |
| public: |
| IFACEMETHOD(Call) |
| (IModelObject* p_context_object, ULONG64 arg_count, |
| _In_reads_(arg_count) IModelObject** pp_arguments, IModelObject** pp_result, |
| IKeyStore** pp_metadata); |
| }; |
| |
| HRESULT GetModelForProperty(const Property& prop, |
| WRL::ComPtr<IDebugHostContext>& sp_ctx, |
| IModelObject** result); |
| |
| #endif // V8_TOOLS_V8WINDBG_SRC_OBJECT_INSPECTION_H_ |