• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 "ecmascript/debugger/debugger_api.h"
17 
18 #include "ecmascript/base/number_helper.h"
19 #include "ecmascript/debugger/js_debugger.h"
20 #include "ecmascript/ecma_macros.h"
21 #include "ecmascript/interpreter/frame_handler.h"
22 #include "ecmascript/interpreter/slow_runtime_stub.h"
23 #include "ecmascript/interpreter/fast_runtime_stub-inl.h"
24 #include "ecmascript/jspandafile/js_pandafile_executor.h"
25 #include "ecmascript/jspandafile/program_object.h"
26 #include "ecmascript/js_handle.h"
27 #include "ecmascript/jspandafile/js_pandafile_manager.h"
28 #include "ecmascript/method.h"
29 #include "ecmascript/module/js_module_manager.h"
30 #include "ecmascript/module/js_module_source_text.h"
31 #include "ecmascript/napi/jsnapi_helper.h"
32 #include "ecmascript/tagged_array.h"
33 #include "ecmascript/tagged_dictionary.h"
34 #include "ecmascript/tagged_hash_array.h"
35 #include "ecmascript/tagged_tree.h"
36 #include "ecmascript/tagged_queue.h"
37 #include "ecmascript/js_api/js_api_hashmap.h"
38 #include "ecmascript/js_api/js_api_hashset.h"
39 #include "ecmascript/js_api/js_api_tree_map.h"
40 #include "ecmascript/js_api/js_api_tree_set.h"
41 #include "ecmascript/js_api/js_api_lightweightmap.h"
42 #include "ecmascript/js_api/js_api_lightweightset.h"
43 #include "ecmascript/frames.h"
44 
45 namespace panda::ecmascript::tooling {
46 using panda::ecmascript::base::ALLOW_BINARY;
47 using panda::ecmascript::base::ALLOW_HEX;
48 using panda::ecmascript::base::ALLOW_OCTAL;
49 using panda::ecmascript::base::NumberHelper;
50 using ecmascript::JSAPIArrayList;
51 using ecmascript::JSAPIDeque;
52 using ecmascript::JSAPIHashMap;
53 using ecmascript::JSAPIHashSet;
54 using ecmascript::JSAPILightWeightMap;
55 using ecmascript::JSAPILightWeightSet;
56 using ecmascript::JSAPIList;
57 using ecmascript::JSAPILinkedList;
58 using ecmascript::JSAPIPlainArray;
59 using ecmascript::JSAPIStack;
60 using ecmascript::JSAPIQueue;
61 using ecmascript::JSAPITreeSet;
62 using ecmascript::JSAPITreeMap;
63 using ecmascript::JSAPIVector;
64 using ecmascript::LinkedNode;
65 using ecmascript::TaggedHashArray;
66 using ecmascript::TaggedNode;
67 using ecmascript::RBTreeNode;
68 using ecmascript::TaggedTreeSet;
69 using ecmascript::TaggedTreeMap;
70 using ecmascript::TaggedQueue;
71 
72 // FrameHandler
GetStackDepth(const EcmaVM * ecmaVm)73 uint32_t DebuggerApi::GetStackDepth(const EcmaVM *ecmaVm)
74 {
75     uint32_t count = 0;
76     FrameHandler frameHandler(ecmaVm->GetJSThread());
77     for (; frameHandler.HasFrame(); frameHandler.PrevJSFrame()) {
78         if (frameHandler.IsEntryFrame() || frameHandler.IsBuiltinFrame()) {
79             continue;
80         }
81         ++count;
82     }
83     return count;
84 }
85 
NewFrameHandler(const EcmaVM * ecmaVm)86 std::shared_ptr<FrameHandler> DebuggerApi::NewFrameHandler(const EcmaVM *ecmaVm)
87 {
88     return std::make_shared<FrameHandler>(ecmaVm->GetJSThread());
89 }
90 
StackWalker(const EcmaVM * ecmaVm,std::function<StackState (const FrameHandler *)> func)91 bool DebuggerApi::StackWalker(const EcmaVM *ecmaVm, std::function<StackState(const FrameHandler *)> func)
92 {
93     FrameHandler frameHandler(ecmaVm->GetJSThread());
94     for (; frameHandler.HasFrame(); frameHandler.PrevJSFrame()) {
95         if (frameHandler.IsEntryFrame() || frameHandler.IsBuiltinFrame()) {
96             continue;
97         }
98         StackState state = func(&frameHandler);
99         if (state == StackState::CONTINUE) {
100             continue;
101         }
102         if (state == StackState::FAILED) {
103             return false;
104         }
105         return true;
106     }
107     return true;
108 }
109 
GetBytecodeOffset(const EcmaVM * ecmaVm)110 uint32_t DebuggerApi::GetBytecodeOffset(const EcmaVM *ecmaVm)
111 {
112     return FrameHandler(ecmaVm->GetJSThread()).GetBytecodeOffset();
113 }
114 
GetMethod(const EcmaVM * ecmaVm)115 std::unique_ptr<PtMethod> DebuggerApi::GetMethod(const EcmaVM *ecmaVm)
116 {
117     FrameHandler frameHandler(ecmaVm->GetJSThread());
118     Method* method = frameHandler.GetMethod();
119     std::unique_ptr<PtMethod> ptMethod = std::make_unique<PtMethod>(
120         method->GetJSPandaFile(), method->GetMethodId(), method->IsNativeWithCallField());
121     return ptMethod;
122 }
123 
SetVRegValue(FrameHandler * frameHandler,size_t index,Local<JSValueRef> value)124 void DebuggerApi::SetVRegValue(FrameHandler *frameHandler, size_t index, Local<JSValueRef> value)
125 {
126     return frameHandler->SetVRegValue(index, JSNApiHelper::ToJSTaggedValue(*value));
127 }
128 
GetBytecodeOffset(const FrameHandler * frameHandler)129 uint32_t DebuggerApi::GetBytecodeOffset(const FrameHandler *frameHandler)
130 {
131     return frameHandler->GetBytecodeOffset();
132 }
133 
GetMethod(const FrameHandler * frameHandler)134 Method *DebuggerApi::GetMethod(const FrameHandler *frameHandler)
135 {
136     return frameHandler->GetMethod();
137 }
138 
IsNativeMethod(const EcmaVM * ecmaVm)139 bool DebuggerApi::IsNativeMethod(const EcmaVM *ecmaVm)
140 {
141     FrameHandler frameHandler(ecmaVm->GetJSThread());
142     return DebuggerApi::IsNativeMethod(&frameHandler);
143 }
144 
IsNativeMethod(const FrameHandler * frameHandler)145 bool DebuggerApi::IsNativeMethod(const FrameHandler *frameHandler)
146 {
147     if (!frameHandler->HasFrame()) {
148         return false;
149     }
150     Method* method = frameHandler->GetMethod();
151     return method->IsNativeWithCallField();
152 }
153 
GetJSPandaFile(const EcmaVM * ecmaVm)154 JSPandaFile *DebuggerApi::GetJSPandaFile(const EcmaVM *ecmaVm)
155 {
156     Method *method = FrameHandler(ecmaVm->GetJSThread()).GetMethod();
157     return const_cast<JSPandaFile *>(method->GetJSPandaFile());
158 }
159 
GetEnv(const FrameHandler * frameHandler)160 JSTaggedValue DebuggerApi::GetEnv(const FrameHandler *frameHandler)
161 {
162     return frameHandler->GetEnv();
163 }
164 
GetSp(const FrameHandler * frameHandler)165 JSTaggedType *DebuggerApi::GetSp(const FrameHandler *frameHandler)
166 {
167     return frameHandler->GetSp();
168 }
169 
GetVregIndex(const FrameHandler * frameHandler,std::string_view name)170 int32_t DebuggerApi::GetVregIndex(const FrameHandler *frameHandler, std::string_view name)
171 {
172     Method *method = DebuggerApi::GetMethod(frameHandler);
173     if (method->IsNativeWithCallField()) {
174         LOG_DEBUGGER(ERROR) << "GetVregIndex: native frame not support";
175         return -1;
176     }
177     DebugInfoExtractor *extractor = JSPandaFileManager::GetInstance()->GetJSPtExtractor(method->GetJSPandaFile());
178     if (extractor == nullptr) {
179         LOG_DEBUGGER(ERROR) << "GetVregIndex: extractor is null";
180         return -1;
181     }
182     auto table = extractor->GetLocalVariableTable(method->GetMethodId());
183     for (auto iter = table.begin(); iter != table.end(); iter++) {
184         if (iter->name == name.data()) {
185             return iter->regNumber;
186         }
187     }
188     return -1;
189 }
190 
GetVRegValue(const EcmaVM * ecmaVm,const FrameHandler * frameHandler,size_t index)191 Local<JSValueRef> DebuggerApi::GetVRegValue(const EcmaVM *ecmaVm,
192     const FrameHandler *frameHandler, size_t index)
193 {
194     auto value = frameHandler->GetVRegValue(index);
195     JSHandle<JSTaggedValue> handledValue(ecmaVm->GetJSThread(), value);
196     return JSNApiHelper::ToLocal<JSValueRef>(handledValue);
197 }
198 
199 // JSThread
GetAndClearException(const EcmaVM * ecmaVm)200 Local<JSValueRef> DebuggerApi::GetAndClearException(const EcmaVM *ecmaVm)
201 {
202     auto exception = ecmaVm->GetJSThread()->GetException();
203     JSHandle<JSTaggedValue> handledException(ecmaVm->GetJSThread(), exception);
204     ecmaVm->GetJSThread()->ClearException();
205     return JSNApiHelper::ToLocal<JSValueRef>(handledException);
206 }
207 
SetException(const EcmaVM * ecmaVm,Local<JSValueRef> exception)208 void DebuggerApi::SetException(const EcmaVM *ecmaVm, Local<JSValueRef> exception)
209 {
210     ecmaVm->GetJSThread()->SetException(JSNApiHelper::ToJSTaggedValue(*exception));
211 }
212 
ClearException(const EcmaVM * ecmaVm)213 void DebuggerApi::ClearException(const EcmaVM *ecmaVm)
214 {
215     return ecmaVm->GetJSThread()->ClearException();
216 }
217 
218 // NumberHelper
StringToDouble(const uint8_t * start,const uint8_t * end,uint8_t radix)219 double DebuggerApi::StringToDouble(const uint8_t *start, const uint8_t *end, uint8_t radix)
220 {
221     return NumberHelper::StringToDouble(start, end, radix, ALLOW_BINARY | ALLOW_HEX | ALLOW_OCTAL);
222 }
223 
224 // JSDebugger
CreateJSDebugger(const EcmaVM * ecmaVm)225 JSDebugger *DebuggerApi::CreateJSDebugger(const EcmaVM *ecmaVm)
226 {
227     return new JSDebugger(ecmaVm);
228 }
229 
DestroyJSDebugger(JSDebugger * debugger)230 void DebuggerApi::DestroyJSDebugger(JSDebugger *debugger)
231 {
232     delete debugger;
233 }
234 
RegisterHooks(JSDebugger * debugger,PtHooks * hooks)235 void DebuggerApi::RegisterHooks(JSDebugger *debugger, PtHooks *hooks)
236 {
237     debugger->RegisterHooks(hooks);
238 }
239 
SetBreakpoint(JSDebugger * debugger,const JSPtLocation & location,Local<FunctionRef> condFuncRef)240 bool DebuggerApi::SetBreakpoint(JSDebugger *debugger, const JSPtLocation &location,
241     Local<FunctionRef> condFuncRef)
242 {
243     return debugger->SetBreakpoint(location, condFuncRef);
244 }
245 
RemoveBreakpoint(JSDebugger * debugger,const JSPtLocation & location)246 bool DebuggerApi::RemoveBreakpoint(JSDebugger *debugger, const JSPtLocation &location)
247 {
248     return debugger->RemoveBreakpoint(location);
249 }
250 
RemoveAllBreakpoints(JSDebugger * debugger)251 void DebuggerApi::RemoveAllBreakpoints(JSDebugger *debugger)
252 {
253     return debugger->RemoveAllBreakpoints();
254 }
255 
256 // ScopeInfo
GetProperties(const EcmaVM * ecmaVm,const FrameHandler * frameHandler,int32_t level,uint32_t slot)257 Local<JSValueRef> DebuggerApi::GetProperties(const EcmaVM *ecmaVm, const FrameHandler *frameHandler,
258                                              int32_t level, uint32_t slot)
259 {
260     JSTaggedValue env = frameHandler->GetEnv();
261     for (int i = 0; i < level; i++) {
262         JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv();
263         ASSERT(!taggedParentEnv.IsUndefined());
264         env = taggedParentEnv;
265     }
266     JSTaggedValue value = LexicalEnv::Cast(env.GetTaggedObject())->GetProperties(slot);
267     JSHandle<JSTaggedValue> handledValue(ecmaVm->GetJSThread(), value);
268     return JSNApiHelper::ToLocal<JSValueRef>(handledValue);
269 }
270 
SetProperties(const EcmaVM * ecmaVm,const FrameHandler * frameHandler,int32_t level,uint32_t slot,Local<JSValueRef> value)271 void DebuggerApi::SetProperties(const EcmaVM *ecmaVm, const FrameHandler *frameHandler,
272                                 int32_t level, uint32_t slot, Local<JSValueRef> value)
273 {
274     JSTaggedValue env = frameHandler->GetEnv();
275     for (int i = 0; i < level; i++) {
276         JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv();
277         ASSERT(!taggedParentEnv.IsUndefined());
278         env = taggedParentEnv;
279     }
280     JSTaggedValue target = JSNApiHelper::ToJSHandle(value).GetTaggedValue();
281     LexicalEnv::Cast(env.GetTaggedObject())->SetProperties(ecmaVm->GetJSThread(), slot, target);
282 }
283 
GetLevelSlot(const FrameHandler * frameHandler,std::string_view name)284 std::pair<int32_t, uint32_t> DebuggerApi::GetLevelSlot(const FrameHandler *frameHandler, std::string_view name)
285 {
286     int32_t level = 0;
287     uint32_t slot = 0;
288     JSTaggedValue curEnv = frameHandler->GetEnv();
289     for (; curEnv.IsTaggedArray(); curEnv = LexicalEnv::Cast(curEnv.GetTaggedObject())->GetParentEnv(), level++) {
290         LexicalEnv *lexicalEnv = LexicalEnv::Cast(curEnv.GetTaggedObject());
291         if (lexicalEnv->GetScopeInfo().IsHole()) {
292             continue;
293         }
294         auto result = JSNativePointer::Cast(lexicalEnv->GetScopeInfo().GetTaggedObject())->GetExternalPointer();
295         ScopeDebugInfo *scopeDebugInfo = reinterpret_cast<ScopeDebugInfo *>(result);
296         auto iter = scopeDebugInfo->scopeInfo.find(name.data());
297         if (iter == scopeDebugInfo->scopeInfo.end()) {
298             continue;
299         }
300         slot = iter->second;
301         return std::make_pair(level, slot);
302     }
303     return std::make_pair(-1, 0);
304 }
305 
GetGlobalValue(const EcmaVM * ecmaVm,Local<StringRef> name)306 Local<JSValueRef> DebuggerApi::GetGlobalValue(const EcmaVM *ecmaVm, Local<StringRef> name)
307 {
308     JSTaggedValue result;
309     JSTaggedValue globalObj = ecmaVm->GetGlobalEnv()->GetGlobalObject();
310     JSThread *thread = ecmaVm->GetJSThread();
311 
312     JSTaggedValue key = JSNApiHelper::ToJSTaggedValue(*name);
313     JSTaggedValue globalRec = SlowRuntimeStub::LdGlobalRecord(thread, key);
314     if (!globalRec.IsUndefined()) {
315         ASSERT(globalRec.IsPropertyBox());
316         result = PropertyBox::Cast(globalRec.GetTaggedObject())->GetValue();
317         return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, result));
318     }
319 
320     JSTaggedValue globalVar = FastRuntimeStub::GetGlobalOwnProperty(thread, globalObj, key);
321     if (!globalVar.IsHole()) {
322         return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, globalVar));
323     } else {
324         result = SlowRuntimeStub::TryLdGlobalByNameFromGlobalProto(thread, globalObj, key);
325         return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, result));
326     }
327 
328     return Local<JSValueRef>();
329 }
330 
SetGlobalValue(const EcmaVM * ecmaVm,Local<StringRef> name,Local<JSValueRef> value)331 bool DebuggerApi::SetGlobalValue(const EcmaVM *ecmaVm, Local<StringRef> name, Local<JSValueRef> value)
332 {
333     JSTaggedValue result;
334     JSTaggedValue globalObj = ecmaVm->GetGlobalEnv()->GetGlobalObject();
335     JSThread *thread = ecmaVm->GetJSThread();
336 
337     JSTaggedValue key = JSNApiHelper::ToJSTaggedValue(*name);
338     JSTaggedValue newVal = JSNApiHelper::ToJSTaggedValue(*value);
339     JSTaggedValue globalRec = SlowRuntimeStub::LdGlobalRecord(thread, key);
340     if (!globalRec.IsUndefined()) {
341         result = SlowRuntimeStub::TryUpdateGlobalRecord(thread, key, newVal);
342         return !result.IsException();
343     }
344 
345     JSTaggedValue globalVar = FastRuntimeStub::GetGlobalOwnProperty(thread, globalObj, key);
346     if (!globalVar.IsHole()) {
347         result = SlowRuntimeStub::StGlobalVar(thread, key, newVal);
348         return !result.IsException();
349     }
350 
351     return false;
352 }
353 
GetCurrentModule(const EcmaVM * ecmaVm)354 JSTaggedValue DebuggerApi::GetCurrentModule(const EcmaVM *ecmaVm)
355 {
356     JSThread *thread = ecmaVm->GetJSThread();
357     FrameHandler frameHandler(thread);
358     for (; frameHandler.HasFrame(); frameHandler.PrevJSFrame()) {
359         if (frameHandler.IsEntryFrame()) {
360             continue;
361         }
362         Method *method = frameHandler.GetMethod();
363         // Skip builtins method
364         if (method->IsNativeWithCallField()) {
365             continue;
366         }
367         JSTaggedValue func = frameHandler.GetFunction();
368         JSTaggedValue module = JSFunction::Cast(func.GetTaggedObject())->GetModule();
369         if (module.IsUndefined()) {
370             continue;
371         }
372         return module;
373     }
374     UNREACHABLE();
375 }
376 
GetImportModule(const EcmaVM * ecmaVm,const JSHandle<JSTaggedValue> & currentModule,std::string & name)377 JSHandle<JSTaggedValue> DebuggerApi::GetImportModule(const EcmaVM *ecmaVm,
378                                                      const JSHandle<JSTaggedValue> &currentModule, std::string &name)
379 {
380     JSThread *thread = ecmaVm->GetJSThread();
381     JSMutableHandle<JSTaggedValue> importModule(thread, thread->GlobalConstants()->GetUndefined());
382     if (!currentModule->IsSourceTextModule()) {
383         return importModule;
384     }
385 
386     JSTaggedValue importEntries = SourceTextModule::Cast(currentModule->GetTaggedObject())->GetImportEntries();
387     if (importEntries.IsUndefined()) {
388         return importModule;
389     }
390 
391     JSHandle<TaggedArray> importArray(thread, TaggedArray::Cast(importEntries.GetTaggedObject()));
392     size_t importEntriesLen = importArray->GetLength();
393     JSHandle<JSTaggedValue> starString = thread->GlobalConstants()->GetHandledStarString();
394     JSMutableHandle<ImportEntry> ee(thread, thread->GlobalConstants()->GetUndefined());
395     JSMutableHandle<TaggedArray> environment(thread, thread->GlobalConstants()->GetUndefined());
396     for (size_t idx = 0; idx < importEntriesLen; idx++) {
397         ee.Update(importArray->Get(idx));
398         JSTaggedValue localName = ee->GetLocalName();
399         JSTaggedValue importName = ee->GetImportName();
400         // Skip 'import * as name from xxx'
401         if (localName.IsString() && !JSTaggedValue::SameValue(importName, starString.GetTaggedValue())) {
402             std::string varName = EcmaStringAccessor(localName).ToStdString();
403             if (varName != name) {
404                 continue;
405             }
406             JSTaggedValue moduleEnvironment = SourceTextModule::Cast(
407                 currentModule->GetTaggedObject())->GetEnvironment();
408             environment.Update(moduleEnvironment);
409             JSTaggedValue resolvedBinding = environment->Get(idx);
410             ResolvedIndexBinding *binding = ResolvedIndexBinding::Cast(resolvedBinding.GetTaggedObject());
411             importModule.Update(binding->GetModule());
412             name = EcmaStringAccessor(importName).ToStdString();
413             return importModule;
414         }
415     }
416     return importModule;
417 }
418 
GetModuleVariableIndex(const EcmaVM * ecmaVm,const JSHandle<JSTaggedValue> & currentModule,std::string & name)419 int32_t DebuggerApi::GetModuleVariableIndex(const EcmaVM *ecmaVm, const JSHandle<JSTaggedValue> &currentModule,
420                                             std::string &name)
421 {
422     if (!currentModule->IsSourceTextModule()) {
423         return -1;
424     }
425     JSTaggedValue dictionary = SourceTextModule::Cast(currentModule->GetTaggedObject())->GetNameDictionary();
426     if (dictionary.IsUndefined()) {
427         return -1;
428     }
429 
430     JSThread *thread = ecmaVm->GetJSThread();
431     if (dictionary.IsTaggedArray()) {
432         JSTaggedValue localExportEntries = SourceTextModule::Cast(
433             currentModule->GetTaggedObject())->GetLocalExportEntries();
434         ASSERT(localExportEntries.IsTaggedArray());
435         JSHandle<TaggedArray> localExportArray(thread, TaggedArray::Cast(localExportEntries.GetTaggedObject()));
436         uint32_t exportEntriesLen = localExportArray->GetLength();
437         JSMutableHandle<LocalExportEntry> ee(thread, thread->GlobalConstants()->GetUndefined());
438         for (uint32_t idx = 0; idx < exportEntriesLen; idx++) {
439             ee.Update(localExportArray->Get(idx));
440             JSTaggedValue localKey = ee->GetLocalName();
441             JSTaggedValue exportKey = ee->GetExportName();
442             if (localKey.IsString() && exportKey.IsString()) {
443                 std::string localName = EcmaStringAccessor(localKey).ToStdString();
444                 std::string exportName = EcmaStringAccessor(exportKey).ToStdString();
445                 if (localName == name || exportName == name) {
446                     return idx;
447                 }
448             }
449         }
450     }
451     return -1;
452 }
453 
GetRequestModuleIndex(const EcmaVM * ecmaVm,JSTaggedValue moduleRequest,const JSHandle<JSTaggedValue> & currentModule)454 int32_t DebuggerApi::GetRequestModuleIndex(const EcmaVM *ecmaVm, JSTaggedValue moduleRequest,
455                                            const JSHandle<JSTaggedValue> &currentModule)
456 {
457     if (!currentModule->IsSourceTextModule()) {
458         return -1;
459     }
460     JSThread *thread = ecmaVm->GetJSThread();
461     JSHandle<SourceTextModule> module(thread, SourceTextModule::Cast(currentModule->GetTaggedObject()));
462     JSHandle<JSTaggedValue> required(thread, moduleRequest);
463     JSHandle<TaggedArray> requestedModules(thread, module->GetRequestedModules());
464     uint32_t requestedModulesLen = requestedModules->GetLength();
465     for (uint32_t idx = 0; idx < requestedModulesLen; idx++) {
466         JSTaggedValue requestModule = requestedModules->Get(idx);
467         if (JSTaggedValue::SameValue(required.GetTaggedValue(), requestModule)) {
468             return idx;
469         }
470     }
471     LOG_ECMA(FATAL) << "this branch is unreachable";
472     return -1;
473 }
474 
GetExportVariableValue(const EcmaVM * ecmaVm,const JSHandle<JSTaggedValue> & currentModule,std::string & name)475 Local<JSValueRef> DebuggerApi::GetExportVariableValue(const EcmaVM *ecmaVm,
476                                                       const JSHandle<JSTaggedValue> &currentModule, std::string &name)
477 {
478     Local<JSValueRef> result;
479     if (!currentModule->IsSourceTextModule()) {
480         return result;
481     }
482     int32_t index = GetModuleVariableIndex(ecmaVm, currentModule, name);
483     if (index == -1) {
484         return result;
485     }
486 
487     JSTaggedValue dictionary = SourceTextModule::Cast(currentModule->GetTaggedObject())->GetNameDictionary();
488     if (dictionary.IsUndefined()) {
489         return result;
490     }
491 
492     JSThread *thread = ecmaVm->GetJSThread();
493     if (dictionary.IsTaggedArray()) {
494         TaggedArray *array = TaggedArray::Cast(dictionary.GetTaggedObject());
495         JSTaggedValue moduleValue = array->Get(index);
496         result = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, moduleValue));
497         return result;
498     }
499     return result;
500 }
501 
SetExportVariableValue(const EcmaVM * ecmaVm,const JSHandle<JSTaggedValue> & currentModule,std::string & name,Local<JSValueRef> value)502 bool DebuggerApi::SetExportVariableValue(const EcmaVM *ecmaVm, const JSHandle<JSTaggedValue> &currentModule,
503                                          std::string &name, Local<JSValueRef> value)
504 {
505     if (!currentModule->IsSourceTextModule()) {
506         return false;
507     }
508     int32_t index = GetModuleVariableIndex(ecmaVm, currentModule, name);
509     if (index == -1) {
510         return false;
511     }
512 
513     JSTaggedValue dictionary = SourceTextModule::Cast(currentModule->GetTaggedObject())->GetNameDictionary();
514     if (dictionary.IsUndefined()) {
515         return false;
516     }
517 
518     JSThread *thread = ecmaVm->GetJSThread();
519     JSTaggedValue curValue = JSNApiHelper::ToJSTaggedValue(*value);
520     if (dictionary.IsTaggedArray()) {
521         TaggedArray *array = TaggedArray::Cast(dictionary.GetTaggedObject());
522         array->Set(thread, index, curValue);
523         return true;
524     }
525     return false;
526 }
527 
GetModuleValue(const EcmaVM * ecmaVm,const JSHandle<JSTaggedValue> & currentModule,std::string & name)528 Local<JSValueRef> DebuggerApi::GetModuleValue(const EcmaVM *ecmaVm, const JSHandle<JSTaggedValue> &currentModule,
529                                               std::string &name)
530 {
531     Local<JSValueRef> result;
532     if (!currentModule->IsSourceTextModule()) {
533         return result;
534     }
535     // Get variable from local export
536     result = GetExportVariableValue(ecmaVm, currentModule, name);
537     if (!result.IsEmpty()) {
538         return result;
539     }
540     // Get variable from import module
541     JSHandle<JSTaggedValue> importModule = GetImportModule(ecmaVm, currentModule, name);
542     result = GetExportVariableValue(ecmaVm, importModule, name);
543     return result;
544 }
545 
SetModuleValue(const EcmaVM * ecmaVm,const JSHandle<JSTaggedValue> & currentModule,std::string & name,Local<JSValueRef> value)546 bool DebuggerApi::SetModuleValue(const EcmaVM *ecmaVm, const JSHandle<JSTaggedValue> &currentModule,
547                                  std::string &name, Local<JSValueRef> value)
548 {
549     bool result;
550     if (!currentModule->IsSourceTextModule()) {
551         return false;
552     }
553     // Set local export variable
554     result = SetExportVariableValue(ecmaVm, currentModule, name, value);
555     if (result == true) {
556         return result;
557     }
558     // Set import module variable
559     JSHandle<JSTaggedValue> importModule = GetImportModule(ecmaVm, currentModule, name);
560     result = SetExportVariableValue(ecmaVm, importModule, name, value);
561     if (result == true) {
562         return result;
563     }
564     return false;
565 }
566 
InitializeExportVariables(const EcmaVM * ecmaVm,Local<ObjectRef> & moduleObj,const JSHandle<JSTaggedValue> & currentModule)567 void DebuggerApi::InitializeExportVariables(const EcmaVM *ecmaVm, Local<ObjectRef> &moduleObj,
568                                             const JSHandle<JSTaggedValue> &currentModule)
569 {
570     if (!currentModule->IsSourceTextModule()) {
571         return;
572     }
573     JSTaggedValue localExportEntries = SourceTextModule::Cast(
574         currentModule->GetTaggedObject())->GetLocalExportEntries();
575     if (localExportEntries.IsUndefined()) {
576         return;
577     }
578 
579     JSThread *thread = ecmaVm->GetJSThread();
580     JSHandle<TaggedArray> localExportArray(thread, TaggedArray::Cast(localExportEntries.GetTaggedObject()));
581     uint32_t exportEntriesLen = localExportArray->GetLength();
582     JSMutableHandle<LocalExportEntry> ee(thread, thread->GlobalConstants()->GetUndefined());
583     JSMutableHandle<JSTaggedValue> name(thread, thread->GlobalConstants()->GetUndefined());
584     JSMutableHandle<JSTaggedValue> value(thread, thread->GlobalConstants()->GetUndefined());
585     JSTaggedValue moduleValue = JSTaggedValue::Undefined();
586     for (uint32_t idx = 0; idx < exportEntriesLen; idx++) {
587         ee.Update(localExportArray->Get(idx));
588         JSTaggedValue key = ee->GetLocalName();
589         name.Update(key);
590         value.Update(moduleValue);
591         if (key.IsString()) {
592             Local<JSValueRef> variableName = JSNApiHelper::ToLocal<JSValueRef>(name);
593             Local<JSValueRef> variableValue = JSNApiHelper::ToLocal<JSValueRef>(value);
594             PropertyAttribute descriptor(variableValue, true, true, true);
595             moduleObj->DefineProperty(ecmaVm, variableName, descriptor);
596         }
597     }
598 }
599 
GetLocalExportVariables(const EcmaVM * ecmaVm,Local<ObjectRef> & moduleObj,const JSHandle<JSTaggedValue> & currentModule,bool isImportStar)600 void DebuggerApi::GetLocalExportVariables(const EcmaVM *ecmaVm, Local<ObjectRef> &moduleObj,
601                                           const JSHandle<JSTaggedValue> &currentModule, bool isImportStar)
602 {
603     if (!currentModule->IsSourceTextModule()) {
604         return;
605     }
606     JSTaggedValue dictionary = SourceTextModule::Cast(currentModule->GetTaggedObject())->GetNameDictionary();
607     if (dictionary.IsUndefined()) {
608         InitializeExportVariables(ecmaVm, moduleObj, currentModule);
609         return;
610     }
611 
612     JSThread *thread = ecmaVm->GetJSThread();
613     JSMutableHandle<JSTaggedValue> name(thread, thread->GlobalConstants()->GetUndefined());
614     JSMutableHandle<JSTaggedValue> value(thread, thread->GlobalConstants()->GetUndefined());
615     if (dictionary.IsTaggedArray()) {
616         JSTaggedValue localExportEntries = SourceTextModule::Cast(
617             currentModule->GetTaggedObject())->GetLocalExportEntries();
618         ASSERT(localExportEntries.IsTaggedArray());
619         JSHandle<TaggedArray> localExportArray(thread, TaggedArray::Cast(localExportEntries.GetTaggedObject()));
620         uint32_t exportEntriesLen = localExportArray->GetLength();
621         JSHandle<TaggedArray> dict(thread, TaggedArray::Cast(dictionary.GetTaggedObject()));
622         uint32_t valueLen = dict->GetLength();
623         if (exportEntriesLen != valueLen) {
624             LOG_FULL(FATAL) << "Key does not match value";
625         }
626 
627         JSMutableHandle<LocalExportEntry> ee(thread, thread->GlobalConstants()->GetUndefined());
628         for (uint32_t idx = 0; idx < exportEntriesLen; idx++) {
629             ee.Update(localExportArray->Get(idx));
630             JSTaggedValue key;
631             if (isImportStar) {
632                 key = ee->GetExportName();
633             } else {
634                 key = ee->GetLocalName();
635             }
636             name.Update(key);
637             JSTaggedValue moduleValue = dict->Get(idx);
638             if (moduleValue.IsHole()) {
639                 moduleValue = JSTaggedValue::Undefined();
640             }
641             value.Update(moduleValue);
642             if (key.IsString()) {
643                 Local<JSValueRef> variableName = JSNApiHelper::ToLocal<JSValueRef>(name);
644                 Local<JSValueRef> variableValue = JSNApiHelper::ToLocal<JSValueRef>(value);
645                 PropertyAttribute descriptor(variableValue, true, true, true);
646                 moduleObj->DefineProperty(ecmaVm, variableName, descriptor);
647             }
648         }
649     }
650 }
651 
GetIndirectExportVariables(const EcmaVM * ecmaVm,Local<ObjectRef> & moduleObj,const JSHandle<JSTaggedValue> & currentModule)652 void DebuggerApi::GetIndirectExportVariables(const EcmaVM *ecmaVm, Local<ObjectRef> &moduleObj,
653                                              const JSHandle<JSTaggedValue> &currentModule)
654 {
655     if (!currentModule->IsSourceTextModule()) {
656         return;
657     }
658     JSTaggedValue indirectExportEntries = SourceTextModule::Cast(
659         currentModule->GetTaggedObject())->GetIndirectExportEntries();
660     if (indirectExportEntries.IsUndefined()) {
661         return;
662     }
663     ASSERT(indirectExportEntries.IsTaggedArray());
664     JSThread *thread = ecmaVm->GetJSThread();
665     JSHandle<TaggedArray> indirectExportArray(thread, TaggedArray::Cast(indirectExportEntries.GetTaggedObject()));
666     uint32_t indirectExportEntriesLen = indirectExportArray->GetLength();
667     JSMutableHandle<IndirectExportEntry> ee(thread, thread->GlobalConstants()->GetUndefined());
668     JSMutableHandle<JSTaggedValue> name(thread, thread->GlobalConstants()->GetUndefined());
669     for (uint32_t idx = 0; idx < indirectExportEntriesLen; idx++) {
670         ee.Update(indirectExportArray->Get(idx));
671         JSTaggedValue key = ee->GetImportName();
672         name.Update(key);
673         if (key.IsString()) {
674             Local<JSValueRef> variableName = JSNApiHelper::ToLocal<JSValueRef>(name);
675             JSHandle<JSTaggedValue> moduleRequest(thread, ee->GetModuleRequest());
676             JSHandle<JSTaggedValue> importModule;
677             JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(currentModule);
678             JSTaggedValue moduleRecordName = module->GetEcmaModuleRecordName();
679             if (moduleRecordName.IsUndefined()) {
680                 importModule = SourceTextModule::HostResolveImportedModule(thread, module, moduleRequest);
681             } else {
682                 importModule = SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, moduleRequest);
683             }
684             std::string importName = EcmaStringAccessor(ee->GetImportName()).ToStdString();
685             Local<JSValueRef> value = GetModuleValue(ecmaVm, importModule, importName);
686             PropertyAttribute descriptor(value, true, true, true);
687             moduleObj->DefineProperty(ecmaVm, variableName, descriptor);
688         }
689     }
690 }
691 
GetImportVariables(const EcmaVM * ecmaVm,Local<ObjectRef> & moduleObj,const JSHandle<JSTaggedValue> & currentModule)692 void DebuggerApi::GetImportVariables(const EcmaVM *ecmaVm, Local<ObjectRef> &moduleObj,
693                                      const JSHandle<JSTaggedValue> &currentModule)
694 {
695     if (!currentModule->IsSourceTextModule()) {
696         return;
697     }
698     JSTaggedValue importEntries = SourceTextModule::Cast(currentModule->GetTaggedObject())->GetImportEntries();
699     if (importEntries.IsUndefined()) {
700         return;
701     }
702 
703     JSThread *thread = ecmaVm->GetJSThread();
704     JSHandle<TaggedArray> importArray(thread, TaggedArray::Cast(importEntries.GetTaggedObject()));
705     uint32_t importEntriesLen = importArray->GetLength();
706     JSHandle<JSTaggedValue> starString = thread->GlobalConstants()->GetHandledStarString();
707     JSMutableHandle<ImportEntry> ee(thread, thread->GlobalConstants()->GetUndefined());
708     JSMutableHandle<JSTaggedValue> name(thread, thread->GlobalConstants()->GetUndefined());
709     for (uint32_t idx = 0; idx < importEntriesLen; idx++) {
710         ee.Update(importArray->Get(idx));
711         JSTaggedValue key = ee->GetImportName();
712         JSTaggedValue localName = ee->GetLocalName();
713         name.Update(localName);
714         if (JSTaggedValue::SameValue(key, starString.GetTaggedValue())) {
715             JSHandle<JSTaggedValue> moduleRequest(thread, ee->GetModuleRequest());
716             JSHandle<JSTaggedValue> importModule;
717             JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(currentModule);
718             JSTaggedValue moduleRecordName = module->GetEcmaModuleRecordName();
719             if (moduleRecordName.IsUndefined()) {
720                 importModule = SourceTextModule::HostResolveImportedModule(thread, module, moduleRequest);
721             } else {
722                 importModule = SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, moduleRequest);
723             }
724             Local<ObjectRef> importModuleObj = ObjectRef::New(ecmaVm);
725             GetLocalExportVariables(ecmaVm, importModuleObj, importModule, true);
726             Local<JSValueRef> variableName = JSNApiHelper::ToLocal<JSValueRef>(name);
727             PropertyAttribute descriptor(static_cast<Local<JSValueRef>>(importModuleObj), true, true, true);
728             moduleObj->DefineProperty(ecmaVm, variableName, descriptor);
729             continue;
730         }
731         JSTaggedValue moduleValue =
732             thread->GetCurrentEcmaContext()->GetModuleManager()->GetModuleValueOutter(idx, currentModule);
733         Local<JSValueRef> value = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, moduleValue));
734         Local<JSValueRef> variableName = JSNApiHelper::ToLocal<JSValueRef>(name);
735         PropertyAttribute descriptor(value, true, true, true);
736         moduleObj->DefineProperty(ecmaVm, variableName, descriptor);
737     }
738 }
739 
HandleUncaughtException(const EcmaVM * ecmaVm,std::string & message)740 void DebuggerApi::HandleUncaughtException(const EcmaVM *ecmaVm, std::string &message)
741 {
742     JSThread *thread = ecmaVm->GetJSThread();
743     [[maybe_unused]] EcmaHandleScope handleScope(thread);
744     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
745 
746     JSHandle<JSTaggedValue> exHandle(thread, thread->GetException());
747     thread->ClearException();
748     if (exHandle->IsJSError()) {
749         JSHandle<JSTaggedValue> nameKey = globalConst->GetHandledNameString();
750         JSHandle<EcmaString> name(JSObject::GetProperty(thread, exHandle, nameKey).GetValue());
751         JSHandle<JSTaggedValue> msgKey = globalConst->GetHandledMessageString();
752         JSHandle<EcmaString> msg(JSObject::GetProperty(thread, exHandle, msgKey).GetValue());
753         message = ConvertToString(*name) + ": " + ConvertToString(*msg);
754     } else {
755         JSHandle<EcmaString> ecmaStr = JSTaggedValue::ToString(thread, exHandle);
756         message = ConvertToString(*ecmaStr);
757     }
758 }
759 
GenerateFuncFromBuffer(const EcmaVM * ecmaVm,const void * buffer,size_t size,std::string_view entryPoint)760 Local<FunctionRef> DebuggerApi::GenerateFuncFromBuffer(const EcmaVM *ecmaVm, const void *buffer,
761                                                        size_t size, std::string_view entryPoint)
762 {
763     JSPandaFileManager *mgr = JSPandaFileManager::GetInstance();
764     std::shared_ptr<JSPandaFile> jsPandaFile =
765         mgr->LoadJSPandaFile(ecmaVm->GetJSThread(), "", entryPoint, buffer, size);
766     if (jsPandaFile == nullptr) {
767         return JSValueRef::Undefined(ecmaVm);
768     }
769 
770     JSHandle<Program> program = mgr->GenerateProgram(const_cast<EcmaVM *>(ecmaVm), jsPandaFile.get(), entryPoint);
771     JSTaggedValue func = program->GetMainFunction();
772     return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(ecmaVm->GetJSThread(), func));
773 }
774 
EvaluateViaFuncCall(EcmaVM * ecmaVm,Local<FunctionRef> funcRef,std::shared_ptr<FrameHandler> & frameHandler)775 Local<JSValueRef> DebuggerApi::EvaluateViaFuncCall(EcmaVM *ecmaVm, Local<FunctionRef> funcRef,
776     std::shared_ptr<FrameHandler> &frameHandler)
777 {
778     JSNApi::EnableUserUncaughtErrorHandler(ecmaVm);
779 
780     JsDebuggerManager *mgr = ecmaVm->GetJsDebuggerManager();
781     bool prevDebugMode = mgr->IsDebugMode();
782     mgr->SetEvalFrameHandler(frameHandler);
783     mgr->SetDebugMode(false); // in order to catch exception
784     ecmaVm->GetJSThread()->CheckSwitchDebuggerBCStub();
785     std::vector<Local<JSValueRef>> args;
786     auto result = funcRef->Call(ecmaVm, JSValueRef::Undefined(ecmaVm), args.data(), args.size());
787     mgr->SetDebugMode(prevDebugMode);
788     ecmaVm->GetJSThread()->CheckSwitchDebuggerBCStub();
789     mgr->SetEvalFrameHandler(nullptr);
790 
791     return result;
792 }
793 
IsExceptionCaught(const EcmaVM * ecmaVm)794 bool DebuggerApi::IsExceptionCaught(const EcmaVM *ecmaVm)
795 {
796     FrameHandler frameHandler(ecmaVm->GetJSThread());
797     for (; frameHandler.HasFrame(); frameHandler.PrevJSFrame()) {
798         if (frameHandler.IsEntryFrame()) {
799             return false;
800         }
801         auto method = frameHandler.GetMethod();
802         if (method->FindCatchBlock(frameHandler.GetBytecodeOffset() != INVALID_INDEX)) {
803             return true;
804         }
805     }
806     return false;
807 }
808 
GetPatchExtractor(const EcmaVM * ecmaVm,const std::string & url)809 DebugInfoExtractor *DebuggerApi::GetPatchExtractor(const EcmaVM *ecmaVm, const std::string &url)
810 {
811     const auto *hotReloadManager = ecmaVm->GetJsDebuggerManager()->GetHotReloadManager();
812     return hotReloadManager->GetPatchExtractor(url);
813 }
814 
GetBaseJSPandaFile(const EcmaVM * ecmaVm,const JSPandaFile * jsPandaFile)815 const JSPandaFile *DebuggerApi::GetBaseJSPandaFile(const EcmaVM *ecmaVm, const JSPandaFile *jsPandaFile)
816 {
817     const auto *hotReloadManager = ecmaVm->GetJsDebuggerManager()->GetHotReloadManager();
818     return hotReloadManager->GetBaseJSPandaFile(jsPandaFile);
819 }
820 
GetNativePointer(const EcmaVM * ecmaVm)821 std::vector<void *> DebuggerApi::GetNativePointer(const EcmaVM *ecmaVm)
822 {
823     void *native = nullptr;
824     std::vector<void *> nativePointer;
825     JSThread *thread = ecmaVm->GetJSThread();
826     JSTaggedType *current = const_cast<JSTaggedType *>(thread->GetCurrentFrame());
827     FrameIterator it(current, thread);
828     for (; !it.Done(); it.Advance<GCVisitedFlag::HYBRID_STACK>()) {
829         if (!it.IsJSFrame()) {
830             continue;
831         }
832         auto method = it.CheckAndGetMethod();
833         if (method == nullptr) {
834             continue;
835         }
836 
837         if (method->IsNativeWithCallField()) {
838             JSTaggedValue function = it.GetFunction();
839             JSHandle<JSTaggedValue> extraInfoValue(
840                 thread, JSFunction::Cast(function.GetTaggedObject())->GetFunctionExtraInfo());
841             auto cb = ecmaVm->GetNativePtrGetter();
842             if (extraInfoValue->IsJSNativePointer() && cb != nullptr) {
843                 JSHandle<JSNativePointer> extraInfo(extraInfoValue);
844                 native = cb(reinterpret_cast<void *>(extraInfo->GetData()));
845                 nativePointer.push_back(native);
846             }
847         } else {
848             nativePointer.push_back(nullptr); // to tell IDE this frame don't hava nativePointer
849         }
850     }
851     return nativePointer;
852 }
853 
GetContainerLength(const EcmaVM * ecmaVm,Local<JSValueRef> value)854 uint32_t DebuggerApi::GetContainerLength(const EcmaVM *ecmaVm, Local<JSValueRef> value)
855 {
856     uint32_t length = Local<ArrayRef>(value)->Length(ecmaVm);
857     return length;
858 }
859 
AddInternalProperties(const EcmaVM * ecmaVm,Local<ObjectRef> object,ArkInternalValueType type,Global<MapRef> internalObjects)860 void DebuggerApi::AddInternalProperties(const EcmaVM *ecmaVm, Local<ObjectRef> object,
861                                         ArkInternalValueType type, Global<MapRef> internalObjects)
862 {
863     internalObjects->Set(ecmaVm, object, NumberRef::New(ecmaVm, static_cast<int32_t>(type)));
864 }
865 
GetArrayListValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)866 Local<JSValueRef> DebuggerApi::GetArrayListValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
867                                                  Global<MapRef> internalObjects)
868 {
869     JSHandle<JSAPIArrayList> arrayList(JSNApiHelper::ToJSHandle(value));
870     uint32_t size = static_cast<uint32_t>(arrayList->GetSize());
871     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
872     JSThread *thread = ecmaVm->GetJSThread();
873     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
874     uint32_t index = 0;
875     while (index < size) {
876         currentValue.Update(arrayList->Get(thread, index));
877         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
878     }
879     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
880     return jsValueRef;
881 }
882 
GetDequeValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)883 Local<JSValueRef> DebuggerApi::GetDequeValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
884                                              Global<MapRef> internalObjects)
885 {
886     JSHandle<JSAPIDeque> deque(JSNApiHelper::ToJSHandle(value));
887     uint32_t size = static_cast<uint32_t>(deque->GetSize());
888     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
889     JSThread *thread = ecmaVm->GetJSThread();
890     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
891     uint32_t index = 0;
892     while (index < size) {
893         currentValue.Update(deque->Get(index));
894         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
895     }
896     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
897     return jsValueRef;
898 }
899 
GetHashMapValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)900 Local<JSValueRef> DebuggerApi::GetHashMapValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
901                                                Global<MapRef> internalObjects)
902 {
903     JSHandle<JSAPIHashMap> hashMap(JSNApiHelper::ToJSHandle(value));
904     JSThread *thread = ecmaVm->GetJSThread();
905     JSHandle<TaggedHashArray> table(thread, hashMap->GetTable());
906     uint32_t length = table->GetLength();
907     uint32_t size = static_cast<uint32_t>(hashMap->GetSize());
908     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
909     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
910     JSMutableHandle<TaggedQueue> queue(thread, factory->NewTaggedQueue(0));
911     JSMutableHandle<TaggedNode> node(thread, JSTaggedValue::Undefined());
912     JSMutableHandle<JSTaggedValue> currentKey(thread, JSTaggedValue::Undefined());
913     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
914     Local<JSValueRef> jsKey = StringRef::NewFromUtf8(ecmaVm, "key");
915     Local<JSValueRef> jsValue = StringRef::NewFromUtf8(ecmaVm, "value");
916     uint32_t pos = 0;
917     uint32_t index = 0;
918     while (index < length) {
919         node.Update(TaggedHashArray::GetCurrentNode(thread, queue, table, index));
920         if (!node.GetTaggedValue().IsHole()) {
921             currentKey.Update(node->GetKey());
922             currentValue.Update(node->GetValue());
923             Local<ObjectRef> objRef = ObjectRef::New(ecmaVm);
924             objRef->Set(ecmaVm, jsKey, JSNApiHelper::ToLocal<JSValueRef>(currentKey));
925             objRef->Set(ecmaVm, jsValue, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
926             AddInternalProperties(ecmaVm, objRef, ArkInternalValueType::Entry, internalObjects);
927             ArrayRef::SetValueAt(ecmaVm, jsValueRef, pos++, objRef);
928         }
929     }
930     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
931     return jsValueRef;
932 }
933 
GetHashSetValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)934 Local<JSValueRef> DebuggerApi::GetHashSetValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
935                                                Global<MapRef> internalObjects)
936 {
937     JSHandle<JSAPIHashSet> hashSet(JSNApiHelper::ToJSHandle(value));
938     JSThread *thread = ecmaVm->GetJSThread();
939     JSHandle<TaggedHashArray> table(thread, hashSet->GetTable());
940     uint32_t length = table->GetLength();
941     uint32_t size = static_cast<uint32_t>(hashSet->GetSize());
942     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
943     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
944     JSMutableHandle<TaggedQueue> queue(thread, factory->NewTaggedQueue(0));
945     JSMutableHandle<TaggedNode> node(thread, JSTaggedValue::Undefined());
946     JSMutableHandle<JSTaggedValue> currentKey(thread, JSTaggedValue::Undefined());
947     Local<JSValueRef> jsValue = StringRef::NewFromUtf8(ecmaVm, "value");
948     uint32_t pos = 0;
949     uint32_t index = 0;
950     while (index < length) {
951         node.Update(TaggedHashArray::GetCurrentNode(thread, queue, table, index));
952         if (!node.GetTaggedValue().IsHole()) {
953             currentKey.Update(node->GetKey());
954             if (currentKey->IsECMAObject()) {
955                 Local<ObjectRef> objRef = ObjectRef::New(ecmaVm);
956                 objRef->Set(ecmaVm, jsValue, JSNApiHelper::ToLocal<JSValueRef>(currentKey));
957                 AddInternalProperties(ecmaVm, objRef, ArkInternalValueType::Entry, internalObjects);
958                 ArrayRef::SetValueAt(ecmaVm, jsValueRef, pos++, objRef);
959             } else {
960                 ArrayRef::SetValueAt(ecmaVm, jsValueRef, pos++, JSNApiHelper::ToLocal<JSValueRef>(currentKey));
961             }
962         }
963     }
964     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
965     return jsValueRef;
966 }
967 
GetLightWeightMapValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)968 Local<JSValueRef> DebuggerApi::GetLightWeightMapValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
969                                                       Global<MapRef> internalObjects)
970 {
971     JSHandle<JSAPILightWeightMap> lightweightMap(JSNApiHelper::ToJSHandle(value));
972     uint32_t size  = static_cast<uint32_t>(lightweightMap->GetSize());
973     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
974     JSThread *thread = ecmaVm->GetJSThread();
975     JSMutableHandle<TaggedArray> keys(thread, lightweightMap->GetKeys());
976     JSMutableHandle<TaggedArray> values(thread, lightweightMap->GetValues());
977     JSMutableHandle<JSTaggedValue> currentKey(thread, JSTaggedValue::Undefined());
978     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
979     Local<JSValueRef> jsKey = StringRef::NewFromUtf8(ecmaVm, "key");
980     Local<JSValueRef> jsValue = StringRef::NewFromUtf8(ecmaVm, "value");
981     uint32_t index = 0;
982     while (index < size) {
983         currentKey.Update(keys->Get(index));
984         currentValue.Update(values->Get(index));
985         Local<ObjectRef> objRef = ObjectRef::New(ecmaVm);
986         objRef->Set(ecmaVm, jsKey, JSNApiHelper::ToLocal<JSValueRef>(currentKey));
987         objRef->Set(ecmaVm, jsValue, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
988         AddInternalProperties(ecmaVm, objRef, ArkInternalValueType::Entry, internalObjects);
989         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, objRef);
990     }
991     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
992     return jsValueRef;
993 }
994 
GetLightWeightSetValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)995 Local<JSValueRef> DebuggerApi::GetLightWeightSetValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
996                                                       Global<MapRef> internalObjects)
997 {
998     JSHandle<JSAPILightWeightSet> lightWeightSet(JSNApiHelper::ToJSHandle(value));
999     uint32_t size = static_cast<uint32_t>(lightWeightSet->GetSize());
1000     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1001     JSThread *thread = ecmaVm->GetJSThread();
1002     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1003     Local<JSValueRef> jsValue = StringRef::NewFromUtf8(ecmaVm, "value");
1004     uint32_t index = 0;
1005     while (index < size) {
1006         currentValue.Update(lightWeightSet->GetValueAt(index));
1007         if (currentValue->IsECMAObject()) {
1008             Local<ObjectRef> objRef = ObjectRef::New(ecmaVm);
1009             objRef->Set(ecmaVm, jsValue, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1010             AddInternalProperties(ecmaVm, objRef, ArkInternalValueType::Entry, internalObjects);
1011             ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, objRef);
1012         } else {
1013             ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1014         }
1015     }
1016     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1017     return jsValueRef;
1018 }
1019 
GetLinkedListValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1020 Local<JSValueRef> DebuggerApi::GetLinkedListValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1021                                                   Global<MapRef> internalObjects)
1022 {
1023     JSHandle<JSAPILinkedList> linkedList(JSNApiHelper::ToJSHandle(value));
1024     JSThread *thread = ecmaVm->GetJSThread();
1025     JSHandle<TaggedDoubleList> doubleList(thread, linkedList->GetDoubleList());
1026     uint32_t size = static_cast<uint32_t>(linkedList->Length());
1027     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1028     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1029     int valueNode = TaggedDoubleList::ELEMENTS_START_INDEX;
1030     uint32_t index = 0;
1031     while (index < size) {
1032         valueNode = doubleList->GetNextDataIndex(valueNode);
1033         currentValue.Update(doubleList->GetElement(valueNode));
1034         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1035     }
1036     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1037     return jsValueRef;
1038 }
1039 
GetListValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1040 Local<JSValueRef> DebuggerApi::GetListValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1041                                             Global<MapRef> internalObjects)
1042 {
1043     JSHandle<JSAPIList> list(JSNApiHelper::ToJSHandle(value));
1044     JSThread *thread = ecmaVm->GetJSThread();
1045     JSHandle<TaggedSingleList> singleList(thread, list->GetSingleList());
1046     uint32_t size = static_cast<uint32_t>(list->Length());
1047     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1048     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1049     int valueNode = TaggedDoubleList::ELEMENTS_START_INDEX;
1050     uint32_t index = 0;
1051     while (index < size) {
1052         valueNode = singleList->GetNextDataIndex(valueNode);
1053         currentValue.Update(singleList->GetElement(valueNode));
1054         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1055     }
1056     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1057     return jsValueRef;
1058 }
1059 
GetPlainArrayValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1060 Local<JSValueRef> DebuggerApi::GetPlainArrayValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1061                                                   Global<MapRef> internalObjects)
1062 {
1063     JSHandle<JSAPIPlainArray> plainarray(JSNApiHelper::ToJSHandle(value));
1064     uint32_t size = static_cast<uint32_t>(plainarray->GetSize());
1065     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1066     JSThread *thread = ecmaVm->GetJSThread();
1067     JSHandle<TaggedArray> keyArray(thread, plainarray->GetKeys());
1068     JSHandle<TaggedArray> valueArray(thread, plainarray->GetValues());
1069     JSMutableHandle<JSTaggedValue> currentKey(thread, JSTaggedValue::Undefined());
1070     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1071     Local<JSValueRef> jsKey = StringRef::NewFromUtf8(ecmaVm, "key");
1072     Local<JSValueRef> jsValue = StringRef::NewFromUtf8(ecmaVm, "value");
1073     uint32_t index = 0;
1074     while (index < size) {
1075         currentKey.Update(keyArray->Get(index));
1076         currentValue.Update(valueArray->Get(index));
1077         Local<ObjectRef> objRef = ObjectRef::New(ecmaVm);
1078         objRef->Set(ecmaVm, jsKey, JSNApiHelper::ToLocal<JSValueRef>(currentKey));
1079         objRef->Set(ecmaVm, jsValue, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1080         AddInternalProperties(ecmaVm, objRef, ArkInternalValueType::Entry, internalObjects);
1081         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, objRef);
1082     }
1083     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1084     return jsValueRef;
1085 }
1086 
GetQueueValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1087 Local<JSValueRef> DebuggerApi::GetQueueValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1088                                              Global<MapRef> internalObjects)
1089 {
1090     JSHandle<JSAPIQueue> queue(JSNApiHelper::ToJSHandle(value));
1091     uint32_t size = static_cast<uint32_t>(queue->GetSize());
1092     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1093     JSThread *thread = ecmaVm->GetJSThread();
1094     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1095     uint32_t pos = 0;
1096     uint32_t index = 0;
1097     while (index < size) {
1098         currentValue.Update(queue->Get(thread, pos));
1099         pos = queue->GetNextPosition(pos);
1100         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1101     }
1102     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1103     return jsValueRef;
1104 }
1105 
GetStackValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1106 Local<JSValueRef> DebuggerApi::GetStackValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1107                                              Global<MapRef> internalObjects)
1108 {
1109     JSHandle<JSAPIStack> stack(JSNApiHelper::ToJSHandle(value));
1110     uint32_t size = static_cast<uint32_t>(stack->GetSize());
1111     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1112     JSThread *thread = ecmaVm->GetJSThread();
1113     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1114     uint32_t index = 0;
1115     while (index < size + 1) {
1116         currentValue.Update(stack->Get(index));
1117         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1118     }
1119     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1120     return jsValueRef;
1121 }
1122 
GetTreeMapValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1123 Local<JSValueRef> DebuggerApi::GetTreeMapValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1124                                                Global<MapRef> internalObjects)
1125 {
1126     JSHandle<JSAPITreeMap> treeMap(JSNApiHelper::ToJSHandle(value));
1127     uint32_t size = static_cast<uint32_t>(treeMap->GetSize());
1128     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1129     JSThread *thread = ecmaVm->GetJSThread();
1130     JSMutableHandle<TaggedTreeMap> iteratedMap(thread, treeMap->GetTreeMap());
1131     uint32_t elements = static_cast<uint32_t>(iteratedMap->NumberOfElements());
1132     JSHandle<TaggedArray> entries = TaggedTreeMap::GetArrayFromMap(thread, iteratedMap);
1133     JSMutableHandle<JSTaggedValue> currentKey(thread, JSTaggedValue::Undefined());
1134     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1135     Local<JSValueRef> jsKey = StringRef::NewFromUtf8(ecmaVm, "key");
1136     Local<JSValueRef> jsValue = StringRef::NewFromUtf8(ecmaVm, "value");
1137     uint32_t index = 0;
1138     while (index < elements) {
1139         int entriesIndex = entries->Get(index).GetInt();
1140         currentKey.Update(iteratedMap->GetKey(entriesIndex));
1141         currentValue.Update(iteratedMap->GetValue(entriesIndex));
1142         Local<ObjectRef> objRef = ObjectRef::New(ecmaVm);
1143         objRef->Set(ecmaVm, jsKey, JSNApiHelper::ToLocal<JSValueRef>(currentKey));
1144         objRef->Set(ecmaVm, jsValue, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1145         AddInternalProperties(ecmaVm, objRef, ArkInternalValueType::Entry, internalObjects);
1146         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, objRef);
1147     }
1148     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1149     return jsValueRef;
1150 }
1151 
GetTreeSetValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1152 Local<JSValueRef> DebuggerApi::GetTreeSetValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1153                                                Global<MapRef> internalObjects)
1154 {
1155     JSHandle<JSAPITreeSet> treeSet(JSNApiHelper::ToJSHandle(value));
1156     JSThread *thread = ecmaVm->GetJSThread();
1157     JSMutableHandle<TaggedTreeSet> iteratedSet(thread, treeSet->GetTreeSet());
1158     uint32_t elements = static_cast<uint32_t>(iteratedSet->NumberOfElements());
1159     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, elements);
1160     JSHandle<TaggedArray> entries = TaggedTreeSet::GetArrayFromSet(thread, iteratedSet);
1161     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1162     Local<JSValueRef> jsValue = StringRef::NewFromUtf8(ecmaVm, "value");
1163     uint32_t index = 0;
1164     while (index < elements) {
1165         int entriesIndex = entries->Get(index).GetInt();
1166         currentValue.Update(iteratedSet->GetKey(entriesIndex));
1167         if (currentValue->IsECMAObject()) {
1168             Local<ObjectRef> objRef = ObjectRef::New(ecmaVm);
1169             objRef->Set(ecmaVm, jsValue, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1170             AddInternalProperties(ecmaVm, objRef, ArkInternalValueType::Entry, internalObjects);
1171             ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, objRef);
1172         } else {
1173             ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1174         }
1175     }
1176     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1177     return jsValueRef;
1178 }
1179 
GetVectorValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1180 Local<JSValueRef> DebuggerApi::GetVectorValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1181                                               Global<MapRef> internalObjects)
1182 {
1183     JSHandle<JSAPIVector> vector(JSNApiHelper::ToJSHandle(value));
1184     uint32_t size = static_cast<uint32_t>(vector->GetSize());
1185     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1186     JSThread *thread = ecmaVm->GetJSThread();
1187     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1188     uint32_t index = 0;
1189     while (index < size) {
1190         currentValue.Update(vector->Get(thread, vector, index));
1191         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1192     }
1193     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1194     return jsValueRef;
1195 }
1196 
DropLastFrame(const EcmaVM * ecmaVm)1197 void DebuggerApi::DropLastFrame(const EcmaVM *ecmaVm)
1198 {
1199     JSThread *thread = ecmaVm->GetJSThread();
1200     auto *debuggerMgr = ecmaVm->GetJsDebuggerManager();
1201     if (!thread->IsAsmInterpreter()) {
1202         debuggerMgr->DropLastFrame();
1203     }
1204 }
1205 }  // namespace panda::ecmascript::tooling
1206