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
42using namespace panda::ecmascript;
43using namespace panda::ecmascript::builtins;
44
45namespace panda::test {
46class BuiltinsJsonTest : public BaseTestWithScope<false> {
47public:
48    class TestClass : public base::BuiltinsBase {
49    public:
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
64        static JSTaggedValue TestForParse(EcmaRuntimeCallInfo *argv)
65        {
66            return TestForCommon(argv);
67        }
68
69        static JSTaggedValue TestForParse1(EcmaRuntimeCallInfo *argv)
70        {
71            (void)argv;
72            return JSTaggedValue::Undefined();
73        }
74
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
87JSTaggedValue 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
115HWTEST_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
134HWTEST_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
155HWTEST_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
176HWTEST_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
201HWTEST_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
217HWTEST_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
238HWTEST_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
257HWTEST_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
277HWTEST_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
295HWTEST_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
324HWTEST_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
337HWTEST_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
373HWTEST_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
404HWTEST_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
424JSHandle<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
438JSHandle<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
455HWTEST_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
474HWTEST_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
510HWTEST_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
541HWTEST_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