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