1/*
2 * Copyright (c) 2023 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/*
17 * @tc.name:jsonstringifier
18 * @tc.desc:test JSON.stringify
19 * @tc.type: FUNC
20 * @tc.require: issue#I7DFJC
21 */
22
23try {
24    const v0 = [1, 2, 3, 4]
25    function Foo(a) {
26        Object.defineProperty(this, "ownKeys", { configurable: true, enumerable: true, value: a });
27    }
28    const v1 = new Foo("2060681564", v0, 9.53248718923);
29    const v2 = new Proxy({}, v1);
30    JSON.stringify(v2);
31} catch (e) {
32    print("test successful");
33}
34
35var obj = {
36    2147483648: 2289
37}
38print(JSON.stringify(obj));
39
40const a = new Uint32Array(0x10);
41let  b = a.__proto__;
42b[1073741823] = {}
43print(JSON.stringify(a))
44
45let o = {
46    get g() {
47        this[1225] |= 4294967295;
48        return 9;
49    },
50    "f1":1,
51    "f2":1,
52    "f3":1,
53    "f4":1,
54    "f5":1,
55    "f6":1,
56    "f7":1,
57    "f8":1,
58}
59print(JSON.stringify(o))
60let o2 = {
61    get g() {
62        delete this.f1;
63        return 8;
64    },
65    "f1":1,
66    "f2":1,
67}
68print(JSON.stringify(o2))
69var handler2 = {
70    get:function(target,name) {
71        delete parent2.c;
72        return name.toUpperCase();
73    },
74}
75var proxy2 = new Proxy({},handler2);
76var parent2 = {a:proxy2,c:"remove"};
77print(JSON.stringify(parent2))
78
79var obj={
80    get 1() {
81        delete this['2'];
82    },
83    2:2,
84    3:3,
85}
86print(JSON.stringify(obj))
87
88var List = undefined;
89var LinkedList = undefined;
90if (globalThis["ArkPrivate"] != undefined) {
91    List = ArkPrivate.Load(ArkPrivate.List);
92    let list = new List();
93    list.add({"f1": 1});
94    list.add({"f2": 2});
95    print(JSON.stringify(list));
96
97    LinkedList = ArkPrivate.Load(ArkPrivate.LinkedList);
98    let linkList = new LinkedList();
99    linkList.add({"f3": 3});
100    linkList.add({"f4": 4});
101    print(JSON.stringify(linkList));
102}
103
104var v6="123456789\u0000";
105print(JSON.stringify([{}],[String],v6))
106
107var handler2 = {
108  get: function(target, name) {
109    delete parent2.c;
110    return name.toUpperCase();
111  }
112}
113var proxy2 = new Proxy({}, handler2);
114var parent2 = { a: "delete", b: proxy2, c: "remove" };
115print(JSON.stringify(parent2))
116parent2.c = "remove";  // Revert side effect.
117print(JSON.stringify(parent2))
118Reflect.defineProperty(globalThis,"c",{
119    get:()=>{
120        delete this["d"];
121        return "c";
122    },
123    enumerable:true,
124});
125Reflect.set(globalThis,"d","d");
126JSON.stringify(globalThis);
127print("end JSON.stringify(globalThis)")
128
129let str1="\uD83D";
130let str2="\uDE0E";
131let str3="\uDE0E\"测试";
132let str4=new String("\uDE0E\"测试2")
133let str=str1+str2
134obj={};
135obj[str1]=str1;
136obj[str2]=str2;
137obj[str3]=str3;
138obj[str4]=str4;
139obj[str]=str
140print(JSON.stringify(obj))
141
142print(JSON.stringify(str))
143print(JSON.stringify(str1))
144print(JSON.stringify(str2))
145print(JSON.stringify(str3))
146print(JSON.stringify(str4))
147
148{
149  var actual = [];
150  var test_obj = {o: false};
151  var replaced = {o: false, replaced: true};
152
153  function replacer(key, value) {
154      actual.push({ holder: this, key, value });
155      if (actual.length === 1) return replaced;
156      if (key === "o") return true;
157      return value;
158  }
159  print(`{"o":true,"replaced":true}` == JSON.stringify(test_obj, replacer));
160  const expect = [
161      {
162        holder: { "": { o: false } },
163        key: "",
164        value: { o: false }
165      },
166      {
167        holder: { o: false, replaced: true },
168        key: "o",
169        value: false
170      },
171      {
172        holder: { o: false, replaced: true },
173        key: "replaced",
174        value: true
175      }
176    ];
177  print(JSON.stringify(expect) == JSON.stringify(actual));
178  print(actual[0].holder[""] == test_obj);
179};
180{
181  var actual = [];
182  var test_obj = {o: false, toJSON };
183  var nested = { toJSON: nestedToJSON };
184  var toJSON1 = {o: false, toJSON1: true }
185  var replaced = {o: false, replaced: true, nested };
186  var toJSON2 = { toJSON2: true };
187
188  function toJSON(key, value) {
189    return toJSON1;
190  }
191  function nestedToJSON(key, value) {
192    return toJSON2;
193  }
194  function replacer(key, value) {
195      actual.push({ holder: this, key, value });
196      if (actual.length === 1) return replaced;
197      if (key === "o") return true;
198      return value;
199  }
200  print(`{"o":true,"replaced":true,"nested":{"toJSON2":true}}` ==
201              JSON.stringify(test_obj, replacer));
202  const expect = [
203      {
204        holder: { "": { o: false, toJSON: toJSON } },
205        key: "",
206        value: { o: false, toJSON1: true }
207      },
208      {
209        holder: { o: false, replaced: true, nested: { toJSON: nestedToJSON } },
210        key: "o",
211        value: false
212      },
213      {
214        holder: { o: false, replaced: true, nested: { toJSON: nestedToJSON } },
215        key: "replaced",
216        value: true
217      },
218      {
219        holder: { o: false, replaced: true, nested: { toJSON: nestedToJSON } },
220        key: "nested",
221        value: { toJSON2: true }
222      },
223      {
224        holder: { toJSON2: true },
225        key: "toJSON2",
226        value: true
227      }
228  ];
229  print(JSON.stringify(expect) == JSON.stringify(actual));
230  print(actual[0].holder[""] == test_obj);
231};
232let obj1 = {
233  get a(){
234      this[102400] = 1;
235      return "a";
236  },
237  b:"b",
238}
239Object.keys(obj1);
240print(JSON.stringify(obj1));
241
242try {
243  let loop = {};
244  loop.obj = loop;
245  JSON.stringify(loop);
246} catch (err) {
247  print(err.name);
248  print(err.message.includes("circular structure"));
249}
250
251try {
252    let arkPrivate = globalThis.ArkPrivate;
253    var List = arkPrivate.Load(arkPrivate.List);
254    const v10 = new List();
255    v10.add(v10);
256    print(JSON.stringify(v10));
257} catch (err) {
258    print(err);
259}
260