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 doHas(x: any) {
26    return mySet.has(x);
27}
28
29function printHas(x: any) {
30    try {
31        print(doHas(x));
32    } finally {
33    }
34}
35
36let mySet = new Set([0, 0.0, -5, 2.5, 1e-78, NaN, "xyz", "12345"]);
37
38// Check without params
39//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetHas
40print(mySet.has()); //: false
41
42// Check with adding element undefined
43//aot: [trace] aot inline builtin: Set.add, caller function name:func_main_0@builtinSetHas
44mySet.add(undefined);
45//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetHas
46print(mySet.has()); //: true
47
48// Check with single param
49//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetHas
50print(mySet.has(0)); //: true
51//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetHas
52print(mySet.has(3)); //: false
53//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetHas
54print(mySet.has(2.5)); //: true
55//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetHas
56print(mySet.has(NaN)); //: true
57
58// Check with 2 params
59//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetHas
60print(mySet.has(0, 0)); //: true
61
62// Check with 3 params
63//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetHas
64print(mySet.has(-21, 10.2, 15)); //: false
65
66// Check with 4 params
67//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetHas
68print(mySet.has(2.5, -800, 0.56, 0)); //: true
69
70// Check after inserting elements
71//aot: [trace] aot inline builtin: Set.add, caller function name:func_main_0@builtinSetHas
72mySet.add(-5);
73//aot: [trace] aot inline builtin: Set.add, caller function name:func_main_0@builtinSetHas
74mySet.add(133.33);
75//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetHas
76print(mySet.has(-5)); //: true
77//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetHas
78print(mySet.has(133.33)); //: true
79
80// Replace standard builtin
81let true_has = mySet.has
82mySet.has = replace
83
84// no deopt
85print(mySet.has(2.5)); //: 2.5
86mySet.has = true_has
87
88function checkObjWithSetProto() {
89    let o = {};
90    Object.setPrototypeOf(o, Set.prototype);
91    try {
92        print((o as Set<number>).has(1));
93    } catch(e) {
94        print(e);
95    }
96}
97
98//aot: [trace] Check Type: NotCallTarget1
99//: TypeError: obj is not JSSet
100checkObjWithSetProto();
101
102//aot: [trace] aot inline builtin: Set.has, caller function name:#*#doHas@builtinSetHas
103printHas(-5); //: true
104// Call standard builtin with non-number param
105//aot: [trace] aot inline builtin: Set.has, caller function name:#*#doHas@builtinSetHas
106printHas("abc"); //: false
107//aot: [trace] aot inline builtin: Set.has, caller function name:#*#doHas@builtinSetHas
108printHas("-5"); //: false
109//aot: [trace] aot inline builtin: Set.has, caller function name:#*#doHas@builtinSetHas
110printHas("xyz"); //: true
111
112if (ArkTools.isAOTCompiled(printHas)) {
113    // Replace standard builtin after call to standard builtin was profiled
114    mySet.has = replace
115}
116printHas(2.5); //pgo: true
117//aot: [trace] Check Type: NotCallTarget1
118//aot: 2.5
119
120printHas("abc"); //pgo: false
121//aot: [trace] Check Type: NotCallTarget1
122//aot: abc
123
124mySet.has = true_has
125
126// Check IR correctness inside try-block
127try {
128    //aot: [trace] aot inline builtin: Set.has, caller function name:#*#doHas@builtinSetHas
129    printHas(NaN); //: true
130    //aot: [trace] aot inline builtin: Set.has, caller function name:#*#doHas@builtinSetHas
131    printHas("abc"); //: false
132} catch (e) {
133}
134
135let obj = {};
136obj.valueOf = (() => { return 0; })
137//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetHas
138print(mySet.has(obj)); //: false
139
140function Throwing() {
141    this.value = 2.5;
142    this.valueOf = function() {
143        if (this.value > 0) {
144            throw new Error("already positive");
145        }
146        return this.value;
147    }
148}
149
150let throwingObj = new Throwing();
151try {
152    //aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetHas
153    print(mySet.has(throwingObj)); //: false
154} catch(e) {
155    print(e);
156} finally {
157    //aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetHas
158    print(mySet.has(obj)); //: false
159}
160
161// Check after clearing
162mySet.clear();
163//aot: [trace] aot inline builtin: Set.clear, caller function name:func_main_0@builtinSetHas
164print(mySet.has(0));
165//aot: [trace] aot inline builtin: Set.has, caller function name:func_main_0@builtinSetHas
166//: false
167