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