1 /*
2  * Copyright (c) 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 #ifndef ECMASCRIPT_TOOLING_TEST_UTILS_TESTCASES_JS_VARIABLE_SECOND_TEST_H
17 #define ECMASCRIPT_TOOLING_TEST_UTILS_TESTCASES_JS_VARIABLE_SECOND_TEST_H
18 
19 #include "test/utils/test_util.h"
20 
21 namespace panda::ecmascript::tooling::test {
22 class JsVariableSecondTest : public TestEvents {
23 public:
JsVariableSecondTest()24     JsVariableSecondTest()
25     {
26         breakpoint = [this](const JSPtLocation &location) {
27             ASSERT_TRUE(location.GetMethodId().IsValid());
28             ASSERT_LOCATION_EQ(location, location_);
29             ++breakpointCounter_;
30             debugger_->NotifyPaused(location, PauseReason::INSTRUMENTATION);
31             TestUtil::SuspendUntilContinue(DebugEvent::BREAKPOINT, location);
32             return true;
33         };
34 
35         loadModule = [this](std::string_view moduleName) {
36             std::string panfaFile = DEBUGGER_ABC_DIR "variable_second.abc";
37             std::string sourceFile = DEBUGGER_JS_DIR "variable_second.js";
38             static_cast<JsVariableSecondTestChannel *>(channel_)->Initial(vm_, runtime_);
39             runtime_->Enable();
40             // 166: breakpointer line
41             int32_t line = 166;
42             location_ = TestUtil::GetLocation(sourceFile.c_str(), line, 0, panfaFile.c_str());
43             ASSERT_TRUE(location_.GetMethodId().IsValid());
44             TestUtil::SuspendUntilContinue(DebugEvent::LOAD_MODULE);
45             ASSERT_EQ(moduleName, panfaFile);
46             ASSERT_TRUE(debugger_->NotifyScriptParsed(0, panfaFile));
47             auto condFuncRef = FunctionRef::Undefined(vm_);
48             auto ret = debugInterface_->SetBreakpoint(location_, condFuncRef);
49             ASSERT_TRUE(ret);
50             return true;
51         };
52 
53         scenario = [this]() {
54             TestUtil::WaitForLoadModule();
55             TestUtil::Continue();
56             TestUtil::WaitForBreakpoint(location_);
57             TestUtil::Continue();
58             auto ret = debugInterface_->RemoveBreakpoint(location_);
59             ASSERT_TRUE(ret);
60             ASSERT_EXITED();
61             return true;
62         };
63 
64         vmDeath = [this]() {
65             ASSERT_EQ(breakpointCounter_, 1U);  // 1: break point counter
66             return true;
67         };
68 
69         channel_ = new JsVariableSecondTestChannel();
70     }
71 
72     std::pair<std::string, std::string> GetEntryPoint() override
73     {
74         std::string panfaFile = DEBUGGER_ABC_DIR "variable_second.abc";
75         return {panfaFile, entryPoint_};
76     }
~JsVariableSecondTest()77     ~JsVariableSecondTest()
78     {
79         delete channel_;
80         channel_ = nullptr;
81     }
82 
83 private:
84     class JsVariableSecondTestChannel : public TestChannel {
85     public:
86         JsVariableSecondTestChannel() = default;
87         ~JsVariableSecondTestChannel() = default;
Initial(const EcmaVM *vm, RuntimeImpl *runtime)88         void Initial(const EcmaVM *vm, RuntimeImpl *runtime)
89         {
90             vm_ = vm;
91             runtime_ = runtime;
92         }
93 
94         void SendNotification(const PtBaseEvents &events) override
95         {
96             const static std::vector<std::function<bool(const PtBaseEvents &events)>> eventList = {
97                 [](const PtBaseEvents &events) -> bool {
98                     std::string sourceFile = DEBUGGER_JS_DIR "variable_second.js";
99                     auto parsed = static_cast<const ScriptParsed *>(&events);
100                     std::string str = parsed->ToJson()->Stringify();
101                     std::cout << "JsVariableSecondTestChannel: SendNotification 0:\n" << str << std::endl;
102 
103                     ASSERT_EQ(parsed->GetName(), "Debugger.scriptParsed");
104                     ASSERT_EQ(parsed->GetUrl(), sourceFile);
105                     return true;
106                 },
107                 [this](const PtBaseEvents &events) -> bool {
108                     auto paused = static_cast<const Paused *>(&events);
109                     std::string str = paused->ToJson()->Stringify();
110                     std::cout << "JsVariableSecondTestChannel: SendNotification 1:\n" << str << std::endl;
111 
112                     ASSERT_EQ(paused->GetName(), "Debugger.paused");
113                     auto frame = paused->GetCallFrames()->at(0).get();
114                     ASSERT_EQ(frame->GetFunctionName(), "foo");
115                     auto scopes = frame->GetScopeChain();
116                     ASSERT_EQ(scopes->size(), 2U);  // 2: contain local and global
117                     for (uint32_t i = 0; i < scopes->size(); i++) {
118                         auto scope = scopes->at(i).get();
119                         if (scope->GetType() != Scope::Type::Local()) {
120                             continue;
121                         }
122                         auto localId = scope->GetObject()->GetObjectId();
123                         GetPropertiesParams params;
124                         params.SetObjectId(localId).SetOwnProperties(true);
125                         std::vector<std::unique_ptr<PropertyDescriptor>> outPropertyDesc;
126                         runtime_->GetProperties(params, &outPropertyDesc, {}, {}, {});
127                         for (const auto &property : outPropertyDesc) {
128                             std::cout << "=====================================" << std::endl;
129                             std::cout << property->GetName() << std::endl;
130                             auto value = property->GetValue();
131                             std::vector<std::string> infos;
132                             PushValueInfo(value, infos);
133                             if (value->GetType() == RemoteObject::TypeName::Object) {
134                                 std::vector<std::unique_ptr<PropertyDescriptor>> outPropertyDescInner;
135                                 ASSERT_TRUE(value->HasObjectId());
136                                 params.SetObjectId(value->GetObjectId()).SetOwnProperties(true);
137                                 runtime_->GetProperties(params, &outPropertyDescInner, {}, {}, {});
138                                 if (outPropertyDescInner.size() == 0) {
139                                     infos.push_back("none");
140                                 }
141                                 for (const auto &propertyInner : outPropertyDescInner) {
142                                     std::cout << "###########################################" << std::endl;
143                                     std::cout << propertyInner->GetName() << std::endl;
144                                     infos.push_back(propertyInner->GetName());
145                                     auto innerValue = propertyInner->GetValue();
146                                     PushValueInfo(innerValue, infos);
147                                 }
148                             }
149                             ASSERT_EQ(infos.size(), variableMap_.at(property->GetName()).size());
150                             for (uint32_t j = 0; j < infos.size(); j++) {
151                                 ASSERT_EQ(infos[j], variableMap_.at(property->GetName())[j]);
152                             }
153                         }
154                     }
155                     return true;
156                 }
157             };
158 
159             ASSERT_TRUE(eventList[index_](events));
160             index_++;
161         }
162 
163     private:
164         NO_COPY_SEMANTIC(JsVariableSecondTestChannel);
165         NO_MOVE_SEMANTIC(JsVariableSecondTestChannel);
166 
PushValueInfo(RemoteObject *value, std::vector<std::string> &infos)167         void PushValueInfo(RemoteObject *value, std::vector<std::string> &infos)
168         {
169             std::cout << "type: " << value->GetType() << std::endl;
170             infos.push_back(value->GetType());
171             if (value->HasObjectId()) {
172                 std::cout << "id: " << value->GetObjectId() << std::endl;
173             }
174             if (value->HasSubType()) {
175                 std::cout << "sub type: " << value->GetSubType() << std::endl;
176                 infos.push_back(value->GetSubType());
177             }
178             if (value->HasClassName()) {
179                 std::cout << "class name: " << value->GetClassName() << std::endl;
180                 infos.push_back(value->GetClassName());
181             }
182             if (value->HasDescription()) {
183                 std::cout << "desc: " << value->GetDescription() << std::endl;
184                 infos.push_back(value->GetDescription());
185             }
186             if (value->HasValue()) {
187                 std::cout << "type: " <<
188                     value->GetValue()->Typeof(vm_)->ToString(vm_) << std::endl;
189                 std::cout << "tostring: " <<
190                     value->GetValue()->ToString(vm_)->ToString(vm_) << std::endl;
191                 infos.push_back(value->GetValue()->ToString(vm_)->ToString(vm_));
192             }
193         }
194 
195         /*
196         * Expect map type: map<name, value list>
197         * value list (optional):
198         *    type
199         *    subType
200         *    className
201         *    description
202         *    value tostring
203         *
204         * if is object value, will push back key and value.
205         *
206         * for example:
207         * var abc = 1
208         *     { "abc", { "number", "1", "1" } }
209         * var obj = { "key": "2" }
210         *     { "obj0", { "object", "Object", "Object", "[object Object]", "key", "string", "2", "2" } }
211         */
212         const std::map<std::string, std::vector<std::string>> variableMap_ = {
213             { "nop", { "undefined" } },
214             { "foo", { "function", "Function", "function foo( { [js code] }",
215                        "Cannot get source code of funtion"} },
216             { "string0", { "string", "helloworld", "helloworld" } },
217             { "boolean0", { "object", "Object", "Boolean{[[PrimitiveValue]]: false}", "false", "[[PrimitiveValue]]",
218                             "boolean", "false", "false" } },
219             { "number0", { "number", "1", "1" } },
220             { "obj0", { "object", "Object", "Object", "[object Object]",
221                         "key0", "string", "value0", "value0",
222                         "key1", "number", "100", "100" } },
223             { "arraybuffer0", { "object", "arraybuffer", "Arraybuffer", "Arraybuffer(24)", "[object ArrayBuffer]",
224                                 "[[Int8Array]]", "object", "Object", "Int8Array(24)",
225                                 "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "[[Uint8Array]]", "object",
226                                 "Object", "Uint8Array(24)", "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
227                                 "[[Uint8ClampedArray]]", "object", "Object", "Uint8ClampedArray",
228                                 "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "[[Int16Array]]", "object",
229                                 "Object", "Int16Array(12)", "0,0,0,0,0,0,0,0,0,0,0,0", "[[Uint16Array]]", "object",
230                                 "Object", "Uint16Array", "0,0,0,0,0,0,0,0,0,0,0,0",
231                                 "[[Int32Array]]", "object", "Object",
232                                 "Int32Array(6)", "0,0,0,0,0,0", "[[Uint32Array]]", "object", "Object", "Uint32Array",
233                                 "0,0,0,0,0,0", "[[Float32Array]]", "object", "Object", "Float32Array", "0,0,0,0,0,0",
234                                 "[[Float64Array]]", "object", "Object", "Float64Array", "0,0,0", "[[BigInt64Array]]",
235                                 "object", "Object", "BigInt64Array", "0,0,0", "[[BigUint64Array]]", "object", "Object",
236                                 "BigUint64Array", "0,0,0" } },
237             { "function0", { "function", "Function", "function function0( { [js code] }",
238                              "Cannot get source code of funtion" } },
239             { "generator0", { "function", "Generator", "function* generator0( { [js code] }",
240                               "Cannot get source code of funtion" } },
241             { "map0", { "object", "map", "Map", "Map(0)", "[object Map]", "size", "number", "0", "0", "[[Entries]]",
242                         "object", "array", "Array", "Array(0)", "" } },
243             { "set0", { "object", "set", "Set", "Set(0)", "[object Set]", "size", "number", "0", "0", "[[Entries]]",
244                         "object", "array", "Array", "Array(0)", "" } },
245             { "undefined0", { "undefined" } },
246             { "array0", { "object", "array", "Array", "Array(2)", "Apple,Banana", "0", "string", "Apple", "Apple",
247                           "1", "string", "Banana", "Banana", "length", "number", "2", "2" } },
248             { "regexp0", { "object", "regexp", "RegExp", "/^\\d+\\.\\d+$/i", "/^\\d+\\.\\d+$/i", "global", "boolean",
249                            "false", "false", "ignoreCase", "boolean", "true", "true", "multiline", "boolean", "false",
250                            "false", "dotAll", "boolean", "false", "false", "hasIndices", "boolean", "false", "false",
251                            "unicode", "boolean", "false", "false", "sticky", "boolean", "false", "false", "flags",
252                            "string", "i", "i", "source", "string", "^\\d+\\.\\d+$", "^\\d+\\.\\d+$", "lastIndex",
253                            "number", "0", "0" } },
254             { "uint8array0", { "object", "Object", "Uint8Array(24)",
255                                "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "0", "number", "0", "0",
256                                "1", "number", "0", "0", "2", "number", "0", "0", "3", "number", "0", "0", "4",
257                                "number", "0", "0", "5", "number", "0", "0", "6", "number", "0", "0", "7",
258                                "number", "0", "0", "8", "number", "0", "0", "9", "number", "0", "0", "10",
259                                "number", "0", "0", "11", "number", "0", "0", "12", "number", "0", "0", "13",
260                                "number", "0", "0", "14", "number", "0", "0", "15", "number", "0", "0", "16",
261                                "number", "0", "0", "17", "number", "0", "0", "18", "number", "0", "0", "19",
262                                "number", "0", "0", "20", "number", "0", "0", "21", "number", "0", "0", "22",
263                                "number", "0", "0", "23", "number", "0", "0" } },
264             { "dataview0", { "object", "dataview", "Dataview", "DataView(24)", "[object DataView]", "buffer",
265                              "object", "arraybuffer", "Arraybuffer", "Arraybuffer(24)", "[object ArrayBuffer]",
266                              "byteLength", "number", "24", "24", "byteOffset", "number", "0", "0" } },
267             { "bigint0", { "bigint", "999n", "999" } },
268             { "typedarray0", { "object", "Object", "Uint8Array(0)", "", "none" } },
269             { "sharedarraybuffer0", { "object", "Object", "SharedArrayBuffer(32)", "[object SharedArrayBuffer]",
270                                       "[[Int8Array]]", "object", "Object", "Int8Array(32)",
271                                       "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
272                                       "[[Uint8Array]]", "object", "Object", "Uint8Array(32)",
273                                       "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
274                                       "[[Int16Array]]", "object", "Object", "Int16Array(16)",
275                                       "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "[[Int32Array]]", "object", "Object",
276                                       "Int32Array(8)", "0,0,0,0,0,0,0,0", "[[ArrayBufferByteLength]]", "number", "32",
277                                       "32", "byteLength", "number", "32", "32" } },
278             { "weakref0", { "object", "Object", "WeakRef {}", "[object WeakRef]", "none" } },
279             { "iterator0", { "function", "Function", "function [Symbol.iterator]( { [native code] }",
280                              "function [Symbol.iterator]() { [native code] }" } },
281             { "array1", { "object", "array", "Array", "Array(3)", "banana,apple,peach", "0", "string", "banana",
282                           "banana", "1", "string", "apple", "apple", "2", "string", "peach", "peach", "length",
283                           "number", "3", "3" } },
284             { "array2", { "object", "array", "Array", "Array(3)", "banana,apple,peach", "0", "string", "banana",
285                           "banana", "1", "string", "apple", "apple", "2", "string", "peach", "peach", "length",
286                           "number", "3", "3" } },
287             { "array3", { "object", "array", "Array", "Array(1)", "apple", "0", "string", "apple", "apple",
288                           "length", "number", "1", "1" } },
289             { "array4", { "string", "banana", "banana" } },
290             { "array5", { "object", "array", "Array", "Array(1)", "", "length", "number", "1", "1" } },
291             { "array6", { "object", "array", "Array", "Array(1)", "helloworld", "0", "string", "helloworld",
292                           "helloworld", "length", "number", "1", "1" } },
293             { "array7", { "object", "array", "Array", "Array(1)", "false", "0", "object", "Object",
294                           "Boolean{[[PrimitiveValue]]: false}", "false", "length", "number", "1", "1" } },
295             { "array8", { "object", "array", "Array", "Array(1)", "[object Object]", "0", "object", "Object",
296                           "Object", "[object Object]", "length", "number", "1", "1" } },
297             { "array9", { "object", "array", "Array", "Array(1)", "Cannot get source code of funtion", "0", "function",
298                           "Function", "function function0( { [js code] }", "Cannot get source code of funtion",
299                           "length", "number", "1", "1" } },
300             { "array10", { "object", "array", "Array", "Array(1)", "[object Map]", "0", "object", "map", "Map",
301                            "Map(0)", "[object Map]", "length", "number", "1", "1" } },
302             { "array11", { "object", "array", "Array", "Array(1)", "[object Set]", "0", "object", "set", "Set",
303                            "Set(0)", "[object Set]", "length", "number", "1", "1" } },
304             { "array12", { "object", "array", "Array", "Array(1)", "", "0", "undefined", "length", "number",
305                            "1", "1" } },
306             { "array13", { "object", "array", "Array", "Array(1)", "Apple,Banana", "0", "object", "array", "Array",
307                            "Array(2)", "Apple,Banana", "length", "number", "1", "1" } },
308             { "array14", { "object", "array", "Array", "Array(1)", "Cannot get source code of funtion", "0",
309                            "function", "Generator", "function* generator0( { [js code] }",
310                            "Cannot get source code of funtion", "length", "number", "1", "1" } },
311             { "array15", { "object", "array", "Array", "Array(1)", "/^\\d+\\.\\d+$/i", "0", "object", "regexp",
312                            "RegExp", "/^\\d+\\.\\d+$/i", "/^\\d+\\.\\d+$/i", "length", "number", "1", "1" } },
313             { "array16", { "object", "array", "Array", "Array(1)", "[object ArrayBuffer]", "0", "object",
314                            "arraybuffer", "Arraybuffer", "Arraybuffer(24)", "[object ArrayBuffer]",
315                            "length", "number", "1", "1" } },
316             { "array17", { "object", "array", "Array", "Array(1)",
317                            "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "0", "object", "Object",
318                            "Uint8Array(24)", "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
319                            "length", "number", "1", "1" } },
320             { "array18", { "object", "array", "Array", "Array(1)", "[object DataView]", "0", "object", "dataview",
321                            "Dataview", "DataView(24)", "[object DataView]", "length", "number", "1", "1" } },
322             { "array19", { "object", "array", "Array", "Array(1)", "999", "0", "bigint", "999n", "999", "length",
323                            "number", "1", "1" } },
324             { "array20", { "object", "array", "Array", "Array(3)", "banana,apple,peach", "0", "string", "banana",
325                            "banana", "1", "string", "apple", "apple", "2", "string", "peach", "peach", "length",
326                            "number", "3", "3" } },
327             { "array21", { "string", "banana", "banana" } },
328             { "typedarray1", { "object", "Object", "Int8Array(0)", "", "none" } },
329             { "typedarray2", { "object", "Object", "Uint8ClampedArray", "", "none" } },
330             { "typedarray3", { "object", "Object", "Int16Array(0)", "", "none" } },
331             { "typedarray4", { "object", "Object", "Uint16Array", "", "none" } },
332             { "typedarray5", { "object", "Object", "Int32Array(0)", "", "none" } },
333             { "typedarray6", { "object", "Object", "Uint32Array", "", "none" } },
334             { "typedarray7", { "object", "Object", "Float32Array", "", "none" } },
335             { "typedarray8", { "object", "Object", "Float64Array", "", "none" } },
336             { "typedarray9", { "object", "Object", "BigInt64Array", "", "none" } },
337             { "typedarray10", { "object", "Object", "BigUint64Array", "", "none" } },
338             { "typedarray11", { "object", "Object", "Uint8Array(1)", "0", "0", "number", "0", "0" } },
339             { "iterator1", { "function", "Function", "function values( { [native code] }",
340                              "function values() { [native code] }" } },
341             { "iterator3", { "function", "Function", "function values( { [native code] }",
342                              "function values() { [native code] }" } },
343             { "iterator2", { "function", "Function", "function entries( { [native code] }",
344                              "function entries() { [native code] }" } },
345             { "iterator4", { "function", "Function", "function values( { [native code] }",
346                              "function values() { [native code] }" } },
347             { "iterator5", { "function", "Function", "function [Symbol.iterator]( { [native code] }",
348                              "function [Symbol.iterator]() { [native code] }" } },
349             { "iterator6", { "function", "Function", "function values( { [native code] }",
350                              "function values() { [native code] }" } },
351             { "iterator7", { "function", "Function", "function values( { [native code] }",
352                              "function values() { [native code] }" } },
353             { "iterator8", { "function", "Function", "function values( { [native code] }",
354                              "function values() { [native code] }" } },
355             { "iterator9", { "function", "Function", "function values( { [native code] }",
356                              "function values() { [native code] }" } },
357             { "iterator10", { "function", "Function", "function values( { [native code] }",
358                               "function values() { [native code] }" } },
359             { "iterator11", { "function", "Function", "function values( { [native code] }",
360                               "function values() { [native code] }" } },
361             { "iterator12", { "function", "Function", "function values( { [native code] }",
362                               "function values() { [native code] }" } },
363             { "iterator13", { "function", "Function", "function values( { [native code] }",
364                               "function values() { [native code] }" } },
365             { "iterator14", { "function", "Function", "function values( { [native code] }",
366                               "function values() { [native code] }" } },
367             { "iterator15", { "function", "Function", "function values( { [native code] }",
368                               "function values() { [native code] }" } },
369             { "iterator16", { "function", "Function", "function values( { [native code] }",
370                               "function values() { [native code] }" } },
371             { "iterator17", { "undefined" } },
372             { "iterator18", { "undefined" } },
373             { "iterator19", { "undefined" } },
374             { "weakMap0", { "object", "weakmap", "Weakmap", "WeakMap(0)", "[object WeakMap]",
375                             "[[Entries]]", "object", "array", "Array", "Array(0)", "" } },
376             { "p1", { "object", "Object", "Number{[[PrimitiveValue]]: 1}", "1", "[[PrimitiveValue]]", "number",
377                       "1", "1" } },
378             { "p2", { "object", "Object", "Number{[[PrimitiveValue]]: 2}", "2", "[[PrimitiveValue]]", "number",
379                       "2", "2" } },
380             { "weakMap1", { "object", "weakmap", "Weakmap", "WeakMap(2) {Object => 'hello', Object => 'world'}",
381                             "[object WeakMap]", "[[Entries]]", "object", "array",
382                             "Array", "Array(2)", "[object Object],[object Object]" } },
383             { "weakMap2", { "object", "weakmap", "Weakmap", "WeakMap(0)", "[object WeakMap]", "[[Entries]]",
384                             "object", "array", "Array", "Array(0)", "", "0", "string", "hello", "hello" } },
385             { "weakMap3", { "object", "weakmap", "Weakmap", "WeakMap(1) {Object => 'weakMap0'}", "[object WeakMap]",
386                             "[[Entries]]", "object", "array", "Array", "Array(1)", "[object Object]" } },
387             { "weakMap4", { "object", "weakmap", "Weakmap", "WeakMap(2) {Object => 37, Object => 'azerty'}",
388                             "[object WeakMap]", "[[Entries]]", "object", "array",
389                             "Array", "Array(2)", "[object Object],[object Object]" } },
390             { "weakMap5", { "object", "weakmap", "Weakmap", "WeakMap(1) {Object => undefined}", "[object WeakMap]",
391                             "[[Entries]]", "object", "array", "Array", "Array(1)", "[object Object]" } },
392             { "weakSet0", { "object", "weakset", "Weakset", "WeakSet(0)", "[object WeakSet]",
393                             "[[Entries]]", "object", "array", "Array", "Array(0)", "" } },
394             { "weakSet1", { "object", "weakset", "Weakset", "WeakSet(1) {Object}", "[object WeakSet]",
395                             "[[Entries]]", "object", "array", "Array", "Array(1)", "[object Object]" } },
396             { "weakSet2", { "object", "weakset", "Weakset", "WeakSet(2) {Object, Object}", "[object WeakSet]",
397                             "[[Entries]]", "object", "array", "Array", "Array(2)",
398                             "[object Object],[object Object]" } },
399             { "Parent", { "function", "Function", "function Parent( { [js code] }",
400                           "Cannot get source code of funtion" } },
401             { "class1", { "object", "Object", "customClass", "[object Object]", "_a", "number", "1", "1",
402                           "_b", "number", "2", "2", "child", "object", "Object", "Child", "[object Object]", "print",
403                           "function", "Function", "function ( { [js code] }", "Cannot get source code of funtion" } },
404             { "parent", { "object", "Object", "Parent", "[object Object]", "name", "string", "parent", "parent",
405                           "age", "number", "50", "50" } },
406             { "customClass", { "function", "Function", "function customClass( { [js code] }",
407                                "Cannot get source code of funtion" } },
408             { "child", { "object", "Object", "Child", "[object Object]", "name", "string", "child", "child",
409                          "age", "number", "15", "15", "idNumber", "string", "1234", "1234" } },
410             { "class2", { "object", "Object", "Object", "[object Object]", "name", "string", "class2", "class2" } },
411             { "Child", { "function", "Function", "function Child( { [js code] }",
412                          "Cannot get source code of funtion" } },
413         };
414 
415         int32_t index_ {0};
416         const EcmaVM *vm_ {nullptr};
417         RuntimeImpl *runtime_ {nullptr};
418     };
419 
420     std::string entryPoint_ = "_GLOBAL::func_main_0";
421     JSPtLocation location_ {nullptr, JSPtLocation::EntityId(0), 0};
422     size_t breakpointCounter_ = 0;
423 };
424 
GetJsVariableSecondTest()425 std::unique_ptr<TestEvents> GetJsVariableSecondTest()
426 {
427     return std::make_unique<JsVariableSecondTest>();
428 }
429 }  // namespace panda::ecmascript::tooling::test
430 
431 #endif  // ECMASCRIPT_TOOLING_TEST_UTILS_TESTCASES_JS_VARIABLE_TEST_H
432