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 function print(str:any):string;
17
18function assert_true(condition: boolean): void
19{
20    if (!condition) {
21        print("assert fail");
22    }
23}
24
25function run(cb: () => void) {
26    let cnt: number = 20;
27    for (let i = 0; i < cnt; ++i) {
28        cb();
29    }
30}
31
32class Base {
33    name: string;
34    value: number;
35    constructor(name: string, value: number) {
36        this.name = name;
37        this.value = value;
38    }
39}
40
41class Child extends Base {}
42
43function testChild0Arg() {
44    let c = new Child();
45    assert_true(c.name === undefined);
46    assert_true(c.value === undefined);
47}
48
49function testChild1Arg() {
50    let c = new Child("one");
51    assert_true(c.name === "one");
52    assert_true(c.value === undefined);
53}
54
55function testChild2Arg() {
56    let c = new Child("two", 2);
57    assert_true(c.name === "two");
58    assert_true(c.value === 2);
59}
60
61function testChild3Arg() {
62    let c = new Child("three", 3, "extra");
63    assert_true(c.name === "three");
64    assert_true(c.value === 3);
65}
66
67class GrandChild extends Child {}
68
69function testGrandChild0Arg() {
70    let c = new GrandChild();
71    assert_true(c.name === undefined);
72    assert_true(c.value === undefined);
73}
74
75function testGrandChild1Arg() {
76    let c = new GrandChild("one");
77    assert_true(c.name === "one");
78    assert_true(c.value === undefined);
79}
80
81function testGrandChild2Arg() {
82    let c = new GrandChild("two", 2);
83    assert_true(c.name === "two");
84    assert_true(c.value === 2);
85}
86
87function testGrandChild3Arg() {
88    let c = new GrandChild("three", 3, "extra");
89    assert_true(c.name === "three");
90    assert_true(c.value === 3);
91}
92
93class BaseRestArgs {
94    args: Object[] = [];
95    constructor(...args) {
96        for (const arg of args) {
97            this.args.push(arg);
98        }
99    }
100}
101
102class ChildRestArgs extends BaseRestArgs {}
103
104function testChildRestArgs0Arg() {
105    let c = new ChildRestArgs();
106    assert_true(c.args.length === 0);
107}
108
109function testChildRestArgs1Arg() {
110    let c = new ChildRestArgs("one");
111    assert_true(c.args.length === 1);
112    assert_true(c.args[0] === "one");
113}
114
115function testChildRestArgs2Arg() {
116    let c = new ChildRestArgs("two", 2);
117    assert_true(c.args.length === 2);
118    assert_true(c.args[0] === "two");
119    assert_true(c.args[1] === 2);
120}
121
122function testChildRestArgs3Arg() {
123    let c = new ChildRestArgs("three", 3, "extra");
124    assert_true(c.args.length === 3);
125    assert_true(c.args[0] === "three");
126    assert_true(c.args[1] === 3);
127    assert_true(c.args[2] === "extra");
128}
129
130class GrandChildRestArgs extends ChildRestArgs {}
131
132function testGrandChildRestArgs0Arg() {
133    let c = new GrandChildRestArgs();
134    assert_true(c.args.length === 0);
135}
136
137function testGrandChildRestArgs1Arg() {
138    let c = new GrandChildRestArgs("one");
139    assert_true(c.args.length === 1);
140    assert_true(c.args[0] === "one");
141}
142
143function testGrandChildRestArgs2Arg() {
144    let c = new GrandChildRestArgs("two", 2);
145    assert_true(c.args.length === 2);
146    assert_true(c.args[0] === "two");
147    assert_true(c.args[1] === 2);
148}
149
150function testGrandChildRestArgs3Arg() {
151    let c = new GrandChildRestArgs("three", 3, "extra");
152    assert_true(c.args.length === 3);
153    assert_true(c.args[0] === "three");
154    assert_true(c.args[1] === 3);
155    assert_true(c.args[2] === "extra");
156}
157
158class BaseArguments {
159    args: Object[] = [];
160    constructor() {
161        for (const arg of arguments) {
162            this.args.push(arg);
163        }
164    }
165}
166
167class ChildArguments extends BaseArguments {}
168
169function testChildArguments0Arg() {
170    let c = new ChildArguments();
171    assert_true(c.args.length === 0);
172}
173
174function testChildArguments1Arg() {
175    let c = new ChildArguments("one");
176    assert_true(c.args.length === 1);
177    assert_true(c.args[0] === "one");
178}
179
180function testChildArguments2Arg() {
181    let c = new ChildArguments("two", 2);
182    assert_true(c.args.length === 2);
183    assert_true(c.args[0] === "two");
184    assert_true(c.args[1] === 2);
185}
186
187function testChildArguments3Arg() {
188    let c = new ChildArguments("three", 3, "extra");
189    assert_true(c.args.length === 3);
190    assert_true(c.args[0] === "three");
191    assert_true(c.args[1] === 3);
192    assert_true(c.args[2] === "extra");
193}
194
195class GrandChildArguments extends ChildArguments {
196}
197
198function testGrandChildArguments0Arg() {
199    let c = new GrandChildArguments();
200    assert_true(c.args.length === 0);
201}
202
203function testGrandChildArguments1Arg() {
204    let c = new GrandChildArguments("one");
205    assert_true(c.args.length === 1);
206    assert_true(c.args[0] === "one");
207}
208
209function testGrandChildArguments2Arg() {
210    let c = new GrandChildArguments("two", 2);
211    assert_true(c.args.length === 2);
212    assert_true(c.args[0] === "two");
213    assert_true(c.args[1] === 2);
214}
215
216function testGrandChildArguments3Arg() {
217    let c = new GrandChildArguments("three", 3, "extra");
218    assert_true(c.args.length === 3);
219    assert_true(c.args[0] === "three");
220    assert_true(c.args[1] === 3);
221    assert_true(c.args[2] === "extra");
222}
223
224class BaseCornerCase {
225    name: string = ""
226    value: number = 0;
227}
228
229class ChildUndefined extends BaseCornerCase {}
230class ChildNull extends BaseCornerCase {}
231class ChildObj extends BaseCornerCase {}
232class ChildNumber extends BaseCornerCase {}
233class ChildString extends BaseCornerCase {}
234class ChildArrow extends BaseCornerCase {}
235class ChildFunction extends BaseCornerCase {}
236
237function runChildCornerCase(ctor: Function, replacement: any) {
238    let cnt = 20;
239    for (let i = 0; i < cnt; ++i) {
240        if (i == cnt - 1) {
241            ctor.__proto__ = replacement;  // at the last iteration, change super ctor
242        }
243        try {
244            new ctor();
245        } catch (e) {
246            print(ctor.name);
247            print(e);
248        }
249    }
250    assert_true(ArkTools.isAOTCompiled(ctor));
251}
252
253function testChildCornerCases() {
254    runChildCornerCase(ChildUndefined, undefined);      // normal
255    runChildCornerCase(ChildNull, null);                // error: super is not ctor
256    runChildCornerCase(ChildObj, {xxx: "yyy"});         // error: super is not ctor
257    runChildCornerCase(ChildNumber, 111);               // normal
258    runChildCornerCase(ChildString, "hello");           // normal
259    runChildCornerCase(ChildArrow, () => {});           // error: super is not ctor
260    runChildCornerCase(ChildFunction, function () {});  // normal
261    assert_true(ArkTools.isAOTCompiled(BaseCornerCase));
262}
263
264
265run(testChild0Arg);
266run(testChild1Arg);
267run(testChild2Arg);
268run(testChild3Arg);
269run(testGrandChild0Arg);
270run(testGrandChild1Arg);
271run(testGrandChild2Arg);
272run(testGrandChild3Arg);
273assert_true(ArkTools.isAOTCompiled(Base));
274assert_true(ArkTools.isAOTCompiled(Child));
275assert_true(ArkTools.isAOTCompiled(GrandChild));
276
277run(testChildRestArgs0Arg);
278run(testChildRestArgs1Arg);
279run(testChildRestArgs2Arg);
280run(testChildRestArgs3Arg);
281run(testGrandChildRestArgs0Arg);
282run(testGrandChildRestArgs1Arg);
283run(testGrandChildRestArgs2Arg);
284run(testGrandChildRestArgs3Arg);
285assert_true(ArkTools.isAOTCompiled(BaseRestArgs));
286assert_true(ArkTools.isAOTCompiled(ChildRestArgs));
287assert_true(ArkTools.isAOTCompiled(GrandChildRestArgs));
288
289run(testChildArguments0Arg);
290run(testChildArguments1Arg);
291run(testChildArguments2Arg);
292run(testChildArguments3Arg);
293run(testGrandChildArguments0Arg);
294run(testGrandChildArguments1Arg);
295run(testGrandChildArguments2Arg);
296run(testGrandChildArguments3Arg);
297assert_true(ArkTools.isAOTCompiled(BaseArguments));
298assert_true(ArkTools.isAOTCompiled(ChildArguments));
299assert_true(ArkTools.isAOTCompiled(GrandChildArguments));
300
301testChildCornerCases();
302
303print("success");
304