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