11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "tools/v8windbg/src/v8windbg-extension.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <iostream>
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci#include "tools/v8windbg/base/utilities.h"
101cb0ef41Sopenharmony_ci#include "tools/v8windbg/src/cur-isolate.h"
111cb0ef41Sopenharmony_ci#include "tools/v8windbg/src/js-stack.h"
121cb0ef41Sopenharmony_ci#include "tools/v8windbg/src/local-variables.h"
131cb0ef41Sopenharmony_ci#include "tools/v8windbg/src/object-inspection.h"
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_cistd::unique_ptr<Extension> Extension::current_extension_ = nullptr;
161cb0ef41Sopenharmony_ciconst wchar_t* pcur_isolate = L"curisolate";
171cb0ef41Sopenharmony_ciconst wchar_t* pjs_stack = L"jsstack";
181cb0ef41Sopenharmony_ciconst wchar_t* pv8_object = L"v8object";
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ciHRESULT CreateExtension() {
211cb0ef41Sopenharmony_ci  if (Extension::Current() != nullptr || sp_data_model_manager == nullptr ||
221cb0ef41Sopenharmony_ci      sp_debug_host == nullptr) {
231cb0ef41Sopenharmony_ci    return E_FAIL;
241cb0ef41Sopenharmony_ci  } else {
251cb0ef41Sopenharmony_ci    std::unique_ptr<Extension> new_extension(new (std::nothrow) Extension());
261cb0ef41Sopenharmony_ci    if (new_extension == nullptr) return E_FAIL;
271cb0ef41Sopenharmony_ci    RETURN_IF_FAIL(new_extension->Initialize());
281cb0ef41Sopenharmony_ci    Extension::SetExtension(std::move(new_extension));
291cb0ef41Sopenharmony_ci    return S_OK;
301cb0ef41Sopenharmony_ci  }
311cb0ef41Sopenharmony_ci}
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_civoid DestroyExtension() { Extension::SetExtension(nullptr); }
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_cibool Extension::DoesTypeDeriveFromObject(
361cb0ef41Sopenharmony_ci    const WRL::ComPtr<IDebugHostType>& sp_type) {
371cb0ef41Sopenharmony_ci  _bstr_t name;
381cb0ef41Sopenharmony_ci  HRESULT hr = sp_type->GetName(name.GetAddress());
391cb0ef41Sopenharmony_ci  if (!SUCCEEDED(hr)) return false;
401cb0ef41Sopenharmony_ci  if (std::string(static_cast<const char*>(name)) == kObject) return true;
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci  WRL::ComPtr<IDebugHostSymbolEnumerator> sp_super_class_enumerator;
431cb0ef41Sopenharmony_ci  hr = sp_type->EnumerateChildren(SymbolKind::SymbolBaseClass, nullptr,
441cb0ef41Sopenharmony_ci                                  &sp_super_class_enumerator);
451cb0ef41Sopenharmony_ci  if (!SUCCEEDED(hr)) return false;
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci  while (true) {
481cb0ef41Sopenharmony_ci    WRL::ComPtr<IDebugHostSymbol> sp_type_symbol;
491cb0ef41Sopenharmony_ci    if (sp_super_class_enumerator->GetNext(&sp_type_symbol) != S_OK) break;
501cb0ef41Sopenharmony_ci    WRL::ComPtr<IDebugHostBaseClass> sp_base_class;
511cb0ef41Sopenharmony_ci    if (FAILED(sp_type_symbol.As(&sp_base_class))) continue;
521cb0ef41Sopenharmony_ci    WRL::ComPtr<IDebugHostType> sp_base_type;
531cb0ef41Sopenharmony_ci    hr = sp_base_class->GetType(&sp_base_type);
541cb0ef41Sopenharmony_ci    if (!SUCCEEDED(hr)) continue;
551cb0ef41Sopenharmony_ci    if (DoesTypeDeriveFromObject(sp_base_type)) {
561cb0ef41Sopenharmony_ci      return true;
571cb0ef41Sopenharmony_ci    }
581cb0ef41Sopenharmony_ci  }
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  return false;
611cb0ef41Sopenharmony_ci}
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ciWRL::ComPtr<IDebugHostType> Extension::GetV8ObjectType(
641cb0ef41Sopenharmony_ci    WRL::ComPtr<IDebugHostContext>& sp_ctx) {
651cb0ef41Sopenharmony_ci  return GetTypeFromV8Module(sp_ctx, kObjectU);
661cb0ef41Sopenharmony_ci}
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ciWRL::ComPtr<IDebugHostType> Extension::GetTypeFromV8Module(
691cb0ef41Sopenharmony_ci    WRL::ComPtr<IDebugHostContext>& sp_ctx, const char16_t* type_name) {
701cb0ef41Sopenharmony_ci  bool is_equal;
711cb0ef41Sopenharmony_ci  if (sp_v8_module_ctx_ == nullptr ||
721cb0ef41Sopenharmony_ci      !SUCCEEDED(sp_v8_module_ctx_->IsEqualTo(sp_ctx.Get(), &is_equal)) ||
731cb0ef41Sopenharmony_ci      !is_equal) {
741cb0ef41Sopenharmony_ci    // Context changed; clear the dictionary.
751cb0ef41Sopenharmony_ci    cached_v8_module_types_.clear();
761cb0ef41Sopenharmony_ci  }
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci  GetV8Module(sp_ctx);  // Will force the correct module to load
791cb0ef41Sopenharmony_ci  if (sp_v8_module_ == nullptr) return nullptr;
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  auto& dictionary_entry = cached_v8_module_types_[type_name];
821cb0ef41Sopenharmony_ci  if (dictionary_entry == nullptr) {
831cb0ef41Sopenharmony_ci    const std::wstring type_name_w(reinterpret_cast<const wchar_t*>(type_name));
841cb0ef41Sopenharmony_ci    // The contract from debug_helper functions is to provide type names that
851cb0ef41Sopenharmony_ci    // would be valid if used in C++ code within the v8::internal namespace.
861cb0ef41Sopenharmony_ci    // They might be fully qualified but aren't required to be. Thus, we must
871cb0ef41Sopenharmony_ci    // simluate an "unqualified name lookup" here, by searching for the type
881cb0ef41Sopenharmony_ci    // starting in the innermost namespace and working outward.
891cb0ef41Sopenharmony_ci    if (SUCCEEDED(sp_v8_module_->FindTypeByName(
901cb0ef41Sopenharmony_ci            (L"v8::internal::" + type_name_w).c_str(), &dictionary_entry))) {
911cb0ef41Sopenharmony_ci      return dictionary_entry;
921cb0ef41Sopenharmony_ci    }
931cb0ef41Sopenharmony_ci    if (SUCCEEDED(sp_v8_module_->FindTypeByName((L"v8::" + type_name_w).c_str(),
941cb0ef41Sopenharmony_ci                                                &dictionary_entry))) {
951cb0ef41Sopenharmony_ci      return dictionary_entry;
961cb0ef41Sopenharmony_ci    }
971cb0ef41Sopenharmony_ci    sp_v8_module_->FindTypeByName(reinterpret_cast<PCWSTR>(type_name),
981cb0ef41Sopenharmony_ci                                  &dictionary_entry);
991cb0ef41Sopenharmony_ci  }
1001cb0ef41Sopenharmony_ci  return dictionary_entry;
1011cb0ef41Sopenharmony_ci}
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_cinamespace {
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci// Returns whether the given module appears to have symbols for V8 code.
1061cb0ef41Sopenharmony_cibool IsV8Module(IDebugHostModule* module) {
1071cb0ef41Sopenharmony_ci  WRL::ComPtr<IDebugHostSymbol> sp_isolate_sym;
1081cb0ef41Sopenharmony_ci  // The below symbol is specific to the main V8 module and is specified with
1091cb0ef41Sopenharmony_ci  // V8_NOINLINE, so it should always be present.
1101cb0ef41Sopenharmony_ci  if (FAILED(module->FindSymbolByName(
1111cb0ef41Sopenharmony_ci          L"v8::internal::Isolate::PushStackTraceAndDie", &sp_isolate_sym))) {
1121cb0ef41Sopenharmony_ci    return false;
1131cb0ef41Sopenharmony_ci  }
1141cb0ef41Sopenharmony_ci  return true;
1151cb0ef41Sopenharmony_ci}
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci}  // namespace
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ciWRL::ComPtr<IDebugHostModule> Extension::GetV8Module(
1201cb0ef41Sopenharmony_ci    WRL::ComPtr<IDebugHostContext>& sp_ctx) {
1211cb0ef41Sopenharmony_ci  // Return the cached version if it exists and the context is the same
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci  // Note: Context will often have the CUSTOM flag set, which never compares
1241cb0ef41Sopenharmony_ci  // equal. So for now DON'T compare by context, but by proc_id. (An API is in
1251cb0ef41Sopenharmony_ci  // progress to compare by address space, which should be usable when shipped).
1261cb0ef41Sopenharmony_ci  /*
1271cb0ef41Sopenharmony_ci  if (sp_v8_module_ != nullptr) {
1281cb0ef41Sopenharmony_ci    bool is_equal;
1291cb0ef41Sopenharmony_ci    if (SUCCEEDED(sp_v8_module_ctx_->IsEqualTo(sp_ctx.Get(), &is_equal)) &&
1301cb0ef41Sopenharmony_ci  is_equal) { return sp_v8_module_; } else { sp_v8_module_ = nullptr;
1311cb0ef41Sopenharmony_ci      sp_v8_module_ctx_ = nullptr;
1321cb0ef41Sopenharmony_ci    }
1331cb0ef41Sopenharmony_ci  }
1341cb0ef41Sopenharmony_ci  */
1351cb0ef41Sopenharmony_ci  WRL::ComPtr<IDebugSystemObjects> sp_sys_objects;
1361cb0ef41Sopenharmony_ci  ULONG proc_id = 0;
1371cb0ef41Sopenharmony_ci  if (SUCCEEDED(sp_debug_control.As(&sp_sys_objects))) {
1381cb0ef41Sopenharmony_ci    if (SUCCEEDED(sp_sys_objects->GetCurrentProcessSystemId(&proc_id))) {
1391cb0ef41Sopenharmony_ci      if (proc_id == v8_module_proc_id_ && sp_v8_module_ != nullptr)
1401cb0ef41Sopenharmony_ci        return sp_v8_module_;
1411cb0ef41Sopenharmony_ci    }
1421cb0ef41Sopenharmony_ci  }
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci  // Search first for a few known module names, to avoid loading symbols for
1451cb0ef41Sopenharmony_ci  // unrelated modules if we can easily avoid it. Generally, failing to find a
1461cb0ef41Sopenharmony_ci  // module is fast but failing to find a symbol within a module is slow. Note
1471cb0ef41Sopenharmony_ci  // that "v8" is listed first because it's highly likely to be the correct
1481cb0ef41Sopenharmony_ci  // module if it exists. The others might include V8 symbols depending on the
1491cb0ef41Sopenharmony_ci  // build configuration.
1501cb0ef41Sopenharmony_ci  std::vector<const wchar_t*> known_names = {
1511cb0ef41Sopenharmony_ci      L"v8", L"v8_for_testing", L"cctest_exe", L"chrome",
1521cb0ef41Sopenharmony_ci      L"d8", L"msedge",         L"node",       L"unittests_exe"};
1531cb0ef41Sopenharmony_ci  for (const wchar_t* name : known_names) {
1541cb0ef41Sopenharmony_ci    WRL::ComPtr<IDebugHostModule> sp_module;
1551cb0ef41Sopenharmony_ci    if (SUCCEEDED(sp_debug_host_symbols->FindModuleByName(sp_ctx.Get(), name,
1561cb0ef41Sopenharmony_ci                                                          &sp_module))) {
1571cb0ef41Sopenharmony_ci      if (IsV8Module(sp_module.Get())) {
1581cb0ef41Sopenharmony_ci        sp_v8_module_ = sp_module;
1591cb0ef41Sopenharmony_ci        sp_v8_module_ctx_ = sp_ctx;
1601cb0ef41Sopenharmony_ci        v8_module_proc_id_ = proc_id;
1611cb0ef41Sopenharmony_ci        return sp_v8_module_;
1621cb0ef41Sopenharmony_ci      }
1631cb0ef41Sopenharmony_ci    }
1641cb0ef41Sopenharmony_ci  }
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci  // Loop through all modules looking for the one that holds a known symbol.
1671cb0ef41Sopenharmony_ci  WRL::ComPtr<IDebugHostSymbolEnumerator> sp_enum;
1681cb0ef41Sopenharmony_ci  if (SUCCEEDED(
1691cb0ef41Sopenharmony_ci          sp_debug_host_symbols->EnumerateModules(sp_ctx.Get(), &sp_enum))) {
1701cb0ef41Sopenharmony_ci    HRESULT hr = S_OK;
1711cb0ef41Sopenharmony_ci    while (true) {
1721cb0ef41Sopenharmony_ci      WRL::ComPtr<IDebugHostSymbol> sp_mod_sym;
1731cb0ef41Sopenharmony_ci      hr = sp_enum->GetNext(&sp_mod_sym);
1741cb0ef41Sopenharmony_ci      // hr == E_BOUNDS : hit the end of the enumerator
1751cb0ef41Sopenharmony_ci      // hr == E_ABORT  : a user interrupt was requested
1761cb0ef41Sopenharmony_ci      if (FAILED(hr)) break;
1771cb0ef41Sopenharmony_ci      WRL::ComPtr<IDebugHostModule> sp_module;
1781cb0ef41Sopenharmony_ci      if (SUCCEEDED(sp_mod_sym.As(&sp_module))) /* should always succeed */
1791cb0ef41Sopenharmony_ci      {
1801cb0ef41Sopenharmony_ci        if (IsV8Module(sp_module.Get())) {
1811cb0ef41Sopenharmony_ci          sp_v8_module_ = sp_module;
1821cb0ef41Sopenharmony_ci          sp_v8_module_ctx_ = sp_ctx;
1831cb0ef41Sopenharmony_ci          v8_module_proc_id_ = proc_id;
1841cb0ef41Sopenharmony_ci          break;
1851cb0ef41Sopenharmony_ci        }
1861cb0ef41Sopenharmony_ci      }
1871cb0ef41Sopenharmony_ci    }
1881cb0ef41Sopenharmony_ci  }
1891cb0ef41Sopenharmony_ci  // This will be the located module, or still nullptr if above fails
1901cb0ef41Sopenharmony_ci  return sp_v8_module_;
1911cb0ef41Sopenharmony_ci}
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ciExtension::Extension() = default;
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ciHRESULT Extension::Initialize() {
1961cb0ef41Sopenharmony_ci  // Create an instance of the DataModel parent for v8::internal::Object types.
1971cb0ef41Sopenharmony_ci  auto object_data_model{WRL::Make<V8ObjectDataModel>()};
1981cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(sp_data_model_manager->CreateDataModelObject(
1991cb0ef41Sopenharmony_ci      object_data_model.Get(), &sp_object_data_model_));
2001cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(sp_object_data_model_->SetConcept(
2011cb0ef41Sopenharmony_ci      __uuidof(IStringDisplayableConcept),
2021cb0ef41Sopenharmony_ci      static_cast<IStringDisplayableConcept*>(object_data_model.Get()),
2031cb0ef41Sopenharmony_ci      nullptr));
2041cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(sp_object_data_model_->SetConcept(
2051cb0ef41Sopenharmony_ci      __uuidof(IDynamicKeyProviderConcept),
2061cb0ef41Sopenharmony_ci      static_cast<IDynamicKeyProviderConcept*>(object_data_model.Get()),
2071cb0ef41Sopenharmony_ci      nullptr));
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_ci  // Register that parent model for all known types of V8 object.
2101cb0ef41Sopenharmony_ci  std::vector<std::u16string> object_class_names = ListObjectClasses();
2111cb0ef41Sopenharmony_ci  object_class_names.push_back(kObjectU);
2121cb0ef41Sopenharmony_ci  object_class_names.push_back(kTaggedValueU);
2131cb0ef41Sopenharmony_ci  for (const std::u16string& name : object_class_names) {
2141cb0ef41Sopenharmony_ci    WRL::ComPtr<IDebugHostTypeSignature> sp_object_type_signature;
2151cb0ef41Sopenharmony_ci    RETURN_IF_FAIL(sp_debug_host_symbols->CreateTypeSignature(
2161cb0ef41Sopenharmony_ci        reinterpret_cast<const wchar_t*>(name.c_str()), nullptr,
2171cb0ef41Sopenharmony_ci        &sp_object_type_signature));
2181cb0ef41Sopenharmony_ci    RETURN_IF_FAIL(sp_data_model_manager->RegisterModelForTypeSignature(
2191cb0ef41Sopenharmony_ci        sp_object_type_signature.Get(), sp_object_data_model_.Get()));
2201cb0ef41Sopenharmony_ci    registered_types_.push_back(
2211cb0ef41Sopenharmony_ci        {sp_object_type_signature.Get(), sp_object_data_model_.Get()});
2221cb0ef41Sopenharmony_ci  }
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci  // Create an instance of the DataModel parent for custom iterable fields.
2251cb0ef41Sopenharmony_ci  auto indexed_field_model{WRL::Make<IndexedFieldParent>()};
2261cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(sp_data_model_manager->CreateDataModelObject(
2271cb0ef41Sopenharmony_ci      indexed_field_model.Get(), &sp_indexed_field_model_));
2281cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(sp_indexed_field_model_->SetConcept(
2291cb0ef41Sopenharmony_ci      __uuidof(IIndexableConcept),
2301cb0ef41Sopenharmony_ci      static_cast<IIndexableConcept*>(indexed_field_model.Get()), nullptr));
2311cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(sp_indexed_field_model_->SetConcept(
2321cb0ef41Sopenharmony_ci      __uuidof(IIterableConcept),
2331cb0ef41Sopenharmony_ci      static_cast<IIterableConcept*>(indexed_field_model.Get()), nullptr));
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ci  // Create an instance of the DataModel parent class for v8::Local<*> types.
2361cb0ef41Sopenharmony_ci  auto local_data_model{WRL::Make<V8LocalDataModel>()};
2371cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(sp_data_model_manager->CreateDataModelObject(
2381cb0ef41Sopenharmony_ci      local_data_model.Get(), &sp_local_data_model_));
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ci  // Register that parent model for all known types that act like v8::Local.
2411cb0ef41Sopenharmony_ci  std::vector<const wchar_t*> handle_class_names = {
2421cb0ef41Sopenharmony_ci      L"v8::Local<*>", L"v8::MaybeLocal<*>", L"v8::internal::Handle<*>",
2431cb0ef41Sopenharmony_ci      L"v8::internal::MaybeHandle<*>"};
2441cb0ef41Sopenharmony_ci  for (const wchar_t* name : handle_class_names) {
2451cb0ef41Sopenharmony_ci    WRL::ComPtr<IDebugHostTypeSignature> signature;
2461cb0ef41Sopenharmony_ci    RETURN_IF_FAIL(
2471cb0ef41Sopenharmony_ci        sp_debug_host_symbols->CreateTypeSignature(name, nullptr, &signature));
2481cb0ef41Sopenharmony_ci    RETURN_IF_FAIL(sp_data_model_manager->RegisterModelForTypeSignature(
2491cb0ef41Sopenharmony_ci        signature.Get(), sp_local_data_model_.Get()));
2501cb0ef41Sopenharmony_ci    registered_types_.push_back({signature.Get(), sp_local_data_model_.Get()});
2511cb0ef41Sopenharmony_ci  }
2521cb0ef41Sopenharmony_ci
2531cb0ef41Sopenharmony_ci  // Add the 'Value' property to the parent model.
2541cb0ef41Sopenharmony_ci  auto local_value_property{WRL::Make<V8LocalValueProperty>()};
2551cb0ef41Sopenharmony_ci  WRL::ComPtr<IModelObject> sp_local_value_property_model;
2561cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(CreateProperty(sp_data_model_manager.Get(),
2571cb0ef41Sopenharmony_ci                                local_value_property.Get(),
2581cb0ef41Sopenharmony_ci                                &sp_local_value_property_model));
2591cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(sp_local_data_model_->SetKey(
2601cb0ef41Sopenharmony_ci      L"Value", sp_local_value_property_model.Get(), nullptr));
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_ci  // Register all function aliases.
2631cb0ef41Sopenharmony_ci  std::vector<std::pair<const wchar_t*, WRL::ComPtr<IModelMethod>>> functions =
2641cb0ef41Sopenharmony_ci      {{pcur_isolate, WRL::Make<CurrIsolateAlias>()},
2651cb0ef41Sopenharmony_ci       {pjs_stack, WRL::Make<JSStackAlias>()},
2661cb0ef41Sopenharmony_ci       {pv8_object, WRL::Make<InspectV8ObjectMethod>()}};
2671cb0ef41Sopenharmony_ci  for (const auto& function : functions) {
2681cb0ef41Sopenharmony_ci    WRL::ComPtr<IModelObject> method;
2691cb0ef41Sopenharmony_ci    RETURN_IF_FAIL(CreateMethod(sp_data_model_manager.Get(),
2701cb0ef41Sopenharmony_ci                                function.second.Get(), &method));
2711cb0ef41Sopenharmony_ci    RETURN_IF_FAIL(sp_debug_host_extensibility->CreateFunctionAlias(
2721cb0ef41Sopenharmony_ci        function.first, method.Get()));
2731cb0ef41Sopenharmony_ci  }
2741cb0ef41Sopenharmony_ci
2751cb0ef41Sopenharmony_ci  // Register a handler for supplying stack frame locals. It has to override the
2761cb0ef41Sopenharmony_ci  // getter functions for "LocalVariables" and "Parameters".
2771cb0ef41Sopenharmony_ci  WRL::ComPtr<IModelObject> stack_frame;
2781cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(sp_data_model_manager->AcquireNamedModel(
2791cb0ef41Sopenharmony_ci      L"Debugger.Models.StackFrame", &stack_frame));
2801cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(OverrideLocalsGetter(stack_frame.Get(), L"LocalVariables",
2811cb0ef41Sopenharmony_ci                                      /*is_parameters=*/false));
2821cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(OverrideLocalsGetter(stack_frame.Get(), L"Parameters",
2831cb0ef41Sopenharmony_ci                                      /*is_parameters=*/true));
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci  // Add node_id property for v8::internal::compiler::Node.
2861cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(
2871cb0ef41Sopenharmony_ci      RegisterAndAddPropertyForClass<V8InternalCompilerNodeIdProperty>(
2881cb0ef41Sopenharmony_ci          L"v8::internal::compiler::Node", L"node_id",
2891cb0ef41Sopenharmony_ci          sp_compiler_node_data_model_));
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_ci  // Add bitset_name property for v8::internal::compiler::Type.
2921cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(
2931cb0ef41Sopenharmony_ci      RegisterAndAddPropertyForClass<V8InternalCompilerBitsetNameProperty>(
2941cb0ef41Sopenharmony_ci          L"v8::internal::compiler::Type", L"bitset_name",
2951cb0ef41Sopenharmony_ci          sp_compiler_type_data_model_));
2961cb0ef41Sopenharmony_ci
2971cb0ef41Sopenharmony_ci  return S_OK;
2981cb0ef41Sopenharmony_ci}
2991cb0ef41Sopenharmony_ci
3001cb0ef41Sopenharmony_citemplate <class PropertyClass>
3011cb0ef41Sopenharmony_ciHRESULT Extension::RegisterAndAddPropertyForClass(
3021cb0ef41Sopenharmony_ci    const wchar_t* class_name, const wchar_t* property_name,
3031cb0ef41Sopenharmony_ci    WRL::ComPtr<IModelObject> sp_data_model) {
3041cb0ef41Sopenharmony_ci  // Create an instance of the DataModel parent class.
3051cb0ef41Sopenharmony_ci  auto instance_data_model{WRL::Make<V8LocalDataModel>()};
3061cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(sp_data_model_manager->CreateDataModelObject(
3071cb0ef41Sopenharmony_ci      instance_data_model.Get(), &sp_data_model));
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ci  // Register that parent model.
3101cb0ef41Sopenharmony_ci  WRL::ComPtr<IDebugHostTypeSignature> class_signature;
3111cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(sp_debug_host_symbols->CreateTypeSignature(class_name, nullptr,
3121cb0ef41Sopenharmony_ci                                                            &class_signature));
3131cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(sp_data_model_manager->RegisterModelForTypeSignature(
3141cb0ef41Sopenharmony_ci      class_signature.Get(), sp_data_model.Get()));
3151cb0ef41Sopenharmony_ci  registered_types_.push_back({class_signature.Get(), sp_data_model.Get()});
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci  // Add the property to the parent model.
3181cb0ef41Sopenharmony_ci  auto property{WRL::Make<PropertyClass>()};
3191cb0ef41Sopenharmony_ci  WRL::ComPtr<IModelObject> sp_property_model;
3201cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(CreateProperty(sp_data_model_manager.Get(), property.Get(),
3211cb0ef41Sopenharmony_ci                                &sp_property_model));
3221cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(
3231cb0ef41Sopenharmony_ci      sp_data_model->SetKey(property_name, sp_property_model.Get(), nullptr));
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_ci  return S_OK;
3261cb0ef41Sopenharmony_ci}
3271cb0ef41Sopenharmony_ci
3281cb0ef41Sopenharmony_ciHRESULT Extension::OverrideLocalsGetter(IModelObject* stack_frame,
3291cb0ef41Sopenharmony_ci                                        const wchar_t* key_name,
3301cb0ef41Sopenharmony_ci                                        bool is_parameters) {
3311cb0ef41Sopenharmony_ci  WRL::ComPtr<IModelObject> original_boxed_getter;
3321cb0ef41Sopenharmony_ci  WRL::ComPtr<IKeyStore> original_getter_metadata;
3331cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(stack_frame->GetKey(key_name, &original_boxed_getter,
3341cb0ef41Sopenharmony_ci                                     &original_getter_metadata));
3351cb0ef41Sopenharmony_ci  WRL::ComPtr<IModelPropertyAccessor> original_getter;
3361cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(UnboxProperty(original_boxed_getter.Get(), &original_getter));
3371cb0ef41Sopenharmony_ci  auto new_getter{WRL::Make<V8LocalVariables>(original_getter, is_parameters)};
3381cb0ef41Sopenharmony_ci  WRL::ComPtr<IModelObject> new_boxed_getter;
3391cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(CreateProperty(sp_data_model_manager.Get(), new_getter.Get(),
3401cb0ef41Sopenharmony_ci                                &new_boxed_getter));
3411cb0ef41Sopenharmony_ci  RETURN_IF_FAIL(stack_frame->SetKey(key_name, new_boxed_getter.Get(),
3421cb0ef41Sopenharmony_ci                                     original_getter_metadata.Get()));
3431cb0ef41Sopenharmony_ci  overridden_properties_.push_back(
3441cb0ef41Sopenharmony_ci      {stack_frame, reinterpret_cast<const char16_t*>(key_name),
3451cb0ef41Sopenharmony_ci       original_boxed_getter.Get(), original_getter_metadata.Get()});
3461cb0ef41Sopenharmony_ci  return S_OK;
3471cb0ef41Sopenharmony_ci}
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_ciExtension::PropertyOverride::PropertyOverride() = default;
3501cb0ef41Sopenharmony_ciExtension::PropertyOverride::PropertyOverride(IModelObject* parent,
3511cb0ef41Sopenharmony_ci                                              std::u16string key_name,
3521cb0ef41Sopenharmony_ci                                              IModelObject* original_value,
3531cb0ef41Sopenharmony_ci                                              IKeyStore* original_metadata)
3541cb0ef41Sopenharmony_ci    : parent(parent),
3551cb0ef41Sopenharmony_ci      key_name(std::move(key_name)),
3561cb0ef41Sopenharmony_ci      original_value(original_value),
3571cb0ef41Sopenharmony_ci      original_metadata(original_metadata) {}
3581cb0ef41Sopenharmony_ciExtension::PropertyOverride::~PropertyOverride() = default;
3591cb0ef41Sopenharmony_ciExtension::PropertyOverride::PropertyOverride(const PropertyOverride&) =
3601cb0ef41Sopenharmony_ci    default;
3611cb0ef41Sopenharmony_ciExtension::PropertyOverride& Extension::PropertyOverride::operator=(
3621cb0ef41Sopenharmony_ci    const PropertyOverride&) = default;
3631cb0ef41Sopenharmony_ci
3641cb0ef41Sopenharmony_ciExtension::RegistrationType::RegistrationType() = default;
3651cb0ef41Sopenharmony_ciExtension::RegistrationType::RegistrationType(
3661cb0ef41Sopenharmony_ci    IDebugHostTypeSignature* sp_signature, IModelObject* sp_data_model)
3671cb0ef41Sopenharmony_ci    : sp_signature(sp_signature), sp_data_model(sp_data_model) {}
3681cb0ef41Sopenharmony_ciExtension::RegistrationType::~RegistrationType() = default;
3691cb0ef41Sopenharmony_ciExtension::RegistrationType::RegistrationType(const RegistrationType&) =
3701cb0ef41Sopenharmony_ci    default;
3711cb0ef41Sopenharmony_ciExtension::RegistrationType& Extension::RegistrationType::operator=(
3721cb0ef41Sopenharmony_ci    const RegistrationType&) = default;
3731cb0ef41Sopenharmony_ci
3741cb0ef41Sopenharmony_ciExtension::~Extension() {
3751cb0ef41Sopenharmony_ci  sp_debug_host_extensibility->DestroyFunctionAlias(pcur_isolate);
3761cb0ef41Sopenharmony_ci  sp_debug_host_extensibility->DestroyFunctionAlias(pjs_stack);
3771cb0ef41Sopenharmony_ci  sp_debug_host_extensibility->DestroyFunctionAlias(pv8_object);
3781cb0ef41Sopenharmony_ci
3791cb0ef41Sopenharmony_ci  for (const auto& registered : registered_types_) {
3801cb0ef41Sopenharmony_ci    sp_data_model_manager->UnregisterModelForTypeSignature(
3811cb0ef41Sopenharmony_ci        registered.sp_data_model.Get(), registered.sp_signature.Get());
3821cb0ef41Sopenharmony_ci  }
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ci  for (const auto& override : overridden_properties_) {
3851cb0ef41Sopenharmony_ci    override.parent->SetKey(
3861cb0ef41Sopenharmony_ci        reinterpret_cast<const wchar_t*>(override.key_name.c_str()),
3871cb0ef41Sopenharmony_ci        override.original_value.Get(), override.original_metadata.Get());
3881cb0ef41Sopenharmony_ci  }
3891cb0ef41Sopenharmony_ci}
390