• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "backend/debugger_executor.h"
17 
18 #include "ecmascript/debugger/debugger_api.h"
19 #include "ecmascript/debugger/js_debugger_manager.h"
20 
21 namespace panda::ecmascript::tooling {
Initialize(const EcmaVM * vm)22 void DebuggerExecutor::Initialize(const EcmaVM *vm)
23 {
24     [[maybe_unused]] EcmaHandleScope handleScope(vm->GetJSThread());
25     Local<ObjectRef> globalObj = JSNApi::GetGlobalObject(vm);
26     globalObj->Set(vm, StringRef::NewFromUtf8(vm, "debuggerSetValue"), FunctionRef::New(
27         const_cast<panda::EcmaVM*>(vm), DebuggerExecutor::DebuggerSetValue));
28     globalObj->Set(vm, StringRef::NewFromUtf8(vm, "debuggerGetValue"), FunctionRef::New(
29         const_cast<panda::EcmaVM*>(vm), DebuggerExecutor::DebuggerGetValue));
30 }
31 
DebuggerGetValue(JsiRuntimeCallInfo * runtimeCallInfo)32 Local<JSValueRef> DebuggerExecutor::DebuggerGetValue(JsiRuntimeCallInfo *runtimeCallInfo)
33 {
34     EcmaVM *vm = runtimeCallInfo->GetVM();
35     uint32_t argc = runtimeCallInfo->GetArgsNumber();
36     if (argc != NUM_ARGS) {
37         return JSValueRef::Undefined(vm);
38     }
39     Local<JSValueRef> name = runtimeCallInfo->GetCallArgRef(0);
40     if (!name->IsString()) {
41         return JSValueRef::Undefined(vm);
42     }
43     Local<JSValueRef> isThrow = runtimeCallInfo->GetCallArgRef(1);
44 
45     auto &frameHandler = vm->GetJsDebuggerManager()->GetEvalFrameHandler();
46     ASSERT(frameHandler);
47 
48     Local<JSValueRef> value = GetValue(vm, frameHandler.get(), Local<StringRef>(name));
49     if (!value.IsEmpty()) {
50         return value;
51     }
52 
53     if (!isThrow->ToBoolean(vm)->Value()) {
54         DebuggerApi::ClearException(vm);
55         return JSValueRef::Undefined(vm);
56     }
57 
58     std::string varName = Local<StringRef>(name)->ToString();
59     ThrowException(vm, varName + " is not defined");
60     return Local<JSValueRef>();
61 }
62 
DebuggerSetValue(JsiRuntimeCallInfo * runtimeCallInfo)63 Local<JSValueRef> DebuggerExecutor::DebuggerSetValue(JsiRuntimeCallInfo *runtimeCallInfo)
64 {
65     EcmaVM *vm = runtimeCallInfo->GetVM();
66     uint32_t argc = runtimeCallInfo->GetArgsNumber();
67     if (argc != NUM_ARGS) {
68         return JSValueRef::Undefined(vm);
69     }
70     Local<JSValueRef> name = runtimeCallInfo->GetCallArgRef(0);
71     if (!name->IsString()) {
72         return JSValueRef::Undefined(vm);
73     }
74     Local<JSValueRef> value = runtimeCallInfo->GetCallArgRef(1);
75 
76     auto &frameHandler = vm->GetJsDebuggerManager()->GetEvalFrameHandler();
77     ASSERT(frameHandler);
78 
79     if (SetValue(vm, frameHandler.get(), Local<StringRef>(name), value)) {
80         return value;
81     }
82 
83     std::string varName = StringRef::Cast(*name)->ToString();
84     ThrowException(vm, varName + " is not defined");
85     return Local<JSValueRef>();
86 }
87 
GetValue(const EcmaVM * vm,const FrameHandler * frameHandler,Local<StringRef> name)88 Local<JSValueRef> DebuggerExecutor::GetValue(const EcmaVM *vm, const FrameHandler *frameHandler, Local<StringRef> name)
89 {
90     Local<JSValueRef> value;
91     value = GetLocalValue(vm, frameHandler, name);
92     if (!value.IsEmpty()) {
93         return value;
94     }
95     value = GetLexicalValue(vm, frameHandler, name);
96     if (!value.IsEmpty()) {
97         return value;
98     }
99     value = GetModuleValue(vm, frameHandler, name);
100     if (!value.IsEmpty()) {
101         return value;
102     }
103     value = GetGlobalValue(vm, name);
104     if (!value.IsEmpty()) {
105         return value;
106     }
107 
108     return Local<JSValueRef>();
109 }
110 
SetValue(const EcmaVM * vm,FrameHandler * frameHandler,Local<StringRef> name,Local<JSValueRef> value)111 bool DebuggerExecutor::SetValue(const EcmaVM *vm, FrameHandler *frameHandler,
112                                 Local<StringRef> name, Local<JSValueRef> value)
113 {
114     if (SetLocalValue(vm, frameHandler, name, value)) {
115         return true;
116     }
117     if (SetLexicalValue(vm, frameHandler, name, value)) {
118         return true;
119     }
120     if (SetModuleValue(vm, frameHandler, name, value)) {
121         return true;
122     }
123     if (SetGlobalValue(vm, name, value)) {
124         return true;
125     }
126 
127     return false;
128 }
129 
ThrowException(const EcmaVM * vm,const std::string & error)130 void DebuggerExecutor::ThrowException(const EcmaVM *vm, const std::string &error)
131 {
132     Local<StringRef> msg = StringRef::NewFromUtf8(vm, error.c_str());
133     Local<JSValueRef> exception = Exception::ReferenceError(vm, msg);
134     JSNApi::ThrowException(vm, exception);
135 }
136 
GetLocalValue(const EcmaVM * vm,const FrameHandler * frameHandler,Local<StringRef> name)137 Local<JSValueRef> DebuggerExecutor::GetLocalValue(const EcmaVM *vm, const FrameHandler *frameHandler,
138                                                   Local<StringRef> name)
139 {
140     Local<JSValueRef> result;
141 
142     int32_t index = DebuggerApi::GetVregIndex(frameHandler, name->ToString());
143     if (index == -1) {
144         return result;
145     }
146 
147     result = DebuggerApi::GetVRegValue(vm, frameHandler, index);
148     return result;
149 }
150 
SetLocalValue(const EcmaVM * vm,FrameHandler * frameHandler,Local<StringRef> name,Local<JSValueRef> value)151 bool DebuggerExecutor::SetLocalValue(const EcmaVM *vm, FrameHandler *frameHandler,
152                                      Local<StringRef> name, Local<JSValueRef> value)
153 {
154     std::string varName = name->ToString();
155     int32_t index = DebuggerApi::GetVregIndex(frameHandler, varName);
156     if (index == -1) {
157         return false;
158     }
159 
160     DebuggerApi::SetVRegValue(frameHandler, index, value);
161     vm->GetJsDebuggerManager()->NotifyLocalScopeUpdated(varName, value);
162     return true;
163 }
164 
GetLexicalValue(const EcmaVM * vm,const FrameHandler * frameHandler,Local<StringRef> name)165 Local<JSValueRef> DebuggerExecutor::GetLexicalValue(const EcmaVM *vm, const FrameHandler *frameHandler,
166                                                     Local<StringRef> name)
167 {
168     Local<JSValueRef> result;
169 
170     auto [level, slot] = DebuggerApi::GetLevelSlot(frameHandler, name->ToString());
171     if (level == -1) {
172         return result;
173     }
174 
175     result = DebuggerApi::GetProperties(vm, frameHandler, level, slot);
176     return result;
177 }
178 
SetLexicalValue(const EcmaVM * vm,const FrameHandler * frameHandler,Local<StringRef> name,Local<JSValueRef> value)179 bool DebuggerExecutor::SetLexicalValue(const EcmaVM *vm, const FrameHandler *frameHandler,
180                                        Local<StringRef> name, Local<JSValueRef> value)
181 {
182     std::string varName = name->ToString();
183     auto [level, slot] = DebuggerApi::GetLevelSlot(frameHandler, varName);
184     if (level == -1) {
185         return false;
186     }
187 
188     DebuggerApi::SetProperties(vm, frameHandler, level, slot, value);
189     vm->GetJsDebuggerManager()->NotifyLocalScopeUpdated(varName, value);
190     return true;
191 }
192 
GetGlobalValue(const EcmaVM * vm,Local<StringRef> name)193 Local<JSValueRef> DebuggerExecutor::GetGlobalValue(const EcmaVM *vm, Local<StringRef> name)
194 {
195     return DebuggerApi::GetGlobalValue(vm, name);
196 }
197 
SetGlobalValue(const EcmaVM * vm,Local<StringRef> name,Local<JSValueRef> value)198 bool DebuggerExecutor::SetGlobalValue(const EcmaVM *vm, Local<StringRef> name, Local<JSValueRef> value)
199 {
200     return DebuggerApi::SetGlobalValue(vm, name, value);
201 }
202 
GetModuleValue(const EcmaVM * vm,const FrameHandler * frameHandler,Local<StringRef> name)203 Local<JSValueRef> DebuggerExecutor::GetModuleValue(const EcmaVM *vm, const FrameHandler *frameHandler,
204                                                    Local<StringRef> name)
205 {
206     Local<JSValueRef> result;
207     std::string varName = name->ToString();
208     Method *method = DebuggerApi::GetMethod(frameHandler);
209     const JSPandaFile *jsPandaFile = method->GetJSPandaFile();
210     if (jsPandaFile != nullptr && (jsPandaFile->IsBundlePack() || !jsPandaFile->IsNewVersion())) {
211         return result;
212     }
213     JSThread *thread = vm->GetJSThread();
214     JSHandle<JSTaggedValue> currentModule(thread, DebuggerApi::GetCurrentModule(vm));
215     if (currentModule->IsSourceTextModule()) {
216         result = DebuggerApi::GetModuleValue(vm, currentModule, varName);
217     }
218     return result;
219 }
220 
SetModuleValue(const EcmaVM * vm,const FrameHandler * frameHandler,Local<StringRef> name,Local<JSValueRef> value)221 bool DebuggerExecutor::SetModuleValue(const EcmaVM *vm, const FrameHandler *frameHandler,
222                                       Local<StringRef> name, Local<JSValueRef> value)
223 {
224     std::string varName = name->ToString();
225     Method *method = DebuggerApi::GetMethod(frameHandler);
226     const JSPandaFile *jsPandaFile = method->GetJSPandaFile();
227     if (jsPandaFile != nullptr && (jsPandaFile->IsBundlePack() || !jsPandaFile->IsNewVersion())) {
228         return false;
229     }
230     JSThread *thread = vm->GetJSThread();
231     JSHandle<JSTaggedValue> currentModule(thread, DebuggerApi::GetCurrentModule(vm));
232     if (currentModule->IsSourceTextModule()) {
233         DebuggerApi::SetModuleValue(vm, currentModule, varName, value);
234     }
235     return true;
236 }
237 }  // namespace panda::ecmascript::tooling
238