• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/tooling/backend/debugger_executor.h"
17 
18 #include "ecmascript/tooling/backend/debugger_api.h"
19 #include "ecmascript/tooling/interface/js_debugger_manager.h"
20 #include "libpandabase/utils/logger.h"
21 
22 namespace panda::ecmascript::tooling {
Initialize(const EcmaVM * vm)23 void DebuggerExecutor::Initialize(const EcmaVM *vm)
24 {
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, nullptr));
28     globalObj->Set(vm, StringRef::NewFromUtf8(vm, "debuggerGetValue"), FunctionRef::New(
29         const_cast<panda::EcmaVM*>(vm), DebuggerExecutor::DebuggerGetValue, nullptr));
30 }
31 
DebuggerGetValue(EcmaVM * vm,Local<JSValueRef> thisArg,const Local<JSValueRef> * argv,int32_t length,void * data)32 Local<JSValueRef> DebuggerExecutor::DebuggerGetValue(EcmaVM *vm, [[maybe_unused]] Local<JSValueRef> thisArg,
33                                                      const Local<JSValueRef> *argv,
34                                                      int32_t length, [[maybe_unused]] void *data)
35 {
36     if (length != NUM_ARGS) {
37         return JSValueRef::Undefined(vm);
38     }
39     Local<JSValueRef> name = argv[0];
40     if (!name->IsString()) {
41         return JSValueRef::Undefined(vm);
42     }
43     Local<JSValueRef> isThrow = argv[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() && !value->IsException()) {
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 JSValueRef::Exception(vm);
61 }
62 
DebuggerSetValue(EcmaVM * vm,Local<JSValueRef> thisArg,const Local<JSValueRef> * argv,int32_t length,void * data)63 Local<JSValueRef> DebuggerExecutor::DebuggerSetValue(EcmaVM *vm, [[maybe_unused]] Local<JSValueRef> thisArg,
64                                                      const Local<JSValueRef> *argv,
65                                                      int32_t length, [[maybe_unused]] void *data)
66 {
67     if (length != NUM_ARGS) {
68         return JSValueRef::Undefined(vm);
69     }
70     Local<JSValueRef> name = argv[0];
71     if (!name->IsString()) {
72         return JSValueRef::Undefined(vm);
73     }
74     Local<JSValueRef> value = argv[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 JSValueRef::Exception(vm);
86 }
87 
GetValue(const EcmaVM * vm,const InterpretedFrameHandler * frameHandler,Local<StringRef> name)88 Local<JSValueRef> DebuggerExecutor::GetValue(const EcmaVM *vm, const InterpretedFrameHandler *frameHandler,
89                                              Local<StringRef> name)
90 {
91     Local<JSValueRef> value;
92     value = GetLocalValue(vm, frameHandler, name);
93     if (!value.IsEmpty()) {
94         return value;
95     }
96     value = GetLexicalValue(vm, frameHandler, name);
97     if (!value.IsEmpty()) {
98         return value;
99     }
100     value = GetGlobalValue(vm, name);
101     if (!value.IsEmpty() && !value->IsException()) {
102         return value;
103     }
104 
105     return Local<JSValueRef>();
106 }
107 
SetValue(const EcmaVM * vm,InterpretedFrameHandler * frameHandler,Local<StringRef> name,Local<JSValueRef> value)108 bool DebuggerExecutor::SetValue(const EcmaVM *vm, InterpretedFrameHandler *frameHandler,
109                                 Local<StringRef> name, Local<JSValueRef> value)
110 {
111     if (SetLocalValue(vm, frameHandler, name, value)) {
112         return true;
113     }
114     if (SetLexicalValue(vm, frameHandler, name, value)) {
115         return true;
116     }
117     if (SetGlobalValue(vm, name, value)) {
118         return true;
119     }
120 
121     return false;
122 }
123 
ThrowException(const EcmaVM * vm,const std::string & error)124 void DebuggerExecutor::ThrowException(const EcmaVM *vm, const std::string &error)
125 {
126     Local<StringRef> msg = StringRef::NewFromUtf8(vm, error.c_str());
127     Local<JSValueRef> exception = Exception::ReferenceError(vm, msg);
128     JSNApi::ThrowException(vm, exception);
129 }
130 
GetLocalValue(const EcmaVM * vm,const InterpretedFrameHandler * frameHandler,Local<StringRef> name)131 Local<JSValueRef> DebuggerExecutor::GetLocalValue(const EcmaVM *vm, const InterpretedFrameHandler *frameHandler,
132                                                   Local<StringRef> name)
133 {
134     Local<JSValueRef> result;
135 
136     int32_t index = DebuggerApi::GetVregIndex(frameHandler, name->ToString());
137     if (index == -1) {
138         return result;
139     }
140 
141     result = DebuggerApi::GetVRegValue(vm, frameHandler, index);
142     return result;
143 }
144 
SetLocalValue(const EcmaVM * vm,InterpretedFrameHandler * frameHandler,Local<StringRef> name,Local<JSValueRef> value)145 bool DebuggerExecutor::SetLocalValue(const EcmaVM *vm, InterpretedFrameHandler *frameHandler,
146                                      Local<StringRef> name, Local<JSValueRef> value)
147 {
148     std::string varName = name->ToString();
149     int32_t index = DebuggerApi::GetVregIndex(frameHandler, varName);
150     if (index == -1) {
151         return false;
152     }
153 
154     DebuggerApi::SetVRegValue(frameHandler, index, value);
155     vm->GetJsDebuggerManager()->NotifyLocalScopeUpdated(varName, value);
156     return true;
157 }
158 
GetLexicalValue(const EcmaVM * vm,const InterpretedFrameHandler * frameHandler,Local<StringRef> name)159 Local<JSValueRef> DebuggerExecutor::GetLexicalValue(const EcmaVM *vm, const InterpretedFrameHandler *frameHandler,
160                                                     Local<StringRef> name)
161 {
162     Local<JSValueRef> result;
163 
164     auto [level, slot] = DebuggerApi::GetLevelSlot(frameHandler, name->ToString());
165     if (level == -1) {
166         return result;
167     }
168 
169     result = DebuggerApi::GetProperties(vm, frameHandler, level, slot);
170     return result;
171 }
172 
SetLexicalValue(const EcmaVM * vm,const InterpretedFrameHandler * frameHandler,Local<StringRef> name,Local<JSValueRef> value)173 bool DebuggerExecutor::SetLexicalValue(const EcmaVM *vm, const InterpretedFrameHandler *frameHandler,
174                                        Local<StringRef> name, Local<JSValueRef> value)
175 {
176     std::string varName = name->ToString();
177     auto [level, slot] = DebuggerApi::GetLevelSlot(frameHandler, varName);
178     if (level == -1) {
179         return false;
180     }
181 
182     DebuggerApi::SetProperties(vm, frameHandler, level, slot, value);
183     vm->GetJsDebuggerManager()->NotifyLocalScopeUpdated(varName, value);
184     return true;
185 }
186 
GetGlobalValue(const EcmaVM * vm,Local<StringRef> name)187 Local<JSValueRef> DebuggerExecutor::GetGlobalValue(const EcmaVM *vm, Local<StringRef> name)
188 {
189     return DebuggerApi::GetGlobalValue(vm, name);
190 }
191 
SetGlobalValue(const EcmaVM * vm,Local<StringRef> name,Local<JSValueRef> value)192 bool DebuggerExecutor::SetGlobalValue(const EcmaVM *vm, Local<StringRef> name, Local<JSValueRef> value)
193 {
194     return DebuggerApi::SetGlobalValue(vm, name, value);
195 }
196 }  // namespace panda::ecmascript::tooling
197