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