• 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 
328 // ScopeInfo
GetProperties(const EcmaVM * ecmaVm,const FrameHandler * frameHandler,int32_t level,uint32_t slot)329 Local<JSValueRef> DebuggerApi::GetProperties(const EcmaVM *ecmaVm, const FrameHandler *frameHandler,
330                                              int32_t level, uint32_t slot)
331 {
332     JSTaggedValue env = frameHandler->GetEnv();
333     for (int i = 0; i < level; i++) {
334         JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv();
335         ASSERT(!taggedParentEnv.IsUndefined());
336         env = taggedParentEnv;
337     }
338     JSTaggedValue value = LexicalEnv::Cast(env.GetTaggedObject())->GetProperties(slot);
339     JSHandle<JSTaggedValue> handledValue(ecmaVm->GetJSThread(), value);
340     return JSNApiHelper::ToLocal<JSValueRef>(handledValue);
341 }
342 
SetProperties(const EcmaVM * ecmaVm,const FrameHandler * frameHandler,int32_t level,uint32_t slot,Local<JSValueRef> value)343 void DebuggerApi::SetProperties(const EcmaVM *ecmaVm, const FrameHandler *frameHandler,
344                                 int32_t level, uint32_t slot, Local<JSValueRef> value)
345 {
346     JSTaggedValue env = frameHandler->GetEnv();
347     for (int i = 0; i < level; i++) {
348         JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv();
349         ASSERT(!taggedParentEnv.IsUndefined());
350         env = taggedParentEnv;
351     }
352     JSTaggedValue target = JSNApiHelper::ToJSHandle(value).GetTaggedValue();
353     LexicalEnv::Cast(env.GetTaggedObject())->SetProperties(ecmaVm->GetJSThread(), slot, target);
354 }
355 
GetLevelSlot(const FrameHandler * frameHandler,std::string_view name)356 std::pair<int32_t, uint32_t> DebuggerApi::GetLevelSlot(const FrameHandler *frameHandler, std::string_view name)
357 {
358     int32_t level = 0;
359     uint32_t slot = 0;
360     JSTaggedValue curEnv = frameHandler->GetEnv();
361     for (; curEnv.IsTaggedArray(); curEnv = LexicalEnv::Cast(curEnv.GetTaggedObject())->GetParentEnv(), level++) {
362         LexicalEnv *lexicalEnv = LexicalEnv::Cast(curEnv.GetTaggedObject());
363         if (lexicalEnv->GetScopeInfo().IsHole()) {
364             continue;
365         }
366         auto result = JSNativePointer::Cast(lexicalEnv->GetScopeInfo().GetTaggedObject())->GetExternalPointer();
367         ScopeDebugInfo *scopeDebugInfo = reinterpret_cast<ScopeDebugInfo *>(result);
368         auto iter = scopeDebugInfo->scopeInfo.find(name.data());
369         if (iter == scopeDebugInfo->scopeInfo.end()) {
370             continue;
371         }
372         slot = iter->second;
373         return std::make_pair(level, slot);
374     }
375     return std::make_pair(-1, 0);
376 }
377 
GetGlobalValue(const EcmaVM * ecmaVm,Local<StringRef> name)378 Local<JSValueRef> DebuggerApi::GetGlobalValue(const EcmaVM *ecmaVm, Local<StringRef> name)
379 {
380     JSTaggedValue result;
381     JSTaggedValue globalObj = ecmaVm->GetGlobalEnv()->GetGlobalObject();
382     JSThread *thread = ecmaVm->GetJSThread();
383 
384     JSTaggedValue key = JSNApiHelper::ToJSTaggedValue(*name);
385     JSTaggedValue globalRec = SlowRuntimeStub::LdGlobalRecord(thread, key);
386     if (!globalRec.IsUndefined()) {
387         ASSERT(globalRec.IsPropertyBox());
388         result = PropertyBox::Cast(globalRec.GetTaggedObject())->GetValue();
389         return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, result));
390     }
391 
392     JSTaggedValue globalVar = FastRuntimeStub::GetGlobalOwnProperty(thread, globalObj, key);
393     if (!globalVar.IsHole()) {
394         return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, globalVar));
395     } else {
396         result = SlowRuntimeStub::TryLdGlobalByNameFromGlobalProto(thread, globalObj, key);
397         return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, result));
398     }
399 
400     return Local<JSValueRef>();
401 }
402 
SetGlobalValue(const EcmaVM * ecmaVm,Local<StringRef> name,Local<JSValueRef> value)403 bool DebuggerApi::SetGlobalValue(const EcmaVM *ecmaVm, Local<StringRef> name, Local<JSValueRef> value)
404 {
405     JSTaggedValue result;
406     JSTaggedValue globalObj = ecmaVm->GetGlobalEnv()->GetGlobalObject();
407     JSThread *thread = ecmaVm->GetJSThread();
408 
409     JSTaggedValue key = JSNApiHelper::ToJSTaggedValue(*name);
410     JSTaggedValue newVal = JSNApiHelper::ToJSTaggedValue(*value);
411     JSTaggedValue globalRec = SlowRuntimeStub::LdGlobalRecord(thread, key);
412     if (!globalRec.IsUndefined()) {
413         result = SlowRuntimeStub::TryUpdateGlobalRecord(thread, key, newVal);
414         return !result.IsException();
415     }
416 
417     JSTaggedValue globalVar = FastRuntimeStub::GetGlobalOwnProperty(thread, globalObj, key);
418     if (!globalVar.IsHole()) {
419         result = SlowRuntimeStub::StGlobalVar(thread, key, newVal);
420         return !result.IsException();
421     }
422 
423     return false;
424 }
425 
GetCurrentModule(const EcmaVM * ecmaVm)426 JSTaggedValue DebuggerApi::GetCurrentModule(const EcmaVM *ecmaVm)
427 {
428     JSThread *thread = ecmaVm->GetJSThread();
429     FrameHandler frameHandler(thread);
430     for (; frameHandler.HasFrame(); frameHandler.PrevJSFrame()) {
431         if (frameHandler.IsEntryFrame()) {
432             continue;
433         }
434         Method *method = frameHandler.GetMethod();
435         // Skip builtins method
436         if (method->IsNativeWithCallField()) {
437             continue;
438         }
439         JSTaggedValue func = frameHandler.GetFunction();
440         JSTaggedValue module = JSFunction::Cast(func.GetTaggedObject())->GetModule();
441         if (module.IsUndefined()) {
442             continue;
443         }
444         return module;
445     }
446     UNREACHABLE();
447 }
448 
GetImportModule(const EcmaVM * ecmaVm,const JSHandle<JSTaggedValue> & currentModule,std::string & name)449 JSHandle<JSTaggedValue> DebuggerApi::GetImportModule(const EcmaVM *ecmaVm,
450                                                      const JSHandle<JSTaggedValue> &currentModule, std::string &name)
451 {
452     JSThread *thread = ecmaVm->GetJSThread();
453     JSMutableHandle<JSTaggedValue> importModule(thread, thread->GlobalConstants()->GetUndefined());
454     if (!currentModule->IsSourceTextModule()) {
455         return importModule;
456     }
457 
458     JSTaggedValue importEntries = SourceTextModule::Cast(currentModule->GetTaggedObject())->GetImportEntries();
459     if (importEntries.IsUndefined()) {
460         return importModule;
461     }
462 
463     JSHandle<TaggedArray> importArray(thread, TaggedArray::Cast(importEntries.GetTaggedObject()));
464     size_t importEntriesLen = importArray->GetLength();
465     JSHandle<JSTaggedValue> starString = thread->GlobalConstants()->GetHandledStarString();
466     JSMutableHandle<ImportEntry> ee(thread, thread->GlobalConstants()->GetUndefined());
467     JSMutableHandle<TaggedArray> environment(thread, thread->GlobalConstants()->GetUndefined());
468     for (size_t idx = 0; idx < importEntriesLen; idx++) {
469         ee.Update(importArray->Get(idx));
470         JSTaggedValue localName = ee->GetLocalName();
471         JSTaggedValue importName = ee->GetImportName();
472         // Skip 'import * as name from xxx'
473         if (localName.IsString() && !JSTaggedValue::SameValue(importName, starString.GetTaggedValue())) {
474             std::string varName = EcmaStringAccessor(localName).ToStdString();
475             if (varName != name) {
476                 continue;
477             }
478             JSTaggedValue moduleEnvironment = SourceTextModule::Cast(
479                 currentModule->GetTaggedObject())->GetEnvironment();
480             environment.Update(moduleEnvironment);
481             JSTaggedValue resolvedBinding = environment->Get(idx);
482             ResolvedIndexBinding *binding = ResolvedIndexBinding::Cast(resolvedBinding.GetTaggedObject());
483             importModule.Update(binding->GetModule());
484             name = EcmaStringAccessor(importName).ToStdString();
485             return importModule;
486         }
487     }
488     return importModule;
489 }
490 
GetModuleVariableIndex(const EcmaVM * ecmaVm,const JSHandle<JSTaggedValue> & currentModule,std::string & name)491 int32_t DebuggerApi::GetModuleVariableIndex(const EcmaVM *ecmaVm, const JSHandle<JSTaggedValue> &currentModule,
492                                             std::string &name)
493 {
494     if (!currentModule->IsSourceTextModule()) {
495         return -1;
496     }
497     JSTaggedValue dictionary = SourceTextModule::Cast(currentModule->GetTaggedObject())->GetNameDictionary();
498     if (dictionary.IsUndefined()) {
499         return -1;
500     }
501 
502     JSThread *thread = ecmaVm->GetJSThread();
503     if (dictionary.IsTaggedArray()) {
504         JSTaggedValue localExportEntries = SourceTextModule::Cast(
505             currentModule->GetTaggedObject())->GetLocalExportEntries();
506         ASSERT(localExportEntries.IsTaggedArray());
507         JSHandle<TaggedArray> localExportArray(thread, TaggedArray::Cast(localExportEntries.GetTaggedObject()));
508         uint32_t exportEntriesLen = localExportArray->GetLength();
509         JSMutableHandle<LocalExportEntry> ee(thread, thread->GlobalConstants()->GetUndefined());
510         for (uint32_t idx = 0; idx < exportEntriesLen; idx++) {
511             ee.Update(localExportArray->Get(idx));
512             JSTaggedValue localKey = ee->GetLocalName();
513             JSTaggedValue exportKey = ee->GetExportName();
514             if (localKey.IsString() && exportKey.IsString()) {
515                 std::string localName = EcmaStringAccessor(localKey).ToStdString();
516                 std::string exportName = EcmaStringAccessor(exportKey).ToStdString();
517                 if (localName == name || exportName == name) {
518                     return idx;
519                 }
520             }
521         }
522     }
523     return -1;
524 }
525 
GetRequestModuleIndex(const EcmaVM * ecmaVm,JSTaggedValue moduleRequest,const JSHandle<JSTaggedValue> & currentModule)526 int32_t DebuggerApi::GetRequestModuleIndex(const EcmaVM *ecmaVm, JSTaggedValue moduleRequest,
527                                            const JSHandle<JSTaggedValue> &currentModule)
528 {
529     if (!currentModule->IsSourceTextModule()) {
530         return -1;
531     }
532     JSThread *thread = ecmaVm->GetJSThread();
533     JSHandle<SourceTextModule> module(thread, SourceTextModule::Cast(currentModule->GetTaggedObject()));
534     JSHandle<JSTaggedValue> required(thread, moduleRequest);
535     JSHandle<TaggedArray> requestedModules(thread, module->GetRequestedModules());
536     uint32_t requestedModulesLen = requestedModules->GetLength();
537     for (uint32_t idx = 0; idx < requestedModulesLen; idx++) {
538         JSTaggedValue requestModule = requestedModules->Get(idx);
539         if (JSTaggedValue::SameValue(required.GetTaggedValue(), requestModule)) {
540             return idx;
541         }
542     }
543     LOG_ECMA(FATAL) << "this branch is unreachable";
544     return -1;
545 }
546 
GetExportVariableValue(const EcmaVM * ecmaVm,const JSHandle<JSTaggedValue> & currentModule,std::string & name)547 Local<JSValueRef> DebuggerApi::GetExportVariableValue(const EcmaVM *ecmaVm,
548                                                       const JSHandle<JSTaggedValue> &currentModule, std::string &name)
549 {
550     Local<JSValueRef> result;
551     if (!currentModule->IsSourceTextModule()) {
552         return result;
553     }
554     int32_t index = GetModuleVariableIndex(ecmaVm, currentModule, name);
555     if (index == -1) {
556         return result;
557     }
558 
559     JSTaggedValue dictionary = SourceTextModule::Cast(currentModule->GetTaggedObject())->GetNameDictionary();
560     if (dictionary.IsUndefined()) {
561         return result;
562     }
563 
564     JSThread *thread = ecmaVm->GetJSThread();
565     if (dictionary.IsTaggedArray()) {
566         TaggedArray *array = TaggedArray::Cast(dictionary.GetTaggedObject());
567         JSTaggedValue moduleValue = array->Get(index);
568         result = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, moduleValue));
569         return result;
570     }
571     return result;
572 }
573 
SetExportVariableValue(const EcmaVM * ecmaVm,const JSHandle<JSTaggedValue> & currentModule,std::string & name,Local<JSValueRef> value)574 bool DebuggerApi::SetExportVariableValue(const EcmaVM *ecmaVm, const JSHandle<JSTaggedValue> &currentModule,
575                                          std::string &name, Local<JSValueRef> value)
576 {
577     if (!currentModule->IsSourceTextModule()) {
578         return false;
579     }
580     int32_t index = GetModuleVariableIndex(ecmaVm, currentModule, name);
581     if (index == -1) {
582         return false;
583     }
584 
585     JSTaggedValue dictionary = SourceTextModule::Cast(currentModule->GetTaggedObject())->GetNameDictionary();
586     if (dictionary.IsUndefined()) {
587         return false;
588     }
589 
590     JSThread *thread = ecmaVm->GetJSThread();
591     JSTaggedValue curValue = JSNApiHelper::ToJSTaggedValue(*value);
592     if (dictionary.IsTaggedArray()) {
593         TaggedArray *array = TaggedArray::Cast(dictionary.GetTaggedObject());
594         array->Set(thread, index, curValue);
595         return true;
596     }
597     return false;
598 }
599 
GetModuleValue(const EcmaVM * ecmaVm,const JSHandle<JSTaggedValue> & currentModule,std::string & name)600 Local<JSValueRef> DebuggerApi::GetModuleValue(const EcmaVM *ecmaVm, const JSHandle<JSTaggedValue> &currentModule,
601                                               std::string &name)
602 {
603     Local<JSValueRef> result;
604     if (!currentModule->IsSourceTextModule()) {
605         return result;
606     }
607     // Get variable from local export
608     result = GetExportVariableValue(ecmaVm, currentModule, name);
609     if (!result.IsEmpty()) {
610         return result;
611     }
612     // Get variable from import module
613     JSHandle<JSTaggedValue> importModule = GetImportModule(ecmaVm, currentModule, name);
614     result = GetExportVariableValue(ecmaVm, importModule, name);
615     return result;
616 }
617 
SetModuleValue(const EcmaVM * ecmaVm,const JSHandle<JSTaggedValue> & currentModule,std::string & name,Local<JSValueRef> value)618 bool DebuggerApi::SetModuleValue(const EcmaVM *ecmaVm, const JSHandle<JSTaggedValue> &currentModule,
619                                  std::string &name, Local<JSValueRef> value)
620 {
621     bool result;
622     if (!currentModule->IsSourceTextModule()) {
623         return false;
624     }
625     // Set local export variable
626     result = SetExportVariableValue(ecmaVm, currentModule, name, value);
627     if (result == true) {
628         return result;
629     }
630     // Set import module variable
631     JSHandle<JSTaggedValue> importModule = GetImportModule(ecmaVm, currentModule, name);
632     result = SetExportVariableValue(ecmaVm, importModule, name, value);
633     if (result == true) {
634         return result;
635     }
636     return false;
637 }
638 
InitializeExportVariables(const EcmaVM * ecmaVm,Local<ObjectRef> & moduleObj,const JSHandle<JSTaggedValue> & currentModule)639 void DebuggerApi::InitializeExportVariables(const EcmaVM *ecmaVm, Local<ObjectRef> &moduleObj,
640                                             const JSHandle<JSTaggedValue> &currentModule)
641 {
642     if (!currentModule->IsSourceTextModule()) {
643         return;
644     }
645     JSTaggedValue localExportEntries = SourceTextModule::Cast(
646         currentModule->GetTaggedObject())->GetLocalExportEntries();
647     if (localExportEntries.IsUndefined()) {
648         return;
649     }
650 
651     JSThread *thread = ecmaVm->GetJSThread();
652     JSHandle<TaggedArray> localExportArray(thread, TaggedArray::Cast(localExportEntries.GetTaggedObject()));
653     uint32_t exportEntriesLen = localExportArray->GetLength();
654     JSMutableHandle<LocalExportEntry> ee(thread, thread->GlobalConstants()->GetUndefined());
655     JSMutableHandle<JSTaggedValue> name(thread, thread->GlobalConstants()->GetUndefined());
656     JSMutableHandle<JSTaggedValue> value(thread, thread->GlobalConstants()->GetUndefined());
657     JSTaggedValue moduleValue = JSTaggedValue::Undefined();
658     for (uint32_t idx = 0; idx < exportEntriesLen; idx++) {
659         ee.Update(localExportArray->Get(idx));
660         JSTaggedValue key = ee->GetLocalName();
661         name.Update(key);
662         value.Update(moduleValue);
663         if (key.IsString()) {
664             Local<JSValueRef> variableName = JSNApiHelper::ToLocal<JSValueRef>(name);
665             Local<JSValueRef> variableValue = JSNApiHelper::ToLocal<JSValueRef>(value);
666             PropertyAttribute descriptor(variableValue, true, true, true);
667             moduleObj->DefineProperty(ecmaVm, variableName, descriptor);
668         }
669     }
670 }
671 
GetLocalExportVariables(const EcmaVM * ecmaVm,Local<ObjectRef> & moduleObj,const JSHandle<JSTaggedValue> & currentModule,bool isImportStar)672 void DebuggerApi::GetLocalExportVariables(const EcmaVM *ecmaVm, Local<ObjectRef> &moduleObj,
673                                           const JSHandle<JSTaggedValue> &currentModule, bool isImportStar)
674 {
675     if (!currentModule->IsSourceTextModule()) {
676         return;
677     }
678     JSTaggedValue dictionary = SourceTextModule::Cast(currentModule->GetTaggedObject())->GetNameDictionary();
679     if (dictionary.IsUndefined()) {
680         InitializeExportVariables(ecmaVm, moduleObj, currentModule);
681         return;
682     }
683 
684     JSThread *thread = ecmaVm->GetJSThread();
685     JSMutableHandle<JSTaggedValue> name(thread, thread->GlobalConstants()->GetUndefined());
686     JSMutableHandle<JSTaggedValue> value(thread, thread->GlobalConstants()->GetUndefined());
687     if (dictionary.IsTaggedArray()) {
688         JSTaggedValue localExportEntries = SourceTextModule::Cast(
689             currentModule->GetTaggedObject())->GetLocalExportEntries();
690         ASSERT(localExportEntries.IsTaggedArray());
691         JSHandle<TaggedArray> localExportArray(thread, TaggedArray::Cast(localExportEntries.GetTaggedObject()));
692         uint32_t exportEntriesLen = localExportArray->GetLength();
693         JSHandle<TaggedArray> dict(thread, TaggedArray::Cast(dictionary.GetTaggedObject()));
694         uint32_t valueLen = dict->GetLength();
695         if (exportEntriesLen != valueLen) {
696             LOG_FULL(FATAL) << "Key does not match value";
697         }
698 
699         JSMutableHandle<LocalExportEntry> ee(thread, thread->GlobalConstants()->GetUndefined());
700         for (uint32_t idx = 0; idx < exportEntriesLen; idx++) {
701             ee.Update(localExportArray->Get(idx));
702             JSTaggedValue key;
703             if (isImportStar) {
704                 key = ee->GetExportName();
705             } else {
706                 key = ee->GetLocalName();
707             }
708             name.Update(key);
709             JSTaggedValue moduleValue = dict->Get(idx);
710             if (moduleValue.IsHole()) {
711                 moduleValue = JSTaggedValue::Undefined();
712             }
713             value.Update(moduleValue);
714             if (key.IsString()) {
715                 Local<JSValueRef> variableName = JSNApiHelper::ToLocal<JSValueRef>(name);
716                 Local<JSValueRef> variableValue = JSNApiHelper::ToLocal<JSValueRef>(value);
717                 PropertyAttribute descriptor(variableValue, true, true, true);
718                 moduleObj->DefineProperty(ecmaVm, variableName, descriptor);
719             }
720         }
721     }
722 }
723 
GetIndirectExportVariables(const EcmaVM * ecmaVm,Local<ObjectRef> & moduleObj,const JSHandle<JSTaggedValue> & currentModule)724 void DebuggerApi::GetIndirectExportVariables(const EcmaVM *ecmaVm, Local<ObjectRef> &moduleObj,
725                                              const JSHandle<JSTaggedValue> &currentModule)
726 {
727     if (!currentModule->IsSourceTextModule()) {
728         return;
729     }
730     JSTaggedValue indirectExportEntries = SourceTextModule::Cast(
731         currentModule->GetTaggedObject())->GetIndirectExportEntries();
732     if (indirectExportEntries.IsUndefined()) {
733         return;
734     }
735     ASSERT(indirectExportEntries.IsTaggedArray());
736     JSThread *thread = ecmaVm->GetJSThread();
737     JSHandle<TaggedArray> indirectExportArray(thread, TaggedArray::Cast(indirectExportEntries.GetTaggedObject()));
738     uint32_t indirectExportEntriesLen = indirectExportArray->GetLength();
739     JSMutableHandle<IndirectExportEntry> ee(thread, thread->GlobalConstants()->GetUndefined());
740     JSMutableHandle<JSTaggedValue> name(thread, thread->GlobalConstants()->GetUndefined());
741     for (uint32_t idx = 0; idx < indirectExportEntriesLen; idx++) {
742         ee.Update(indirectExportArray->Get(idx));
743         JSTaggedValue key = ee->GetImportName();
744         name.Update(key);
745         if (key.IsString()) {
746             Local<JSValueRef> variableName = JSNApiHelper::ToLocal<JSValueRef>(name);
747             JSHandle<JSTaggedValue> moduleRequest(thread, ee->GetModuleRequest());
748             JSHandle<JSTaggedValue> importModule;
749             JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(currentModule);
750             CString moduleRecordName = module->GetEcmaModuleRecordNameString();
751             if (moduleRecordName.empty()) {
752                 importModule = SourceTextModule::HostResolveImportedModule(thread, module, moduleRequest);
753             } else {
754                 importModule = SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, moduleRequest);
755                 RETURN_IF_ABRUPT_COMPLETION(thread);
756             }
757             std::string importName = EcmaStringAccessor(ee->GetImportName()).ToStdString();
758             Local<JSValueRef> value = GetModuleValue(ecmaVm, importModule, importName);
759             PropertyAttribute descriptor(value, true, true, true);
760             moduleObj->DefineProperty(ecmaVm, variableName, descriptor);
761         }
762     }
763 }
764 
GetImportVariables(const EcmaVM * ecmaVm,Local<ObjectRef> & moduleObj,const JSHandle<JSTaggedValue> & currentModule)765 void DebuggerApi::GetImportVariables(const EcmaVM *ecmaVm, Local<ObjectRef> &moduleObj,
766                                      const JSHandle<JSTaggedValue> &currentModule)
767 {
768     if (!currentModule->IsSourceTextModule()) {
769         return;
770     }
771     JSTaggedValue importEntries = SourceTextModule::Cast(currentModule->GetTaggedObject())->GetImportEntries();
772     if (importEntries.IsUndefined()) {
773         return;
774     }
775 
776     JSThread *thread = ecmaVm->GetJSThread();
777     JSHandle<TaggedArray> importArray(thread, TaggedArray::Cast(importEntries.GetTaggedObject()));
778     uint32_t importEntriesLen = importArray->GetLength();
779     JSHandle<JSTaggedValue> starString = thread->GlobalConstants()->GetHandledStarString();
780     JSMutableHandle<ImportEntry> ee(thread, thread->GlobalConstants()->GetUndefined());
781     JSMutableHandle<JSTaggedValue> name(thread, thread->GlobalConstants()->GetUndefined());
782     for (uint32_t idx = 0; idx < importEntriesLen; idx++) {
783         ee.Update(importArray->Get(idx));
784         JSTaggedValue key = ee->GetImportName();
785         JSTaggedValue localName = ee->GetLocalName();
786         name.Update(localName);
787         if (JSTaggedValue::SameValue(key, starString.GetTaggedValue())) {
788             JSHandle<JSTaggedValue> moduleRequest(thread, ee->GetModuleRequest());
789             JSHandle<JSTaggedValue> importModule;
790             JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(currentModule);
791             CString moduleRecordName = module->GetEcmaModuleRecordNameString();
792             if (moduleRecordName.empty()) {
793                 importModule = SourceTextModule::HostResolveImportedModule(thread, module, moduleRequest);
794             } else {
795                 importModule = SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, moduleRequest);
796                 RETURN_IF_ABRUPT_COMPLETION(thread);
797             }
798             Local<ObjectRef> importModuleObj = ObjectRef::New(ecmaVm);
799             GetLocalExportVariables(ecmaVm, importModuleObj, importModule, true);
800             Local<JSValueRef> variableName = JSNApiHelper::ToLocal<JSValueRef>(name);
801             PropertyAttribute descriptor(static_cast<Local<JSValueRef>>(importModuleObj), true, true, true);
802             moduleObj->DefineProperty(ecmaVm, variableName, descriptor);
803             continue;
804         }
805         JSTaggedValue moduleValue =
806             thread->GetCurrentEcmaContext()->GetModuleManager()->GetModuleValueOutter(idx, currentModule);
807         Local<JSValueRef> value = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, moduleValue));
808         Local<JSValueRef> variableName = JSNApiHelper::ToLocal<JSValueRef>(name);
809         PropertyAttribute descriptor(value, true, true, true);
810         moduleObj->DefineProperty(ecmaVm, variableName, descriptor);
811     }
812 }
813 
HandleUncaughtException(const EcmaVM * ecmaVm,std::string & message)814 void DebuggerApi::HandleUncaughtException(const EcmaVM *ecmaVm, std::string &message)
815 {
816     JSThread *thread = ecmaVm->GetJSThread();
817     [[maybe_unused]] EcmaHandleScope handleScope(thread);
818     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
819 
820     JSHandle<JSTaggedValue> exHandle(thread, thread->GetException());
821     thread->ClearException();
822     if (exHandle->IsJSError()) {
823         JSHandle<JSTaggedValue> nameKey = globalConst->GetHandledNameString();
824         JSHandle<EcmaString> name(JSObject::GetProperty(thread, exHandle, nameKey).GetValue());
825         JSHandle<JSTaggedValue> msgKey = globalConst->GetHandledMessageString();
826         JSHandle<EcmaString> msg(JSObject::GetProperty(thread, exHandle, msgKey).GetValue());
827         message = ConvertToString(*name) + ": " + ConvertToString(*msg);
828     } else {
829         JSHandle<EcmaString> ecmaStr = JSTaggedValue::ToString(thread, exHandle);
830         message = ConvertToString(*ecmaStr);
831     }
832 }
833 
GenerateFuncFromBuffer(const EcmaVM * ecmaVm,const void * buffer,size_t size,std::string_view entryPoint)834 Local<FunctionRef> DebuggerApi::GenerateFuncFromBuffer(const EcmaVM *ecmaVm, const void *buffer,
835                                                        size_t size, std::string_view entryPoint)
836 {
837     JSPandaFileManager *mgr = JSPandaFileManager::GetInstance();
838     std::shared_ptr<JSPandaFile> jsPandaFile =
839         mgr->LoadJSPandaFile(ecmaVm->GetJSThread(), "", entryPoint, buffer, size);
840     if (jsPandaFile == nullptr) {
841         return JSValueRef::Undefined(ecmaVm);
842     }
843 
844     JSHandle<Program> program = mgr->GenerateProgram(const_cast<EcmaVM *>(ecmaVm), jsPandaFile.get(), entryPoint);
845     JSTaggedValue func = program->GetMainFunction();
846     return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(ecmaVm->GetJSThread(), func));
847 }
848 
EvaluateViaFuncCall(EcmaVM * ecmaVm,Local<FunctionRef> funcRef,std::shared_ptr<FrameHandler> & frameHandler)849 Local<JSValueRef> DebuggerApi::EvaluateViaFuncCall(EcmaVM *ecmaVm, Local<FunctionRef> funcRef,
850     std::shared_ptr<FrameHandler> &frameHandler)
851 {
852     JSNApi::EnableUserUncaughtErrorHandler(ecmaVm);
853 
854     JsDebuggerManager *mgr = ecmaVm->GetJsDebuggerManager();
855     bool prevDebugMode = mgr->IsDebugMode();
856     mgr->SetEvalFrameHandler(frameHandler);
857     mgr->SetDebugMode(false); // in order to catch exception
858     ecmaVm->GetJSThread()->CheckSwitchDebuggerBCStub();
859     std::vector<Local<JSValueRef>> args;
860     auto result = funcRef->Call(ecmaVm, JSValueRef::Undefined(ecmaVm), args.data(), args.size());
861     mgr->SetDebugMode(prevDebugMode);
862     ecmaVm->GetJSThread()->CheckSwitchDebuggerBCStub();
863     mgr->SetEvalFrameHandler(nullptr);
864 
865     return result;
866 }
867 
CallFunctionOnCall(EcmaVM * ecmaVm,Local<FunctionRef> funcRef,std::shared_ptr<FrameHandler> & frameHandler)868 Local<JSValueRef> DebuggerApi::CallFunctionOnCall(EcmaVM *ecmaVm, Local<FunctionRef> funcRef,
869     std::shared_ptr<FrameHandler> &frameHandler)
870 {
871     JSNApi::EnableUserUncaughtErrorHandler(ecmaVm);
872 
873     JsDebuggerManager *mgr = ecmaVm->GetJsDebuggerManager();
874     bool prevDebugMode = mgr->IsDebugMode();
875     mgr->SetEvalFrameHandler(frameHandler);
876     mgr->SetDebugMode(false);
877     ecmaVm->GetJSThread()->CheckSwitchDebuggerBCStub();
878     std::vector<Local<JSValueRef>> args;
879     auto result = funcRef->Call(ecmaVm, JSValueRef::Undefined(ecmaVm), args.data(), args.size());
880     mgr->SetDebugMode(prevDebugMode);
881     ecmaVm->GetJSThread()->CheckSwitchDebuggerBCStub();
882     mgr->SetEvalFrameHandler(nullptr);
883 
884     return result;
885 }
886 
IsExceptionCaught(const EcmaVM * ecmaVm)887 bool DebuggerApi::IsExceptionCaught(const EcmaVM *ecmaVm)
888 {
889     FrameHandler frameHandler(ecmaVm->GetJSThread());
890     for (; frameHandler.HasFrame(); frameHandler.PrevJSFrame()) {
891         if (frameHandler.IsEntryFrame()) {
892             return false;
893         }
894         auto method = frameHandler.GetMethod();
895         if (method->FindCatchBlock(frameHandler.GetBytecodeOffset()) != INVALID_INDEX) {
896             return true;
897         }
898     }
899     return false;
900 }
901 
GetPatchExtractors(const EcmaVM * ecmaVm,const std::string & url)902 std::vector<DebugInfoExtractor *> DebuggerApi::GetPatchExtractors(const EcmaVM *ecmaVm, const std::string &url)
903 {
904     const auto *hotReloadManager = ecmaVm->GetJsDebuggerManager()->GetHotReloadManager();
905     return hotReloadManager->GetPatchExtractors(url);
906 }
907 
GetBaseJSPandaFile(const EcmaVM * ecmaVm,const JSPandaFile * jsPandaFile)908 const JSPandaFile *DebuggerApi::GetBaseJSPandaFile(const EcmaVM *ecmaVm, const JSPandaFile *jsPandaFile)
909 {
910     const auto *hotReloadManager = ecmaVm->GetJsDebuggerManager()->GetHotReloadManager();
911     return hotReloadManager->GetBaseJSPandaFile(jsPandaFile);
912 }
913 
GetNativePointer(const EcmaVM * ecmaVm)914 std::vector<void *> DebuggerApi::GetNativePointer(const EcmaVM *ecmaVm)
915 {
916     void *native = nullptr;
917     std::vector<void *> nativePointer;
918     JSThread *thread = ecmaVm->GetJSThread();
919     JSTaggedType *current = const_cast<JSTaggedType *>(thread->GetCurrentFrame());
920     FrameIterator it(current, thread);
921     for (; !it.Done(); it.Advance<GCVisitedFlag::HYBRID_STACK>()) {
922         if (!it.IsJSFrame()) {
923             continue;
924         }
925         auto method = it.CheckAndGetMethod();
926         if (method == nullptr) {
927             continue;
928         }
929 
930         if (method->IsNativeWithCallField()) {
931             JSTaggedValue function = it.GetFunction();
932             JSHandle<JSTaggedValue> extraInfoValue(
933                 thread, JSFunction::Cast(function.GetTaggedObject())->GetFunctionExtraInfo());
934             auto cb = ecmaVm->GetNativePtrGetter();
935             if (extraInfoValue->IsJSNativePointer() && cb != nullptr) {
936                 JSHandle<JSNativePointer> extraInfo(extraInfoValue);
937                 native = cb(reinterpret_cast<void *>(extraInfo->GetData()));
938                 nativePointer.push_back(native);
939             }
940         } else {
941             nativePointer.push_back(nullptr); // to tell IDE this frame don't hava nativePointer
942         }
943     }
944     return nativePointer;
945 }
946 
GetContainerLength(const EcmaVM * ecmaVm,Local<JSValueRef> value)947 uint32_t DebuggerApi::GetContainerLength(const EcmaVM *ecmaVm, Local<JSValueRef> value)
948 {
949     uint32_t length = Local<ArrayRef>(value)->Length(ecmaVm);
950     return length;
951 }
952 
AddInternalProperties(const EcmaVM * ecmaVm,Local<ObjectRef> object,ArkInternalValueType type,Global<MapRef> internalObjects)953 void DebuggerApi::AddInternalProperties(const EcmaVM *ecmaVm, Local<ObjectRef> object,
954                                         ArkInternalValueType type, Global<MapRef> internalObjects)
955 {
956     if (internalObjects.IsEmpty()) {
957         return;
958     }
959     internalObjects->Set(ecmaVm, object, NumberRef::New(ecmaVm, static_cast<int32_t>(type)));
960 }
961 
GetArrayListValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)962 Local<JSValueRef> DebuggerApi::GetArrayListValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
963                                                  Global<MapRef> internalObjects)
964 {
965     JSHandle<JSAPIArrayList> arrayList(JSNApiHelper::ToJSHandle(value));
966     uint32_t size = static_cast<uint32_t>(arrayList->GetSize());
967     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
968     JSThread *thread = ecmaVm->GetJSThread();
969     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
970     uint32_t index = 0;
971     while (index < size) {
972         currentValue.Update(arrayList->Get(thread, index));
973         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
974     }
975     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
976     return jsValueRef;
977 }
978 
GetDequeValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)979 Local<JSValueRef> DebuggerApi::GetDequeValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
980                                              Global<MapRef> internalObjects)
981 {
982     JSHandle<JSAPIDeque> deque(JSNApiHelper::ToJSHandle(value));
983     uint32_t size = static_cast<uint32_t>(deque->GetSize());
984     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
985     JSThread *thread = ecmaVm->GetJSThread();
986     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
987     uint32_t index = 0;
988     while (index < size) {
989         currentValue.Update(deque->Get(index));
990         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
991     }
992     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
993     return jsValueRef;
994 }
995 
GetHashMapValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)996 Local<JSValueRef> DebuggerApi::GetHashMapValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
997                                                Global<MapRef> internalObjects)
998 {
999     JSHandle<JSAPIHashMap> hashMap(JSNApiHelper::ToJSHandle(value));
1000     JSThread *thread = ecmaVm->GetJSThread();
1001     JSHandle<TaggedHashArray> table(thread, hashMap->GetTable());
1002     uint32_t length = table->GetLength();
1003     uint32_t size = static_cast<uint32_t>(hashMap->GetSize());
1004     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1005     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1006     JSMutableHandle<TaggedQueue> queue(thread, factory->NewTaggedQueue(0));
1007     JSMutableHandle<TaggedNode> node(thread, JSTaggedValue::Undefined());
1008     JSMutableHandle<JSTaggedValue> currentKey(thread, JSTaggedValue::Undefined());
1009     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1010     Local<JSValueRef> jsKey = StringRef::NewFromUtf8(ecmaVm, "key");
1011     Local<JSValueRef> jsValue = StringRef::NewFromUtf8(ecmaVm, "value");
1012     uint32_t pos = 0;
1013     uint32_t index = 0;
1014     while (index < length) {
1015         node.Update(TaggedHashArray::GetCurrentNode(thread, queue, table, index));
1016         if (!node.GetTaggedValue().IsHole()) {
1017             currentKey.Update(node->GetKey());
1018             currentValue.Update(node->GetValue());
1019             Local<ObjectRef> objRef = ObjectRef::New(ecmaVm);
1020             objRef->Set(ecmaVm, jsKey, JSNApiHelper::ToLocal<JSValueRef>(currentKey));
1021             objRef->Set(ecmaVm, jsValue, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1022             AddInternalProperties(ecmaVm, objRef, ArkInternalValueType::Entry, internalObjects);
1023             ArrayRef::SetValueAt(ecmaVm, jsValueRef, pos++, objRef);
1024         }
1025     }
1026     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1027     return jsValueRef;
1028 }
1029 
GetHashSetValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1030 Local<JSValueRef> DebuggerApi::GetHashSetValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1031                                                Global<MapRef> internalObjects)
1032 {
1033     JSHandle<JSAPIHashSet> hashSet(JSNApiHelper::ToJSHandle(value));
1034     JSThread *thread = ecmaVm->GetJSThread();
1035     JSHandle<TaggedHashArray> table(thread, hashSet->GetTable());
1036     uint32_t length = table->GetLength();
1037     uint32_t size = static_cast<uint32_t>(hashSet->GetSize());
1038     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1039     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1040     JSMutableHandle<TaggedQueue> queue(thread, factory->NewTaggedQueue(0));
1041     JSMutableHandle<TaggedNode> node(thread, JSTaggedValue::Undefined());
1042     JSMutableHandle<JSTaggedValue> currentKey(thread, JSTaggedValue::Undefined());
1043     Local<JSValueRef> jsValue = StringRef::NewFromUtf8(ecmaVm, "value");
1044     uint32_t pos = 0;
1045     uint32_t index = 0;
1046     while (index < length) {
1047         node.Update(TaggedHashArray::GetCurrentNode(thread, queue, table, index));
1048         if (!node.GetTaggedValue().IsHole()) {
1049             currentKey.Update(node->GetKey());
1050             if (currentKey->IsECMAObject()) {
1051                 Local<ObjectRef> objRef = ObjectRef::New(ecmaVm);
1052                 objRef->Set(ecmaVm, jsValue, JSNApiHelper::ToLocal<JSValueRef>(currentKey));
1053                 AddInternalProperties(ecmaVm, objRef, ArkInternalValueType::Entry, internalObjects);
1054                 ArrayRef::SetValueAt(ecmaVm, jsValueRef, pos++, objRef);
1055             } else {
1056                 ArrayRef::SetValueAt(ecmaVm, jsValueRef, pos++, JSNApiHelper::ToLocal<JSValueRef>(currentKey));
1057             }
1058         }
1059     }
1060     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1061     return jsValueRef;
1062 }
1063 
GetLightWeightMapValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1064 Local<JSValueRef> DebuggerApi::GetLightWeightMapValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1065                                                       Global<MapRef> internalObjects)
1066 {
1067     JSHandle<JSAPILightWeightMap> lightweightMap(JSNApiHelper::ToJSHandle(value));
1068     uint32_t size  = static_cast<uint32_t>(lightweightMap->GetSize());
1069     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1070     JSThread *thread = ecmaVm->GetJSThread();
1071     JSMutableHandle<TaggedArray> keys(thread, lightweightMap->GetKeys());
1072     JSMutableHandle<TaggedArray> values(thread, lightweightMap->GetValues());
1073     JSMutableHandle<JSTaggedValue> currentKey(thread, JSTaggedValue::Undefined());
1074     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1075     Local<JSValueRef> jsKey = StringRef::NewFromUtf8(ecmaVm, "key");
1076     Local<JSValueRef> jsValue = StringRef::NewFromUtf8(ecmaVm, "value");
1077     uint32_t index = 0;
1078     while (index < size) {
1079         currentKey.Update(keys->Get(index));
1080         currentValue.Update(values->Get(index));
1081         Local<ObjectRef> objRef = ObjectRef::New(ecmaVm);
1082         objRef->Set(ecmaVm, jsKey, JSNApiHelper::ToLocal<JSValueRef>(currentKey));
1083         objRef->Set(ecmaVm, jsValue, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1084         AddInternalProperties(ecmaVm, objRef, ArkInternalValueType::Entry, internalObjects);
1085         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, objRef);
1086     }
1087     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1088     return jsValueRef;
1089 }
1090 
GetLightWeightSetValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1091 Local<JSValueRef> DebuggerApi::GetLightWeightSetValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1092                                                       Global<MapRef> internalObjects)
1093 {
1094     JSHandle<JSAPILightWeightSet> lightWeightSet(JSNApiHelper::ToJSHandle(value));
1095     uint32_t size = static_cast<uint32_t>(lightWeightSet->GetSize());
1096     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1097     JSThread *thread = ecmaVm->GetJSThread();
1098     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1099     Local<JSValueRef> jsValue = StringRef::NewFromUtf8(ecmaVm, "value");
1100     uint32_t index = 0;
1101     while (index < size) {
1102         currentValue.Update(lightWeightSet->GetValueAt(index));
1103         if (currentValue->IsECMAObject()) {
1104             Local<ObjectRef> objRef = ObjectRef::New(ecmaVm);
1105             objRef->Set(ecmaVm, jsValue, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1106             AddInternalProperties(ecmaVm, objRef, ArkInternalValueType::Entry, internalObjects);
1107             ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, objRef);
1108         } else {
1109             ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1110         }
1111     }
1112     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1113     return jsValueRef;
1114 }
1115 
GetLinkedListValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1116 Local<JSValueRef> DebuggerApi::GetLinkedListValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1117                                                   Global<MapRef> internalObjects)
1118 {
1119     JSHandle<JSAPILinkedList> linkedList(JSNApiHelper::ToJSHandle(value));
1120     JSThread *thread = ecmaVm->GetJSThread();
1121     JSHandle<TaggedDoubleList> doubleList(thread, linkedList->GetDoubleList());
1122     uint32_t size = static_cast<uint32_t>(linkedList->Length());
1123     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1124     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1125     int valueNode = TaggedDoubleList::ELEMENTS_START_INDEX;
1126     uint32_t index = 0;
1127     while (index < size) {
1128         valueNode = doubleList->GetNextDataIndex(valueNode);
1129         currentValue.Update(doubleList->GetElement(valueNode));
1130         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1131     }
1132     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1133     return jsValueRef;
1134 }
1135 
GetListValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1136 Local<JSValueRef> DebuggerApi::GetListValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1137                                             Global<MapRef> internalObjects)
1138 {
1139     JSHandle<JSAPIList> list(JSNApiHelper::ToJSHandle(value));
1140     JSThread *thread = ecmaVm->GetJSThread();
1141     JSHandle<TaggedSingleList> singleList(thread, list->GetSingleList());
1142     uint32_t size = static_cast<uint32_t>(list->Length());
1143     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1144     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1145     int valueNode = TaggedDoubleList::ELEMENTS_START_INDEX;
1146     uint32_t index = 0;
1147     while (index < size) {
1148         valueNode = singleList->GetNextDataIndex(valueNode);
1149         currentValue.Update(singleList->GetElement(valueNode));
1150         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1151     }
1152     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1153     return jsValueRef;
1154 }
1155 
GetPlainArrayValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1156 Local<JSValueRef> DebuggerApi::GetPlainArrayValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1157                                                   Global<MapRef> internalObjects)
1158 {
1159     JSHandle<JSAPIPlainArray> plainarray(JSNApiHelper::ToJSHandle(value));
1160     uint32_t size = static_cast<uint32_t>(plainarray->GetSize());
1161     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1162     JSThread *thread = ecmaVm->GetJSThread();
1163     JSHandle<TaggedArray> keyArray(thread, plainarray->GetKeys());
1164     JSHandle<TaggedArray> valueArray(thread, plainarray->GetValues());
1165     JSMutableHandle<JSTaggedValue> currentKey(thread, JSTaggedValue::Undefined());
1166     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1167     Local<JSValueRef> jsKey = StringRef::NewFromUtf8(ecmaVm, "key");
1168     Local<JSValueRef> jsValue = StringRef::NewFromUtf8(ecmaVm, "value");
1169     uint32_t index = 0;
1170     while (index < size) {
1171         currentKey.Update(keyArray->Get(index));
1172         currentValue.Update(valueArray->Get(index));
1173         Local<ObjectRef> objRef = ObjectRef::New(ecmaVm);
1174         objRef->Set(ecmaVm, jsKey, JSNApiHelper::ToLocal<JSValueRef>(currentKey));
1175         objRef->Set(ecmaVm, jsValue, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1176         AddInternalProperties(ecmaVm, objRef, ArkInternalValueType::Entry, internalObjects);
1177         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, objRef);
1178     }
1179     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1180     return jsValueRef;
1181 }
1182 
GetQueueValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1183 Local<JSValueRef> DebuggerApi::GetQueueValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1184                                              Global<MapRef> internalObjects)
1185 {
1186     JSHandle<JSAPIQueue> queue(JSNApiHelper::ToJSHandle(value));
1187     uint32_t size = static_cast<uint32_t>(queue->GetSize());
1188     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1189     JSThread *thread = ecmaVm->GetJSThread();
1190     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1191     uint32_t pos = 0;
1192     uint32_t index = 0;
1193     while (index < size) {
1194         currentValue.Update(queue->Get(thread, pos));
1195         pos = queue->GetNextPosition(pos);
1196         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1197     }
1198     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1199     return jsValueRef;
1200 }
1201 
GetStackValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1202 Local<JSValueRef> DebuggerApi::GetStackValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1203                                              Global<MapRef> internalObjects)
1204 {
1205     JSHandle<JSAPIStack> stack(JSNApiHelper::ToJSHandle(value));
1206     uint32_t size = static_cast<uint32_t>(stack->GetSize() + 1);
1207     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1208     JSThread *thread = ecmaVm->GetJSThread();
1209     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1210     uint32_t index = 0;
1211     while (index < size) {
1212         currentValue.Update(stack->Get(index));
1213         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1214     }
1215     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1216     return jsValueRef;
1217 }
1218 
GetTreeMapValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1219 Local<JSValueRef> DebuggerApi::GetTreeMapValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1220                                                Global<MapRef> internalObjects)
1221 {
1222     JSHandle<JSAPITreeMap> treeMap(JSNApiHelper::ToJSHandle(value));
1223     uint32_t size = static_cast<uint32_t>(treeMap->GetSize());
1224     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1225     JSThread *thread = ecmaVm->GetJSThread();
1226     JSMutableHandle<TaggedTreeMap> iteratedMap(thread, treeMap->GetTreeMap());
1227     uint32_t elements = static_cast<uint32_t>(iteratedMap->NumberOfElements());
1228     JSHandle<TaggedArray> entries = TaggedTreeMap::GetArrayFromMap(thread, iteratedMap);
1229     JSMutableHandle<JSTaggedValue> currentKey(thread, JSTaggedValue::Undefined());
1230     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1231     Local<JSValueRef> jsKey = StringRef::NewFromUtf8(ecmaVm, "key");
1232     Local<JSValueRef> jsValue = StringRef::NewFromUtf8(ecmaVm, "value");
1233     uint32_t index = 0;
1234     while (index < elements) {
1235         int entriesIndex = entries->Get(index).GetInt();
1236         currentKey.Update(iteratedMap->GetKey(entriesIndex));
1237         currentValue.Update(iteratedMap->GetValue(entriesIndex));
1238         Local<ObjectRef> objRef = ObjectRef::New(ecmaVm);
1239         objRef->Set(ecmaVm, jsKey, JSNApiHelper::ToLocal<JSValueRef>(currentKey));
1240         objRef->Set(ecmaVm, jsValue, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1241         AddInternalProperties(ecmaVm, objRef, ArkInternalValueType::Entry, internalObjects);
1242         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, objRef);
1243     }
1244     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1245     return jsValueRef;
1246 }
1247 
GetTreeSetValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1248 Local<JSValueRef> DebuggerApi::GetTreeSetValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1249                                                Global<MapRef> internalObjects)
1250 {
1251     JSHandle<JSAPITreeSet> treeSet(JSNApiHelper::ToJSHandle(value));
1252     JSThread *thread = ecmaVm->GetJSThread();
1253     JSMutableHandle<TaggedTreeSet> iteratedSet(thread, treeSet->GetTreeSet());
1254     uint32_t elements = static_cast<uint32_t>(iteratedSet->NumberOfElements());
1255     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, elements);
1256     JSHandle<TaggedArray> entries = TaggedTreeSet::GetArrayFromSet(thread, iteratedSet);
1257     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1258     Local<JSValueRef> jsValue = StringRef::NewFromUtf8(ecmaVm, "value");
1259     uint32_t index = 0;
1260     while (index < elements) {
1261         int entriesIndex = entries->Get(index).GetInt();
1262         currentValue.Update(iteratedSet->GetKey(entriesIndex));
1263         if (currentValue->IsECMAObject()) {
1264             Local<ObjectRef> objRef = ObjectRef::New(ecmaVm);
1265             objRef->Set(ecmaVm, jsValue, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1266             AddInternalProperties(ecmaVm, objRef, ArkInternalValueType::Entry, internalObjects);
1267             ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, objRef);
1268         } else {
1269             ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1270         }
1271     }
1272     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1273     return jsValueRef;
1274 }
1275 
GetVectorValue(const EcmaVM * ecmaVm,Local<JSValueRef> value,Global<MapRef> internalObjects)1276 Local<JSValueRef> DebuggerApi::GetVectorValue(const EcmaVM *ecmaVm, Local<JSValueRef> value,
1277                                               Global<MapRef> internalObjects)
1278 {
1279     JSHandle<JSAPIVector> vector(JSNApiHelper::ToJSHandle(value));
1280     uint32_t size = static_cast<uint32_t>(vector->GetSize());
1281     Local<JSValueRef> jsValueRef = ArrayRef::New(ecmaVm, size);
1282     JSThread *thread = ecmaVm->GetJSThread();
1283     JSMutableHandle<JSTaggedValue> currentValue(thread, JSTaggedValue::Undefined());
1284     uint32_t index = 0;
1285     while (index < size) {
1286         currentValue.Update(vector->Get(thread, vector, index));
1287         ArrayRef::SetValueAt(ecmaVm, jsValueRef, index++, JSNApiHelper::ToLocal<JSValueRef>(currentValue));
1288     }
1289     AddInternalProperties(ecmaVm, jsValueRef, ArkInternalValueType::Entry, internalObjects);
1290     return jsValueRef;
1291 }
1292 
CheckPromiseQueueSize(const EcmaVM * ecmaVm)1293 bool DebuggerApi::CheckPromiseQueueSize(const EcmaVM *ecmaVm)
1294 {
1295     auto *debuggerMgr = ecmaVm->GetJsDebuggerManager();
1296     uint32_t queueSizeEntry = debuggerMgr->GetPromiseQueueSizeRecordOfTopFrame();
1297     JSThread *thread = ecmaVm->GetJSThread();
1298     EcmaContext *context = thread->GetCurrentEcmaContext();
1299     uint32_t queueSizeCurrent = job::MicroJobQueue::GetPromiseQueueSize(thread, context->GetMicroJobQueue());
1300     return queueSizeEntry == queueSizeCurrent;
1301 }
1302 
CheckIsSendableMethod(const EcmaVM * ecmaVm)1303 bool DebuggerApi::CheckIsSendableMethod(const EcmaVM *ecmaVm)
1304 {
1305     auto *debuggerMgr = ecmaVm->GetJsDebuggerManager();
1306     return debuggerMgr->CheckIsSendableMethod();
1307 }
IsMainThread()1308 bool DebuggerApi::IsMainThread()
1309 {
1310     return JSThread::IsMainThread();
1311 }
1312 
DropLastFrame(const EcmaVM * ecmaVm)1313 void DebuggerApi::DropLastFrame(const EcmaVM *ecmaVm)
1314 {
1315     auto *debuggerMgr = ecmaVm->GetJsDebuggerManager();
1316     debuggerMgr->DropLastFrame();
1317 }
1318 
DebuggerNativeScope(const EcmaVM * vm)1319 DebuggerApi::DebuggerNativeScope::DebuggerNativeScope(const EcmaVM *vm)
1320 {
1321     thread_ = vm->GetAssociatedJSThread();
1322     ecmascript::ThreadState oldState = thread_->GetState();
1323     if (oldState != ecmascript::ThreadState::RUNNING) {
1324         return;
1325     }
1326     oldThreadState_ = static_cast<uint16_t>(oldState);
1327     hasSwitchState_ = true;
1328     thread_->UpdateState(ecmascript::ThreadState::NATIVE);
1329 }
1330 
~DebuggerNativeScope()1331 DebuggerApi::DebuggerNativeScope::~DebuggerNativeScope()
1332 {
1333     if (hasSwitchState_) {
1334         thread_->UpdateState(static_cast<ecmascript::ThreadState>(oldThreadState_));
1335     }
1336 }
1337 
DebuggerManagedScope(const EcmaVM * vm)1338 DebuggerApi::DebuggerManagedScope::DebuggerManagedScope(const EcmaVM *vm)
1339 {
1340     thread_ = vm->GetAssociatedJSThread();
1341     ecmascript::ThreadState oldState = thread_->GetState();
1342     if (oldState == ecmascript::ThreadState::RUNNING) {
1343         return;
1344     }
1345     oldThreadState_ = static_cast<uint16_t>(oldState);
1346     hasSwitchState_ = true;
1347     thread_->UpdateState(ecmascript::ThreadState::RUNNING);
1348 }
1349 
~DebuggerManagedScope()1350 DebuggerApi::DebuggerManagedScope::~DebuggerManagedScope()
1351 {
1352     if (hasSwitchState_) {
1353         thread_->UpdateState(static_cast<ecmascript::ThreadState>(oldThreadState_));
1354     }
1355 }
1356 }  // namespace panda::ecmascript::tooling
1357