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