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> ¤tModule, 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> ¤tModule,
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> ¤tModule)
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> ¤tModule, 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> ¤tModule,
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> ¤tModule,
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> ¤tModule,
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> ¤tModule)
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> ¤tModule, 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> ¤tModule)
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> ¤tModule)
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