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