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();