• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2022-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "object_repository.h"
17 
18 #include "include/tooling/pt_lang_extension.h"
19 #include "runtime/handle_scope-inl.h"
20 
21 namespace ark::tooling::inspector {
ObjectRepository()22 ObjectRepository::ObjectRepository()
23     : extension_(ManagedThread::GetCurrent()->GetLanguageContext().CreatePtLangExt()),
24       scope_(ManagedThread::GetCurrent())
25 {
26 }
27 
CreateGlobalObject()28 RemoteObject ObjectRepository::CreateGlobalObject()
29 {
30     return RemoteObject::Object("[Global]", GLOBAL_OBJECT_ID, "Global object");
31 }
32 
CreateFrameObject(const PtFrame & frame,const std::map<std::string,TypedValue> & locals,std::optional<RemoteObject> & objThis)33 RemoteObject ObjectRepository::CreateFrameObject(const PtFrame &frame, const std::map<std::string, TypedValue> &locals,
34                                                  std::optional<RemoteObject> &objThis)
35 {
36     ASSERT(ManagedThread::GetCurrent()->GetMutatorLock()->HasLock());
37 
38     std::vector<PropertyDescriptor> properties;
39     properties.reserve(locals.size());
40     auto thisParamName = extension_->GetThisParameterName();
41     for (const auto &[paramName, value] : locals) {
42         auto obj = CreateObject(value);
43         if (paramName == thisParamName) {
44             objThis.emplace(std::move(obj));
45         } else {
46             properties.emplace_back(paramName, std::move(obj));
47         }
48     }
49 
50     auto id = counter_++;
51     frames_.emplace(id, std::move(properties));
52 
53     return RemoteObject::Object("", id, "Frame #" + std::to_string(frame.GetFrameId()));
54 }
55 
CreateObject(TypedValue value)56 RemoteObject ObjectRepository::CreateObject(TypedValue value)
57 {
58     ASSERT(ManagedThread::GetCurrent()->GetMutatorLock()->HasLock());
59 
60     switch (value.GetType()) {
61         case panda_file::Type::TypeId::INVALID:
62         case panda_file::Type::TypeId::VOID:
63             return RemoteObject::Undefined();
64         case panda_file::Type::TypeId::U1:
65             return RemoteObject::Boolean(value.GetAsU1());
66         case panda_file::Type::TypeId::I8:
67             return RemoteObject::Number(value.GetAsI8());
68         case panda_file::Type::TypeId::U8:
69             return RemoteObject::Number(value.GetAsU8());
70         case panda_file::Type::TypeId::I16:
71             return RemoteObject::Number(value.GetAsI16());
72         case panda_file::Type::TypeId::U16:
73             return RemoteObject::Number(value.GetAsU16());
74         case panda_file::Type::TypeId::I32:
75             return RemoteObject::Number(value.GetAsI32());
76         case panda_file::Type::TypeId::U32:
77             return RemoteObject::Number(value.GetAsU32());
78         case panda_file::Type::TypeId::F32:
79             return RemoteObject::Number(value.GetAsF32());
80         case panda_file::Type::TypeId::F64:
81             return RemoteObject::Number(value.GetAsF64());
82         case panda_file::Type::TypeId::I64:
83             return RemoteObject::Number(value.GetAsI64());
84         case panda_file::Type::TypeId::U64:
85             return RemoteObject::Number(value.GetAsU64());
86         case panda_file::Type::TypeId::REFERENCE:
87             return CreateObject(value.GetAsReference());
88         case panda_file::Type::TypeId::TAGGED:
89             return CreateObject(value.GetAsTagged());
90     }
91     UNREACHABLE();
92 }
93 
GetProperties(RemoteObjectId id,bool generatePreview)94 std::vector<PropertyDescriptor> ObjectRepository::GetProperties(RemoteObjectId id, bool generatePreview)
95 {
96     ASSERT(ManagedThread::GetCurrent()->GetMutatorLock()->HasLock());
97 
98     auto properties = GetProperties(id);
99 
100     if (generatePreview) {
101         for (auto &property : properties) {
102             if (property.IsAccessor()) {
103                 continue;
104             }
105 
106             RemoteObject &value = property.GetValue();
107             auto preview = CreateObjectPreview(value);
108             if (preview.has_value()) {
109                 value.SetObjectPreview(std::move(*preview));
110             }
111         }
112     }
113 
114     return properties;
115 }
116 
CreateObjectPreview(RemoteObject & remobj)117 std::optional<ObjectPreview> ObjectRepository::CreateObjectPreview(RemoteObject &remobj)
118 {
119     auto valueId = remobj.GetObjectId();
120     if (!valueId.has_value()) {
121         return {};
122     }
123 
124     ObjectPreview preview(remobj.GetType(), GetProperties(*valueId));
125 
126     return preview;
127 }
128 
CreateObject(coretypes::TaggedValue value)129 RemoteObject ObjectRepository::CreateObject(coretypes::TaggedValue value)
130 {
131     if (value.IsHeapObject()) {
132         return CreateObject(value.GetHeapObject());
133     }
134     if (value.IsUndefined() || value.IsHole()) {
135         return RemoteObject::Undefined();
136     }
137     if (value.IsNull()) {
138         return RemoteObject::Null();
139     }
140     if (value.IsBoolean()) {
141         return RemoteObject::Boolean(value.IsTrue());
142     }
143     if (value.IsInt()) {
144         return RemoteObject::Number(value.GetInt());
145     }
146     if (value.IsDouble()) {
147         return RemoteObject::Number(value.GetDouble());
148     }
149     UNREACHABLE();
150 }
151 
CreateObject(ObjectHeader * object)152 RemoteObject ObjectRepository::CreateObject(ObjectHeader *object)
153 {
154     ASSERT(ManagedThread::GetCurrent()->GetMutatorLock()->HasLock());
155 
156     if (object == nullptr) {
157         return RemoteObject::Null();
158     }
159 
160     if (auto str = extension_->GetAsString(object)) {
161         return RemoteObject::String(*str);
162     }
163 
164     RemoteObjectId id;
165 
166     // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
167     auto it = std::find_if(objects_.begin(), objects_.end(), [object](auto &p) { return p.second.GetPtr() == object; });
168     if (it == objects_.end()) {
169         id = counter_++;
170 
171         objects_.emplace(std::piecewise_construct, std::forward_as_tuple(id),
172                          std::forward_as_tuple(ManagedThread::GetCurrent(), object));
173     } else {
174         id = it->first;
175     }
176 
177     // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
178     if (auto arrayLen = extension_->GetLengthIfArray(object)) {
179         // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
180         return RemoteObject::Array(extension_->GetClassName(object), *arrayLen, id);
181     }
182 
183     // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
184     return RemoteObject::Object(extension_->GetClassName(object), id);
185 }
186 
GetProperties(RemoteObjectId id)187 std::vector<PropertyDescriptor> ObjectRepository::GetProperties(RemoteObjectId id)
188 {
189     ASSERT(ManagedThread::GetCurrent()->GetMutatorLock()->HasLock());
190 
191     auto fIt = frames_.find(id);
192     if (fIt != frames_.end()) {
193         ASSERT(objects_.find(id) == objects_.end());
194         return fIt->second;
195     }
196 
197     std::vector<PropertyDescriptor> properties;
198     auto propertyHandler = [this, &properties](auto &name, auto value, auto isFinal, auto isAccessor) {
199         auto property = isAccessor ? PropertyDescriptor::Accessor(name, CreateObject(value))
200                                    : PropertyDescriptor(name, CreateObject(value));
201         if (!isAccessor && isFinal) {
202             property.SetWritable(false);
203         }
204         properties.emplace_back(std::move(property));
205     };
206 
207     if (id == GLOBAL_OBJECT_ID) {
208         ASSERT(objects_.find(id) == objects_.end());
209         extension_->EnumerateGlobals(propertyHandler);
210     } else {
211         auto oIt = objects_.find(id);
212         if (oIt == objects_.end()) {
213             LOG(INFO, DEBUGGER) << "Unknown object ID " << id;
214             return {};
215         }
216 
217         extension_->EnumerateProperties(oIt->second.GetPtr(), propertyHandler);
218     }
219 
220     return properties;
221 }
222 }  // namespace ark::tooling::inspector
223