blob: 238d8610c7823f2f17d7f79c536ff0c5d2c72c17 [file] [log] [blame]
// 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_