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