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