• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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    assert_unreachable();
32} catch (e) {
33  assert_equal(true,true);
34}
35
36var obj = {
37    2147483648: 2289
38}
39assert_equal(JSON.stringify(obj),'{"2147483648":2289}');
40
41const a = new Uint32Array(0x10);
42let  b = a.__proto__;
43b[1073741823] = {}
44assert_equal(JSON.stringify(a),'{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0}')
45
46let o = {
47    get g() {
48        this[1225] |= 4294967295;
49        return 9;
50    },
51    "f1":1,
52    "f2":1,
53    "f3":1,
54    "f4":1,
55    "f5":1,
56    "f6":1,
57    "f7":1,
58    "f8":1,
59}
60assert_equal(JSON.stringify(o),'{"g":9,"f1":1,"f2":1,"f3":1,"f4":1,"f5":1,"f6":1,"f7":1,"f8":1}')
61let o2 = {
62    get g() {
63        delete this.f1;
64        return 8;
65    },
66    "f1":1,
67    "f2":1,
68}
69assert_equal(JSON.stringify(o2),'{"g":8,"f2":1}')
70var handler2 = {
71    get:function(target,name) {
72        delete parent2.c;
73        return name.toUpperCase();
74    },
75}
76var proxy2 = new Proxy({},handler2);
77var parent2 = {a:proxy2,c:"remove"};
78assert_equal(JSON.stringify(parent2),'{"a":{}}')
79
80var obj={
81    get 1() {
82        delete this['2'];
83    },
84    2:2,
85    3:3,
86}
87assert_equal(JSON.stringify(obj),'{"3":3}')
88
89var List = undefined;
90var LinkedList = undefined;
91if (globalThis["ArkPrivate"] != undefined) {
92    List = ArkPrivate.Load(ArkPrivate.List);
93    let list = new List();
94    list.add({"f1": 1});
95    list.add({"f2": 2});
96    print(JSON.stringify(list));
97
98    LinkedList = ArkPrivate.Load(ArkPrivate.LinkedList);
99    let linkList = new LinkedList();
100    linkList.add({"f3": 3});
101    linkList.add({"f4": 4});
102    print(JSON.stringify(linkList));
103}
104
105var v6="123456789\u0000";
106assert_equal(JSON.stringify([{}]),'[{}]')
107assert_equal(JSON.stringify([String]),'[null]')
108assert_equal(JSON.stringify(v6),'"123456789\\u0000"')
109
110
111var handler2 = {
112  get: function(target, name) {
113    delete parent2.c;
114    return name.toUpperCase();
115  }
116}
117var proxy2 = new Proxy({}, handler2);
118var parent2 = { a: "delete", b: proxy2, c: "remove" };
119assert_equal(JSON.stringify(parent2),'{"a":"delete","b":{}}')
120parent2.c = "remove";  // Revert side effect.
121assert_equal(JSON.stringify(parent2),'{"a":"delete","b":{}}')
122Reflect.defineProperty(globalThis,"c",{
123    get:()=>{
124        delete this["d"];
125        return "c";
126    },
127    enumerable:true,
128});
129Reflect.set(globalThis,"d","d");
130JSON.stringify(globalThis);
131
132let str1="\uD83D";
133let str2="\uDE0E";
134let str3="\uDE0E\"测试";
135let str4=new String("\uDE0E\"测试2")
136let str=str1+str2
137obj={};
138obj[str1]=str1;
139obj[str2]=str2;
140obj[str3]=str3;
141obj[str4]=str4;
142obj[str]=str
143assert_equal(JSON.stringify(obj),'{"\\ud83d":"\\ud83d","\\ude0e":"\\ude0e","\\ude0e\\"测试":"\\ude0e\\"测试","\\ude0e\\"测试2":"\\ude0e\\"测试2","��":"��"}')
144
145assert_equal(JSON.stringify(str),'"��"')
146assert_equal(JSON.stringify(str1),'"\\ud83d"')
147assert_equal(JSON.stringify(str2),'"\\ude0e"')
148assert_equal(JSON.stringify(str3),'"\\ude0e\\"测试"')
149assert_equal(JSON.stringify(str4),'"\\ude0e\\"测试2"')
150
151{
152  var actual = [];
153  var test_obj = {o: false};
154  var replaced = {o: false, replaced: true};
155
156  function replacer(key, value) {
157      actual.push({ holder: this, key, value });
158      if (actual.length === 1) return replaced;
159      if (key === "o") return true;
160      return value;
161  }
162  assert_equal(`{"o":true,"replaced":true}` == JSON.stringify(test_obj, replacer),true);
163  const expect = [
164      {
165        holder: { "": { o: false } },
166        key: "",
167        value: { o: false }
168      },
169      {
170        holder: { o: false, replaced: true },
171        key: "o",
172        value: false
173      },
174      {
175        holder: { o: false, replaced: true },
176        key: "replaced",
177        value: true
178      }
179    ];
180  assert_equal(JSON.stringify(expect) == JSON.stringify(actual),true);
181  assert_equal(actual[0].holder[""] == test_obj,true);
182};
183{
184  var actual = [];
185  var test_obj = {o: false, toJSON };
186  var nested = { toJSON: nestedToJSON };
187  var toJSON1 = {o: false, toJSON1: true }
188  var replaced = {o: false, replaced: true, nested };
189  var toJSON2 = { toJSON2: true };
190
191  function toJSON(key, value) {
192    return toJSON1;
193  }
194  function nestedToJSON(key, value) {
195    return toJSON2;
196  }
197  function replacer(key, value) {
198      actual.push({ holder: this, key, value });
199      if (actual.length === 1) return replaced;
200      if (key === "o") return true;
201      return value;
202  }
203  assert_equal(`{"o":true,"replaced":true,"nested":{"toJSON2":true}}` ==
204            JSON.stringify(test_obj, replacer),true);
205  const expect = [
206      {
207        holder: { "": { o: false, toJSON: toJSON } },
208        key: "",
209        value: { o: false, toJSON1: true }
210      },
211      {
212        holder: { o: false, replaced: true, nested: { toJSON: nestedToJSON } },
213        key: "o",
214        value: false
215      },
216      {
217        holder: { o: false, replaced: true, nested: { toJSON: nestedToJSON } },
218        key: "replaced",
219        value: true
220      },
221      {
222        holder: { o: false, replaced: true, nested: { toJSON: nestedToJSON } },
223        key: "nested",
224        value: { toJSON2: true }
225      },
226      {
227        holder: { toJSON2: true },
228        key: "toJSON2",
229        value: true
230      }
231  ];
232  assert_equal(JSON.stringify(expect) == JSON.stringify(actual),true);
233  assert_equal(actual[0].holder[""] == test_obj,true);
234};
235let obj1 = {
236  get a(){
237      this[102400] = 1;
238      return "a";
239  },
240  b:"b",
241}
242Object.keys(obj1);
243assert_equal(JSON.stringify(obj1),'{"a":"a","b":"b"}');
244
245try {
246  let loop = {};
247  loop.obj = loop;
248  JSON.stringify(loop);
249  assert_unreachable();
250} catch (err) {
251  assert_equal(err.name,'TypeError');
252  assert_equal(err.message.includes("circular structure"),true);
253}
254
255const specialString = '"Hello\nWorld\\tThis is a test string with special characters: \u00A9 \u00AE "';
256const nestedObj = {
257  level1: {
258    level2: {
259      level3: {
260        message: specialString,
261        number: 42,
262        truthy: true,
263        anotherObj: {
264          key: 'value'
265        },
266        array: [1, 'two', false, { nested: 'object' }]
267      }
268    }
269  }
270};
271assert_equal((JSON.stringify(nestedObj, null, 2)).substring(2, 5), '  "');
272assert_equal((JSON.stringify(nestedObj, null, " ")).substring(2, 4), ' "');
273
274try {
275    let arkPrivate = globalThis.ArkPrivate;
276    var List = arkPrivate.Load(arkPrivate.List);
277    const v10 = new List();
278    v10.add(v10);
279    JSON.stringify(v10);
280    assert_unreachable();
281} catch (err) {
282    assert_equal("Caught an error: "+ err, "Caught an error: TypeError: stack contains value, usually caused by circular structure");
283}
284
285const testspaceobj = {
286  name: "abc",
287  age: 123,
288  city: "Shanghai"
289};
290const testspaceobjAssert = JSON.stringify(testspaceobj, null, Infinity);
291assert_equal(JSON.stringify(testspaceobj, null, Infinity),testspaceobjAssert);
292
293{
294    let obj = {};
295    let tmp = obj;
296    for (let i = 0; i < 5000; i++) {
297        tmp.name = {};
298        tmp = tmp.name;
299    }
300    try {
301        let res = JSON.stringify(obj);
302        assert_unreachable();
303    } catch (error) {
304        assert_equal(error instanceof RangeError, true);
305    }
306}
307
308test_end();