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