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