1 /*
2  * Copyright (c) 2021 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/builtins/builtins_json.h"
17 
18 #include <algorithm>
19 #include <iomanip>
20 #include <sstream>
21 
22 #include "ecmascript/base/builtins_base.h"
23 #include "ecmascript/builtins/builtins_bigint.h"
24 #include "ecmascript/builtins/builtins_errors.h"
25 #include "ecmascript/builtins/builtins_proxy.h"
26 #include "ecmascript/builtins/builtins_typedarray.h"
27 #include "ecmascript/ecma_runtime_call_info.h"
28 #include "ecmascript/ecma_string-inl.h"
29 #include "ecmascript/ecma_vm.h"
30 #include "ecmascript/global_env.h"
31 #include "ecmascript/js_array.h"
32 #include "ecmascript/js_function.h"
33 #include "ecmascript/js_handle.h"
34 #include "ecmascript/js_object-inl.h"
35 #include "ecmascript/js_primitive_ref.h"
36 #include "ecmascript/js_tagged_value-inl.h"
37 #include "ecmascript/js_tagged_value.h"
38 #include "ecmascript/js_thread.h"
39 #include "ecmascript/object_factory.h"
40 #include "ecmascript/tests/test_helper.h"
41 
42 using namespace panda::ecmascript;
43 using namespace panda::ecmascript::builtins;
44 
45 namespace panda::test {
46 class BuiltinsJsonTest : public BaseTestWithScope<false> {
47 public:
48     class TestClass : public base::BuiltinsBase {
49     public:
TestForCommon(EcmaRuntimeCallInfo *argv)50         static JSTaggedValue TestForCommon(EcmaRuntimeCallInfo *argv)
51         {
52             JSTaggedValue key = GetCallArg(argv, 0).GetTaggedValue();
53             if (key.IsUndefined()) {
54                 return JSTaggedValue::Undefined();
55             }
56             JSTaggedValue value = GetCallArg(argv, 1).GetTaggedValue();
57             if (value.IsUndefined()) {
58                 return JSTaggedValue::Undefined();
59             }
60 
61             return JSTaggedValue(value);
62         }
63 
TestForParse(EcmaRuntimeCallInfo *argv)64         static JSTaggedValue TestForParse(EcmaRuntimeCallInfo *argv)
65         {
66             return TestForCommon(argv);
67         }
68 
TestForParse1(EcmaRuntimeCallInfo *argv)69         static JSTaggedValue TestForParse1(EcmaRuntimeCallInfo *argv)
70         {
71             (void)argv;
72             return JSTaggedValue::Undefined();
73         }
74 
TestForStringfy(EcmaRuntimeCallInfo *argv)75         static JSTaggedValue TestForStringfy(EcmaRuntimeCallInfo *argv)
76         {
77             uint32_t argc = argv->GetArgsNumber();
78             if (argc > 0) {
79                 return TestForCommon(argv);
80             }
81 
82             return JSTaggedValue::Undefined();
83         }
84     };
85 };
86 
CreateBuiltinJSObject1(JSThread *thread, const CString keyCStr)87 JSTaggedValue CreateBuiltinJSObject1(JSThread *thread, const CString keyCStr)
88 {
89     EcmaVM *ecmaVM = thread->GetEcmaVM();
90     JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv();
91     ObjectFactory *factory = ecmaVM->GetFactory();
92     JSHandle<JSTaggedValue> objectFunc(globalEnv->GetObjectFunction());
93 
94     JSHandle<JSObject> jsobject(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc));
95     EXPECT_TRUE(*jsobject != nullptr);
96 
97     JSHandle<JSTaggedValue> key(factory->NewFromASCII(&keyCStr[0]));
98     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
99     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(jsobject), key, value);
100 
101     CString str2 = "y";
102     JSHandle<JSTaggedValue> key2(factory->NewFromASCII(str2));
103     JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(2.5)); // 2.5 : test case
104     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(jsobject), key2, value2);
105 
106     CString str3 = "z";
107     JSHandle<JSTaggedValue> key3(factory->NewFromASCII(str3));
108     JSHandle<JSTaggedValue> value3(factory->NewFromASCII("abc"));
109     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(jsobject), key3, value3);
110 
111     return jsobject.GetTaggedValue();
112 }
113 // Math.abs(-10)
114 
HWTEST_F_L0(BuiltinsJsonTest, Parse10)115 HWTEST_F_L0(BuiltinsJsonTest, Parse10)
116 {
117     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
118 
119     JSHandle<JSTaggedValue> msg(factory->NewFromASCII(
120         "\t\r \n{\t\r \n \"property\"\t\r \n:\t\r \n{\t\r \n}\t\r \n,\t\r \n \"prop2\"\t\r \n:\t\r \n [\t\r \ntrue\t\r "
121         "\n,\t\r \nnull\t\r \n,123.456\t\r \n] \t\r \n}\t\r \n"));
122     JSHandle<EcmaString> str(JSTaggedValue::ToString(thread, msg));
123 
124     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
125     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
126     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
127     ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
128 
129     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
130     JSTaggedValue result = BuiltinsJson::Parse(ecmaRuntimeCallInfo);
131     ASSERT_TRUE(result.IsECMAObject());
132 }
133 
HWTEST_F_L0(BuiltinsJsonTest, Parse21)134 HWTEST_F_L0(BuiltinsJsonTest, Parse21)
135 {
136     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
137     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
138 
139     JSHandle<JSTaggedValue> msg(factory->NewFromASCII("[100,2.5,\"abc\"]"));
140 
141     JSHandle<JSFunction> handleFunc = factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::TestForParse));
142     JSHandle<EcmaString> str(JSTaggedValue::ToString(thread, msg));
143 
144     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
145     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
146     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
147     ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
148     ecmaRuntimeCallInfo->SetCallArg(1, handleFunc.GetTaggedValue());
149 
150     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
151     JSTaggedValue result = BuiltinsJson::Parse(ecmaRuntimeCallInfo);
152     ASSERT_TRUE(result.IsECMAObject());
153 }
154 
HWTEST_F_L0(BuiltinsJsonTest, Parse)155 HWTEST_F_L0(BuiltinsJsonTest, Parse)
156 {
157     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
158     JSHandle<JSTaggedValue> lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString();
159 
160     JSHandle<JSTaggedValue> msg(factory->NewFromASCII("[100,2.5,\"abc\"]"));
161     JSHandle<EcmaString> str(JSTaggedValue::ToString(thread, msg));
162     std::vector<JSTaggedValue> args{str.GetTaggedValue()};
163     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, args, 6);
164 
165     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
166     JSTaggedValue result = BuiltinsJson::Parse(ecmaRuntimeCallInfo);
167     JSTaggedValue value(static_cast<JSTaggedType>(result.GetRawData()));
168     ASSERT_TRUE(value.IsECMAObject());
169     JSHandle<JSObject> valueHandle(thread, value);
170     JSHandle<JSTaggedValue> lenResult =
171         JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(valueHandle), lengthKeyHandle).GetValue();
172     uint32_t length = JSTaggedValue::ToLength(thread, lenResult).ToUint32();
173     EXPECT_EQ(length, 3U);
174 }
175 
HWTEST_F_L0(BuiltinsJsonTest, Parse2)176 HWTEST_F_L0(BuiltinsJsonTest, Parse2)
177 {
178     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
179     JSHandle<JSTaggedValue> msg(factory->NewFromASCII("{\"epf\":100,\"key1\":200}"));
180     JSHandle<EcmaString> str(JSTaggedValue::ToString(thread, msg));
181 
182     std::vector<JSTaggedValue> args{str.GetTaggedValue()};
183     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, args, 6);
184 
185     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
186     JSTaggedValue result = BuiltinsJson::Parse(ecmaRuntimeCallInfo);
187     JSTaggedValue value(static_cast<JSTaggedType>(result.GetRawData()));
188     ASSERT_TRUE(value.IsECMAObject());
189     JSHandle<JSObject> valueHandle(thread, value);
190 
191     JSHandle<TaggedArray> nameList(JSObject::EnumerableOwnNames(thread, valueHandle));
192     JSHandle<JSArray> nameResult = JSArray::CreateArrayFromList(thread, nameList);
193 
194     JSHandle<JSTaggedValue> handleKey(nameResult);
195     JSHandle<JSTaggedValue> lengthKey(factory->NewFromASCII("length"));
196     JSHandle<JSTaggedValue> lenResult = JSObject::GetProperty(thread, handleKey, lengthKey).GetValue();
197     uint32_t length = JSTaggedValue::ToLength(thread, lenResult).ToUint32();
198     ASSERT_EQ(length, 2U);
199 }
200 
HWTEST_F_L0(BuiltinsJsonTest, Parse3)201 HWTEST_F_L0(BuiltinsJsonTest, Parse3)
202 {
203     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
204     JSHandle<EcmaString> str = factory->NewFromStdString("\"\\u0000\"");
205 
206     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
207     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
208     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
209     ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
210 
211     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
212     JSTaggedValue result = BuiltinsJson::Parse(ecmaRuntimeCallInfo);
213     uint32_t length = EcmaStringAccessor(result).GetLength();
214     ASSERT_EQ(length, 1U);
215 }
216 
HWTEST_F_L0(BuiltinsJsonTest, Parse4)217 HWTEST_F_L0(BuiltinsJsonTest, Parse4)
218 {
219     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
220     JSHandle<EcmaString> str = factory->NewFromStdString("{\n\t\"on\":\t0\n}");
221     JSHandle<EcmaString> key = factory->NewFromStdString("on");
222 
223     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
224     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
225     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
226     ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
227 
228     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
229     JSTaggedValue result = BuiltinsJson::Parse(ecmaRuntimeCallInfo);
230     JSHandle<JSTaggedValue> value =
231         JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>(thread, result), JSHandle<JSTaggedValue>(key))
232             .GetValue();
233     int32_t number = JSTaggedValue::ToInt32(thread, value);
234     ASSERT_EQ(number, 0);
235 }
236 
237 
HWTEST_F_L0(BuiltinsJsonTest, Stringify11)238 HWTEST_F_L0(BuiltinsJsonTest, Stringify11)
239 {
240     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
241     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
242     JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateBuiltinJSObject1(thread, "x"));
243     JSHandle<JSFunction> handleFunc =
244         factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::TestForStringfy));
245 
246     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
247     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
248     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
249     ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
250     ecmaRuntimeCallInfo->SetCallArg(1, handleFunc.GetTaggedValue());
251 
252     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
253     JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
254     ASSERT_TRUE(result.IsString());
255 }
256 
HWTEST_F_L0(BuiltinsJsonTest, Stringify12)257 HWTEST_F_L0(BuiltinsJsonTest, Stringify12)
258 {
259     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
260     JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateBuiltinJSObject1(thread, "x"));
261     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
262     JSHandle<JSFunction> handleFunc =
263         factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::TestForStringfy));
264 
265     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
266     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
267     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
268     ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
269     ecmaRuntimeCallInfo->SetCallArg(1, handleFunc.GetTaggedValue());
270     ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(10)));
271 
272     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
273     JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
274     ASSERT_TRUE(result.IsString());
275 }
276 
HWTEST_F_L0(BuiltinsJsonTest, Stringify13)277 HWTEST_F_L0(BuiltinsJsonTest, Stringify13)
278 {
279     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
280     JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateBuiltinJSObject1(thread, "x"));
281     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
282     JSHandle<JSFunction> handleFunc =
283         factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::TestForStringfy));
284     JSHandle<JSTaggedValue> msg(factory->NewFromASCII("tttt"));
285     JSHandle<EcmaString> str(JSTaggedValue::ToString(thread, msg));
286 
287     std::vector<JSTaggedValue> args{obj.GetTaggedValue(), handleFunc.GetTaggedValue(), str.GetTaggedValue()};
288     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, args, 10);
289 
290     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
291     JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
292     ASSERT_TRUE(result.IsString());
293 }
294 
HWTEST_F_L0(BuiltinsJsonTest, Stringify14)295 HWTEST_F_L0(BuiltinsJsonTest, Stringify14)
296 {
297     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
298     JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateBuiltinJSObject1(thread, "x"));
299     JSArray *arr = JSArray::Cast(JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetTaggedValue().GetTaggedObject());
300 
301     JSHandle<JSObject> obj1(thread, arr);
302     JSHandle<JSTaggedValue> key0(thread, JSTaggedValue(0));
303     JSHandle<JSTaggedValue> value0(factory->NewFromASCII("x"));
304     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key0, value0);
305     JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(1));
306     JSHandle<JSTaggedValue> value1(factory->NewFromASCII("z"));
307     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key1, value1);
308 
309     JSHandle<JSTaggedValue> msg(factory->NewFromASCII("tttt"));
310     JSHandle<EcmaString> str(JSTaggedValue::ToString(thread, msg));
311 
312     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
313     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
314     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
315     ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
316     ecmaRuntimeCallInfo->SetCallArg(1, obj1.GetTaggedValue());
317     ecmaRuntimeCallInfo->SetCallArg(2, str.GetTaggedValue());
318 
319     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
320     JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
321     ASSERT_TRUE(result.IsString());
322 }
323 
HWTEST_F_L0(BuiltinsJsonTest, Stringify)324 HWTEST_F_L0(BuiltinsJsonTest, Stringify)
325 {
326     JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateBuiltinJSObject1(thread, "x"));
327     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
328     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
329     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
330     ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
331 
332     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
333     JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
334     ASSERT_TRUE(result.IsString());
335 }
336 
HWTEST_F_L0(BuiltinsJsonTest, Stringify1)337 HWTEST_F_L0(BuiltinsJsonTest, Stringify1)
338 {
339     auto ecmaVM = thread->GetEcmaVM();
340     ObjectFactory *factory = ecmaVM->GetFactory();
341     JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
342 
343     JSArray *arr = JSArray::Cast(JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetTaggedValue().GetTaggedObject());
344 
345     EXPECT_TRUE(arr != nullptr);
346     JSHandle<JSObject> obj(thread, arr);
347     JSHandle<JSTaggedValue> key0(thread, JSTaggedValue(0));
348 
349     JSHandle<JSTaggedValue> value(factory->NewFromASCII("def"));
350     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key0, value);
351 
352     JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(1));
353     PropertyDescriptor desc1(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(200)), true, true, true);
354     JSArray::DefineOwnProperty(thread, obj, key1, desc1);
355 
356     JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(2));
357     JSHandle<JSTaggedValue> value2(factory->NewFromASCII("abc"));
358     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key2, value2);
359 
360     JSHandle<JSFunction> handleFunc =
361         factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::TestForStringfy));
362     JSHandle<JSTaggedValue> msg(factory->NewFromASCII("tttt"));
363     JSHandle<EcmaString> str(JSTaggedValue::ToString(thread, msg));
364 
365     std::vector<JSTaggedValue> args{obj.GetTaggedValue(), handleFunc.GetTaggedValue(), str.GetTaggedValue()};
366     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, args, 10);
367 
368     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
369     JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
370     ASSERT_TRUE(result.IsString());
371 }
372 
HWTEST_F_L0(BuiltinsJsonTest, Stringify2)373 HWTEST_F_L0(BuiltinsJsonTest, Stringify2)
374 {
375     auto ecmaVM = thread->GetEcmaVM();
376     ObjectFactory *factory = ecmaVM->GetFactory();
377 
378     JSArray *arr = JSArray::Cast(JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetTaggedValue().GetTaggedObject());
379     EXPECT_TRUE(arr != nullptr);
380     JSHandle<JSObject> obj(thread, arr);
381 
382     JSHandle<JSTaggedValue> key0(thread, JSTaggedValue(0));
383     PropertyDescriptor desc0(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), true, true, true);
384     JSArray::DefineOwnProperty(thread, obj, key0, desc0);
385     JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(1));
386     // 2.5 : test case
387     PropertyDescriptor desc1(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(2.5)), true, true, true);
388     JSArray::DefineOwnProperty(thread, obj, key1, desc1);
389     // 2 : test case
390     JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(2));
391     JSHandle<JSTaggedValue> value2(factory->NewFromASCII("abc"));
392     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key2, value2);
393 
394     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
395     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
396     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
397     ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
398 
399     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
400     JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
401     ASSERT_TRUE(result.IsString());
402 }
403 
HWTEST_F_L0(BuiltinsJsonTest, Stringify3)404 HWTEST_F_L0(BuiltinsJsonTest, Stringify3)
405 {
406     auto ecmaVM = thread->GetEcmaVM();
407     ObjectFactory *factory = ecmaVM->GetFactory();
408 
409     uint16_t data[1];
410     data[0] = 0;
411     JSHandle<EcmaString> str = factory->NewFromUtf16(data, 1);
412     JSHandle<EcmaString> test = factory->NewFromStdString("\"\\u0000\"");
413 
414     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
415     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
416     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
417     ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
418 
419     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
420     JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
421     ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*test, EcmaString::Cast(result.GetTaggedObject())));
422 }
423 
CreateJSObject(JSThread *thread)424 JSHandle<JSTaggedValue> CreateJSObject(JSThread *thread)
425 {
426     EcmaVM *ecmaVM = thread->GetEcmaVM();
427     JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv();
428     JSHandle<JSTaggedValue> objFun = globalEnv->GetObjectFunction();
429     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
430 
431     JSHandle<JSTaggedValue> obj(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
432     JSHandle<JSTaggedValue> key(factory->NewFromStdString("x"));
433     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
434     JSObject::SetProperty(thread, obj, key, value);
435     return obj;
436 }
437 
CreateProxy(JSThread *thread)438 JSHandle<JSTaggedValue> CreateProxy(JSThread *thread)
439 {
440     JSHandle<JSTaggedValue> target = CreateJSObject(thread);
441     JSHandle<JSTaggedValue> handler = CreateJSObject(thread);
442 
443     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Null(), 8);
444     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
445     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
446     ecmaRuntimeCallInfo->SetCallArg(0, target.GetTaggedValue());
447     ecmaRuntimeCallInfo->SetCallArg(1, handler.GetTaggedValue());
448 
449     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
450     JSTaggedValue result = BuiltinsProxy::ProxyConstructor(ecmaRuntimeCallInfo);
451     TestHelper::TearDownFrame(thread, prev);
452     return JSHandle<JSTaggedValue>(thread, result);
453 }
454 
HWTEST_F_L0(BuiltinsJsonTest, Stringify4)455 HWTEST_F_L0(BuiltinsJsonTest, Stringify4)  // Test for proxy object
456 {
457     auto ecmaVM = thread->GetEcmaVM();
458     ObjectFactory *factory = ecmaVM->GetFactory();
459 
460     JSHandle<JSTaggedValue> proxy = CreateProxy(thread);
461     JSHandle<EcmaString> test = factory->NewFromStdString("{\"x\":1}");
462 
463     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
464     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
465     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
466     ecmaRuntimeCallInfo->SetCallArg(0, proxy.GetTaggedValue());
467 
468     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
469     JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
470     ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*test, EcmaString::Cast(result.GetTaggedObject())));
471     TestHelper::TearDownFrame(thread, prev);
472 }
473 
HWTEST_F_L0(BuiltinsJsonTest, Stringify5)474 HWTEST_F_L0(BuiltinsJsonTest, Stringify5)  // Test for typedarray object
475 {
476     auto ecmaVM = thread->GetEcmaVM();
477     ObjectFactory *factory = ecmaVM->GetFactory();
478     [[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(3));
479     array->Set(thread, 0, JSTaggedValue(2));
480     array->Set(thread, 1, JSTaggedValue(3));
481     array->Set(thread, 2, JSTaggedValue(4));
482 
483     JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
484     JSHandle<JSTaggedValue> jsArray(JSArray::CreateArrayFromList(thread, array));
485     JSHandle<JSFunction> int8Func(env->GetInt8ArrayFunction());
486     JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
487     auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
488     ecmaRuntimeCallInfo1->SetNewTarget(JSTaggedValue(*int8Func));
489     ecmaRuntimeCallInfo1->SetThis(JSTaggedValue(*globalObject));
490     ecmaRuntimeCallInfo1->SetCallArg(0, jsArray.GetTaggedValue());
491 
492     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
493     JSHandle<JSTaggedValue> int8Array(thread, BuiltinsTypedArray::Int8ArrayConstructor(ecmaRuntimeCallInfo1));
494     TestHelper::TearDownFrame(thread, prev);
495 
496     JSHandle<EcmaString> test = factory->NewFromStdString("{\"0\":2,\"1\":3,\"2\":4}");
497 
498     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
499     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
500     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
501     ecmaRuntimeCallInfo->SetCallArg(0, int8Array.GetTaggedValue());
502 
503     prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
504     JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
505     TestHelper::TearDownFrame(thread, prev);
506     ASSERT_TRUE(result.IsString());
507     ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*test, EcmaString::Cast(result.GetTaggedObject())));
508 }
509 
HWTEST_F_L0(BuiltinsJsonTest, Stringify6)510 HWTEST_F_L0(BuiltinsJsonTest, Stringify6)  // Test for bigint object
511 {
512     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
513     JSHandle<JSTaggedValue> numericValue(factory->NewFromASCII("123456789123456789"));
514 
515     auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
516     ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined());
517     ecmaRuntimeCallInfo1->SetThis(JSTaggedValue::Undefined());
518     ecmaRuntimeCallInfo1->SetCallArg(0, numericValue.GetTaggedValue());
519 
520     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
521     JSTaggedValue result1 = BuiltinsBigInt::BigIntConstructor(ecmaRuntimeCallInfo1);
522     TestHelper::TearDownFrame(thread, prev);
523 
524     JSHandle<JSTaggedValue> bigIntHandle(thread, result1);
525 
526     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
527     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
528     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
529     ecmaRuntimeCallInfo->SetCallArg(0, bigIntHandle.GetTaggedValue());
530 
531     prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
532     [[maybe_unused]] JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
533     bool hasPendingException = false;
534     if (thread->HasPendingException()) {
535         hasPendingException = true;
536         thread->ClearException();
537     }
538     ASSERT_TRUE(hasPendingException);
539 }
540 
HWTEST_F_L0(BuiltinsJsonTest, StringifyAndParse)541 HWTEST_F_L0(BuiltinsJsonTest, StringifyAndParse)
542 {
543     auto ecmaVM = thread->GetEcmaVM();
544     ObjectFactory *factory = ecmaVM->GetFactory();
545     JSHandle<JSTaggedValue> obj = CreateJSObject(thread);
546     JSHandle<JSTaggedValue> ykey(factory->NewFromASCII("y"));
547     JSHandle<JSTaggedValue> yvalue(thread, JSTaggedValue(2.2)); // 2.2: use to test double value
548     JSObject::SetProperty(thread, obj, ykey, yvalue);
549 
550     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
551     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
552     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
553     ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
554     JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Hole());
555     {
556         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
557         result.Update(BuiltinsJson::Stringify(ecmaRuntimeCallInfo));
558         TestHelper::TearDownFrame(thread, prev);
559     }
560     {
561         ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
562         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
563         ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
564         ecmaRuntimeCallInfo->SetCallArg(0, result.GetTaggedValue());
565         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
566         result.Update(BuiltinsJson::Parse(ecmaRuntimeCallInfo));
567         TestHelper::TearDownFrame(thread, prev);
568     }
569     ASSERT_TRUE(result->IsECMAObject());
570 
571     JSHandle<JSObject> resultObj(result);
572     JSHandle<JSTaggedValue> key(factory->NewFromASCII("x"));
573     JSHandle<JSTaggedValue> res = JSObject::GetProperty(thread, resultObj, key).GetValue();
574     ASSERT_TRUE(res->IsInt());
575     ASSERT_EQ(res->GetInt(), 1);
576 
577     res = JSObject::GetProperty(thread, resultObj, ykey).GetValue();
578     ASSERT_TRUE(res->IsDouble());
579     ASSERT_EQ(res->GetDouble(), 2.2); // 2.2:use to test double value
580 }
581 }  // namespace panda::test
582