• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021 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
16import {
17    expect
18} from 'chai';
19import 'mocha';
20import {
21    EcmaCopyrestargs,
22    EcmaDefinefuncdyn,
23    EcmaReturnundefined,
24    EcmaStglobalvar,
25    EcmaStlettoglobalrecord,
26    EcmaStricteqdyn,
27    Imm,
28    Jeqz,
29    Label,
30    LdaDyn,
31    LdaiDyn,
32    ResultType,
33    StaDyn,
34    VReg
35} from "../../src/irnodes";
36import {
37    GlobalVariable,
38    LocalVariable
39} from "../../src/variable";
40import { checkInstructions, compileAllSnippet, SnippetCompiler } from "../utils/base";
41
42describe("FunctionDeclarationTest", function () {
43    it('function definition in the global scope', function () {
44        let snippetCompiler = new SnippetCompiler();
45        snippetCompiler.compile("function foo() {}");
46        let funcName = "foo";
47        let expected = [
48            new EcmaDefinefuncdyn(funcName, new Imm(0), new VReg()),
49            new EcmaStglobalvar(funcName),
50            new EcmaReturnundefined()
51        ];
52        let insns = snippetCompiler.getGlobalInsns();
53        let globalScope = snippetCompiler.getGlobalScope();
54        expect(checkInstructions(insns, expected)).to.be.true;
55        let foo = globalScope!.findLocal(funcName);
56        expect(foo != undefined).to.be.true;
57        expect(foo instanceof GlobalVariable).to.be.true;
58    });
59
60    it('function redefinition in the global scope', function () {
61        let snippetCompiler = new SnippetCompiler();
62        snippetCompiler.compile(`
63      function foo() {}
64      function foo() {}
65      `);
66        let expected = [
67            new EcmaDefinefuncdyn("#2#foo", new Imm(0), new VReg()),
68            new EcmaStglobalvar("foo"),
69            new EcmaReturnundefined()
70        ];
71        let insns = snippetCompiler.getGlobalInsns();
72        let globalScope = snippetCompiler.getGlobalScope();
73        expect(checkInstructions(insns, expected)).to.be.true;
74        let foo = globalScope!.findLocal("foo");
75        expect(foo != undefined).to.be.true;
76        expect(foo instanceof GlobalVariable).to.be.true;
77    });
78
79    it('function definition inside a function', function () {
80        let snippetCompiler = new SnippetCompiler();
81        snippetCompiler.compile(`function out() {function foo() {}}`);
82        let funcReg = new VReg();
83        let expected = [
84            new EcmaDefinefuncdyn("foo", new Imm(0), new VReg()),
85            new StaDyn(funcReg),
86
87            new EcmaReturnundefined()
88        ];
89        let functionPg = snippetCompiler.getPandaGenByName("out");
90        let insns = functionPg!.getInsns();
91        let functionScope = functionPg!.getScope();
92
93        expect(checkInstructions(insns!, expected)).to.be.true;
94        let foo = functionScope!.findLocal("foo");
95        expect(foo != undefined).to.be.true;
96        expect(foo instanceof LocalVariable).to.be.true;
97        let parameterLength = functionPg!.getParameterLength();
98        expect(parameterLength == 0).to.be.true;
99    });
100
101    it("function expression", function () {
102        let snippetCompiler = new SnippetCompiler();
103        snippetCompiler.compile("let foo = function() {}");
104        let insns = snippetCompiler.getGlobalInsns();
105        let expected = [
106            new EcmaDefinefuncdyn("foo", new Imm(0), new VReg()),
107            new EcmaStlettoglobalrecord("foo"),
108            new EcmaReturnundefined()
109        ];
110        expect(checkInstructions(insns, expected)).to.be.true;
111    });
112
113    it("Parameters with initializer", function () {
114        let compilerunit = compileAllSnippet("function test(a, b = 1) {}");
115        let undefinedVReg = new VReg();
116        let value = new VReg();
117        let endLabel = new Label();
118
119        let expected_main = [
120            new EcmaDefinefuncdyn("test", new Imm(1), new VReg()),
121            new EcmaStglobalvar("test"),
122            new EcmaReturnundefined()
123        ];
124        let expected_func = [
125            // func_test_0
126            new LdaDyn(new VReg()),
127            new EcmaStricteqdyn(undefinedVReg),
128            new Jeqz(endLabel),
129            new LdaiDyn(new Imm(1)),
130            new StaDyn(value),
131            endLabel,
132            new EcmaReturnundefined(),
133        ];
134
135        compilerunit.forEach(element => {
136            if (element.internalName == "func_main_0") {
137                let insns = element.getInsns();
138                expect(checkInstructions(insns, expected_main)).to.be.true;
139            } else if (element.internalName == "test") {
140                let insns = element.getInsns();
141                expect(checkInstructions(insns, expected_func)).to.be.true;
142                let parameterLength = element.getParameterLength();
143                expect(parameterLength == 1).to.be.true;
144            }
145        });
146    });
147
148    it("Rest Parameters", function () {
149        let snippetCompiler = new SnippetCompiler();
150        snippetCompiler.compile(`function test(a, ...b) {}`);
151
152        let idx = new Imm(1);
153        let lastParam = new VReg();
154        let expected_func = [
155            // func_test_0
156            new EcmaCopyrestargs(idx),
157            new StaDyn(lastParam),
158            new EcmaReturnundefined(),
159        ];
160
161        let functionPg = snippetCompiler.getPandaGenByName("test");
162        let insns = functionPg!.getInsns();
163
164        expect(checkInstructions(insns, expected_func)).to.be.true;
165    });
166});
167