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 doIsNaN(x: any): any {
26    return isNaN(x);
27}
28
29function printIsNaN(x: any) {
30    try {
31        print(doIsNaN(x));
32    } finally {
33    }
34}
35
36var x = "x"
37x -= 1
38//aot: [trace] aot inline builtin: isNan, caller function name:func_main_0@builtinGlobalIsNan
39print(isNaN(x)) //: true
40
41// Check with single int param
42//aot: [trace] aot inline builtin: isNan, caller function name:func_main_0@builtinGlobalIsNan
43print(isNaN(0)); //: false
44//aot: [trace] aot inline builtin: isNan, caller function name:func_main_0@builtinGlobalIsNan
45print(isNaN(3)); //: false
46//aot: [trace] aot inline builtin: isNan, caller function name:func_main_0@builtinGlobalIsNan
47print(isNaN(-5)); //: false
48
49// Check with single float param
50//aot: [trace] aot inline builtin: isNan, caller function name:func_main_0@builtinGlobalIsNan
51print(isNaN(-1.5)); //: false
52//aot: [trace] aot inline builtin: isNan, caller function name:func_main_0@builtinGlobalIsNan
53print(isNaN(1.5)); //: false
54
55// Check with special float params
56//aot: [trace] aot inline builtin: isNan, caller function name:func_main_0@builtinGlobalIsNan
57print(isNaN(Infinity)); //: false
58//aot: [trace] aot inline builtin: isNan, caller function name:func_main_0@builtinGlobalIsNan
59print(isNaN(-Infinity)); //: false
60//aot: [trace] aot inline builtin: isNan, caller function name:func_main_0@builtinGlobalIsNan
61print(isNaN(NaN)); //: true
62//aot: [trace] aot inline builtin: Math.exp, caller function name:func_main_0@builtinGlobalIsNan
63//aot: [trace] aot inline builtin: isNan, caller function name:func_main_0@builtinGlobalIsNan
64print(isNaN(Math.exp(800))); //: false
65
66// Check with 2 params
67//aot: [trace] aot inline builtin: isNan, caller function name:func_main_0@builtinGlobalIsNan
68print(isNaN(NaN, Infinity)); //: true
69
70// Check with 3 params
71//aot: [trace] aot inline builtin: isNan, caller function name:func_main_0@builtinGlobalIsNan
72print(isNaN(NaN, 3, Infinity)); //: true
73
74
75// Replace standard builtin
76let true_is_nan = isNaN
77isNaN = replace
78print(isNaN(NaN)); //: NaN
79isNaN = true_is_nan
80
81//aot: [trace] aot inline builtin: isNan, caller function name:#*#doIsNaN@builtinGlobalIsNan
82printIsNaN(-3);    //: false
83//aot: [trace] aot inline builtin: isNan, caller function name:#*#doIsNaN@builtinGlobalIsNan
84//aot: [trace] Check Type: NotNumber1
85printIsNaN("abc"); //: true
86//aot: [trace] aot inline builtin: isNan, caller function name:#*#doIsNaN@builtinGlobalIsNan
87//aot: [trace] Check Type: NotNumber1
88printIsNaN("abc"); //: true
89//aot: [trace] aot inline builtin: isNan, caller function name:#*#doIsNaN@builtinGlobalIsNan
90printIsNaN(-12); //: false
91
92// Call standard builtin with non-number param
93//aot: [trace] aot inline builtin: isNan, caller function name:#*#doIsNaN@builtinGlobalIsNan
94//aot: [trace] Check Type: NotNumber1
95printIsNaN("abc"); //: true
96//aot: [trace] aot inline builtin: isNan, caller function name:#*#doIsNaN@builtinGlobalIsNan
97//aot: [trace] Check Type: NotNumber1
98printIsNaN("-12"); //: false
99
100if (ArkTools.isAOTCompiled(doIsNaN)) {
101    // Replace standard builtin after call to standard builtin was profiled
102    isNaN = replace
103}
104printIsNaN(-12); //pgo: false
105                 //aot: [trace] Check Type: NotCallTarget1
106                 //aot: -12
107printIsNaN("abc"); //pgo: true
108                   //aot: [trace] Check Type: NotCallTarget1
109                   //aot: abc
110isNaN = true_is_nan
111
112// Check IR correctness inside try-block
113try {
114    //aot: [trace] aot inline builtin: isNan, caller function name:#*#doIsNaN@builtinGlobalIsNan
115    printIsNaN(-12); //: false
116    //aot: [trace] aot inline builtin: isNan, caller function name:#*#doIsNaN@builtinGlobalIsNan
117    printIsNaN(NaN); //: true
118    //aot: [trace] aot inline builtin: isNan, caller function name:#*#doIsNaN@builtinGlobalIsNan
119    //aot: [trace] Check Type: NotNumber1
120    printIsNaN("abc"); //: true
121} catch (e) {
122}
123
124let obj = {};
125obj.valueOf = (() => { return -23; })
126//aot: [trace] aot inline builtin: isNan, caller function name:func_main_0@builtinGlobalIsNan
127//aot: [trace] Check Type: NotNumber1
128print(isNaN(obj)); //: false
129
130function Throwing() {
131    this.value = -14;
132}
133Throwing.prototype.valueOf = function() {
134    if (this.value > 0) {
135        throw new Error("already positive");
136    }
137    return this.value;
138}
139let throwingObj = new Throwing();
140
141try {
142    print(isNaN(throwingObj)); //: false
143    throwingObj.value = 10;
144    print(isNaN(throwingObj)); //: Error: already positive
145} catch(e) {
146    print(e);
147} finally {
148    print(isNaN(obj)); //: false
149}