1/*
2 * Copyright (c) 2024 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
16declare interface ArkTools {
17    isAOTCompiled(args: any): boolean;
18}
19declare function print(arg:any):string;
20function replace(x : any)
21{
22    return x;
23}
24
25function doAdd(x : any) {
26    return mySet.add(x);
27}
28
29function printAdd(x : any) {
30    try {
31        print(doAdd(x));
32    } finally {
33    }
34}
35
36function tryAdd(x: any, y : any) {
37    try {
38        print(x.add(y));
39    } finally {
40    }
41}
42
43let mySet = new Set();
44
45// Check without params
46print(mySet.add());
47//aot: [trace] aot inline builtin: Set.add, caller function name:func_main_0@builtinSetAdd
48//: [object Set]
49print(mySet.size);
50//: 1
51print(mySet.has(undefined));
52//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
53//: true
54
55// Check with single param
56mySet.add(125);
57//aot: [trace] aot inline builtin: Set.add, caller function name:func_main_0@builtinSetAdd
58print(mySet.size);
59//: 2
60print(mySet.has(125));
61//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
62//: true
63
64// Check with 2 params
65mySet.add(0, undefined);
66//aot: [trace] aot inline builtin: Set.add, caller function name:func_main_0@builtinSetAdd
67print(mySet.size);
68//: 3
69print(mySet.has(0));
70//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
71//: true
72
73// Check with 3 params
74mySet.add(0, "ab", 14);
75//aot: [trace] aot inline builtin: Set.add, caller function name:func_main_0@builtinSetAdd
76print(mySet.size);
77//: 3
78print(mySet.has(0));
79//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
80//: true
81
82for (let key of mySet.values()) {
83    print(key);
84}
85//: undefined
86//: 125
87//: 0
88
89let true_add = mySet.add
90
91printAdd(15);
92//aot: [trace] aot inline builtin: Set.add, caller function name:#*#doAdd@builtinSetAdd
93//: [object Set]
94print(mySet.has(15));
95//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
96//: true
97
98// Call standard builtin with non-number param
99mySet.add("abc");
100//aot: [trace] aot inline builtin: Set.add, caller function name:func_main_0@builtinSetAdd
101print(mySet.has("abc"));
102//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
103//: true
104
105if (ArkTools.isAOTCompiled(printAdd)) {
106    // Replace standard builtin after call to standard builtin was profiled
107    mySet.add = replace
108}
109
110printAdd(42);
111//pgo: [object Set]
112//aot: [trace] Check Type: BuiltinInstanceHClassMismatch
113//aot: 42
114print(mySet.has(42));
115//pgo: true
116//aot: [trace] Check Type: BuiltinInstanceHClassMismatch
117//aot: false
118
119print("fuck") //: fuck
120mySet.add = true_add
121print(mySet.add("xyz"));
122//: [object Set]
123//aot: [trace] aot inline builtin: Set.add, caller function name:func_main_0@builtinSetAdd
124print(mySet.has("xyz"));
125//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
126//: true
127
128// Check IR correctness inside try-block
129try {
130    printAdd(2.5);
131    //aot: [[trace] aot inline builtin: Set.add, caller function name:#*#doAdd@builtinSetAdd
132    //: [object Set]
133    printAdd("oops");
134    //aot: [[trace] aot inline builtin: Set.add, caller function name:#*#doAdd@builtinSetAdd
135    //: [object Set]
136    print(mySet.has(2.5));
137    //aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
138    //: true
139    print(mySet.has("oops"));
140    //aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
141    //: true
142} catch (e) {
143}
144
145
146let obj = {};
147obj.valueOf = (() => { return 7; })
148
149mySet.add(obj);
150//aot: [trace] aot inline builtin: Set.add, caller function name:func_main_0@builtinSetAdd
151print(mySet.has(obj));
152//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
153//: true
154print(mySet.has(7));
155//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
156//: false
157mySet.clear();
158
159function Throwing() {
160    this.value = 2;
161    Throwing.prototype.valueOf = function() {
162        if (this.value > 0) {
163            throw new Error("positive");
164        }
165        return this.value;
166    }
167}
168
169let throwingObj = new Throwing();
170try {
171    mySet.add(throwingObj);
172    //aot: [trace] aot inline builtin: Set.add, caller function name:func_main_0@builtinSetAdd
173    print(mySet.has(throwingObj));
174    //aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
175    //: true
176    print(mySet.has(2));
177    //aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
178    //: false
179} catch(e) {
180    print(e);
181} finally {
182    mySet.add(obj);
183    //aot: [trace] aot inline builtin: Set.add, caller function name:func_main_0@builtinSetAdd
184    print(mySet.has(obj));
185    //aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
186    //: true
187    print(mySet.has(7));
188    //aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
189    //: false
190}
191
192let trueadd = Set.prototype.add;
193let m = new Set();
194
195print("baseline"); //: baseline
196let m2 = new Set([1]);
197let m3 = new Set([1]);
198let m4 = new Set([1]);
199
200tryAdd(m, 13);
201//aot: [trace] aot inline builtin: Set.add, caller function name:func_main_0@builtinSetAdd
202//: [object Set]
203print(m.has(13));
204//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
205//: true
206
207tryAdd(m2, 13);
208//aot: [trace] aot inline builtin: Set.add, caller function name:#*#doAdd@builtinSetAdd
209//: [object Set]
210print(m2.has(13));
211//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
212//: true
213
214tryAdd(m3, 13);
215//aot: [trace] aot inline builtin: Set.add, caller function name:#*#doAdd@builtinSetAdd
216//: [object Set]
217print(m3.has(13));
218//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
219//: true
220
221tryAdd(m4, 13);
222//aot: [trace] aot inline builtin: Set.add, caller function name:#*#doAdd@builtinSetAdd
223//: [object Set]
224print(m4.has(13));
225//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
226//: true
227
228print("case 0"); //: case 0
229if (ArkTools.isAOTCompiled(tryAdd)) {
230    m4.garbage = function(x: any) {
231        return undefined;
232    }
233}
234
235// Nothing changed
236tryAdd(m, 25);
237//aot: [trace] aot inline builtin: Set.add, caller function name:#*#doAdd@builtinSetAdd
238//: [object Set]
239print(m.has(25));
240//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
241//: true
242
243tryAdd(m2, 25);
244//aot: [trace] aot inline builtin: Set.add, caller function name:#*#doAdd@builtinSetAdd
245//: [object Set]
246print(m2.has(25));
247//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
248//: true
249
250tryAdd(m3, 25);
251//aot: [trace] aot inline builtin: Set.add, caller function name:#*#doAdd@builtinSetAdd
252//: [object Set]
253print(m3.has(25));
254//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
255//: true
256
257tryAdd(m4);
258//aot: [trace] Check Type: BuiltinInstanceHClassMismatch
259//aot: [trace] aot inline builtin: Set.add, caller function name:#*#doAdd@builtinSetAdd
260//: [object Set]
261print(m3.has(25));
262//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
263//: true
264
265print("case 2");
266//: case 2
267let mimicSet = {
268    add: trueadd
269}
270let mm = new Set([1]);
271
272tryAdd(mm, -200);
273//aot: [trace] aot inline builtin: Set.add, caller function name:#*#doAdd@builtinSetAdd
274//: [object Set]
275print(mm.has(-200));
276//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
277//: true
278
279if (ArkTools.isAOTCompiled(tryAdd)) {
280    Object.setPrototypeOf(mm, mimicSet)
281}
282
283tryAdd(mm, 32);
284//aot: [trace] Check Type: BuiltinInstanceHClassMismatch
285//pgo: [object Set]
286//aot: [object Object]
287
288print("case 3") //: case 3
289if (ArkTools.isAOTCompiled(tryAdd)) {
290    Set.prototype.add = function(x: any) {
291        return "prototype";
292    }
293}
294
295tryAdd(m, -1);
296//aot: [trace] aot inline builtin: Set.add, caller function name:#*#doAdd@builtinSetAdd
297//pgo: [object Set]
298//aot: prototype
299print(m.has(-1));
300//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetAdd
301//: true
302
303function checkObjWithSetProto() {
304    let o = {};
305    Object.setPrototypeOf(o, Set.prototype);
306    try {
307        o.add(1);
308    } catch(e) {
309        print(e);
310    }
311}
312
313//aot: [trace] Check Type: NotCallTarget1
314//: TypeError: obj is not JSSet
315checkObjWithSetProto();
316