• 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 { DiagnosticCode, DiagnosticError } from '../../src/diagnostic';
21import {
22    Createemptyobject,
23    Getnextpropname,
24    Getpropiterator,
25    Returnundefined,
26    Strictnoteq,
27    Tryldglobalbyname,
28    Trystglobalbyname,
29    Jeqz,
30    Jmp,
31    Label,
32    Lda,
33    Sta,
34    VReg,
35    Imm,
36    IRNode
37} from "../../src/irnodes";
38import { checkInstructions, compileMainSnippet } from "../utils/base";
39import { creatAstFromSnippet } from "../utils/asthelper"
40import { PandaGen } from '../../src/pandagen';
41
42describe("forInLoopTest", function () {
43    it("forInLoopwithEmptyObject", function () {
44        let insns = compileMainSnippet("for (let prop in {}) {}");
45        IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined);
46        let prop = new VReg();
47        let temp = new VReg();
48        let objInstance = new VReg();
49        let iterReg = new VReg();
50        let rhs = new VReg();
51
52        let loopStartLabel = new Label();
53        let loopEndLabel = new Label();
54        let expected = [
55            new Createemptyobject(),
56            new Sta(objInstance),
57            new Getpropiterator(),
58            new Sta(iterReg),
59
60            loopStartLabel,
61            new Getnextpropname(iterReg),
62            new Sta(rhs),
63            new Strictnoteq(new Imm(0), temp),
64            new Jeqz(loopEndLabel),
65            new Lda(rhs),
66            new Sta(prop),
67            new Jmp(loopStartLabel),
68
69            loopEndLabel,
70            new Returnundefined()
71        ];
72        expect(checkInstructions(insns, expected)).to.be.true;
73
74        let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz));
75
76        expect(jumps.length).to.equal(2);
77    });
78
79    it("forInLoopWithExpressionAsLoopVariable", function () {
80        let insns = compileMainSnippet(`
81      let prop;
82      let obj;
83      for (prop in obj) {
84      }
85      `);
86        let temp = new VReg();
87        let iterReg = new VReg();
88        let rhs = new VReg();
89
90        let loopStartLabel = new Label();
91        let loopEndLabel = new Label();
92        IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined);
93        (<PandaGen>(IRNode.pg)).updateIcSize(2);
94        let expected = [
95            new Tryldglobalbyname(new Imm(0), 'obj'),
96            new Getpropiterator(),
97            new Sta(iterReg),
98
99            loopStartLabel,
100            new Getnextpropname(iterReg),
101            new Sta(rhs),
102            new Strictnoteq(new Imm(1), temp),
103            new Jeqz(loopEndLabel),
104            new Lda(rhs),
105            new Trystglobalbyname(new Imm(2), 'prop'),
106            new Jmp(loopStartLabel),
107
108            loopEndLabel,
109        ];
110
111        insns = insns.slice(4, insns.length - 1);
112        expect(checkInstructions(insns, expected)).to.be.true;
113
114        let jmp = <Jmp>insns.find(item => (item instanceof Jmp));
115        let jeqz = <Jeqz>insns.find(item => (item instanceof Jeqz));
116        expect(jmp.getTarget()).to.equal(insns[3]);
117        expect(jeqz.getTarget()).to.equal(insns[insns.length - 1]);
118    });
119
120    it("forInLoopwithObjectwithContinue", function () {
121        let insns = compileMainSnippet("for (let prop in {}) {continue; }");
122        let prop = new VReg();
123        let temp = new VReg();
124        let objInstance = new VReg();
125        let iterReg = new VReg();
126        let rhs = new VReg();
127
128        let loopStartLabel = new Label();
129        let loopEndLabel = new Label();
130        IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined);
131        let expected = [
132            new Createemptyobject(),
133            new Sta(objInstance),
134            new Getpropiterator(),
135            new Sta(iterReg),
136
137            loopStartLabel,
138            new Getnextpropname(iterReg),
139            new Sta(rhs),
140            new Strictnoteq(new Imm(0), temp),
141            new Jeqz(loopEndLabel),
142            new Lda(rhs),
143            new Sta(prop),
144            new Jmp(loopStartLabel),
145            new Jmp(loopStartLabel),
146
147            loopEndLabel,
148            new Returnundefined()
149        ];
150        expect(checkInstructions(insns, expected)).to.be.true;
151
152        let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz));
153
154        expect(jumps.length).to.equal(3);
155    });
156
157    it("forInLoopwithObjectwithBreak", function () {
158        let insns = compileMainSnippet("for (let prop in {}) {break; }");
159        let prop = new VReg();
160        let temp = new VReg();
161        let objInstance = new VReg();
162        let iterReg = new VReg();
163        let rhs = new VReg();
164
165        let loopStartLabel = new Label();
166        let loopEndLabel = new Label();
167        IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined);
168        let expected = [
169            new Createemptyobject(),
170            new Sta(objInstance),
171            new Getpropiterator(),
172            new Sta(iterReg),
173
174            loopStartLabel,
175            new Getnextpropname(iterReg),
176            new Sta(rhs),
177            new Strictnoteq(new Imm(0), temp),
178            new Jeqz(loopEndLabel),
179            new Lda(rhs),
180            new Sta(prop),
181            new Jmp(loopEndLabel),
182            new Jmp(loopStartLabel),
183
184            loopEndLabel,
185            new Returnundefined()
186        ];
187        expect(checkInstructions(insns, expected)).to.be.true;
188
189        let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz));
190
191        expect(jumps.length).to.equal(3);
192    });
193
194    it("ForIn SyntaxError", function () {
195        let source: string = `for ([(x, y)] in {}) { }`;
196        let errorThrown = false;
197        try {
198            compileMainSnippet(source);
199        } catch (err) {
200            expect(err instanceof DiagnosticError).to.be.true;
201            expect((<DiagnosticError>err).code).to.equal(DiagnosticCode.Property_destructuring_pattern_expected);
202            errorThrown = true;
203        }
204        expect(errorThrown).to.be.true;
205    });
206});
207