• 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    Callthis0,
23    Createemptyarray,
24    Getiterator,
25    Isfalse,
26    Ldobjbyname,
27    Returnundefined,
28    Strictnoteq,
29    Throw,
30    ThrowIfnotobject,
31    Imm,
32    Jeqz,
33    Jmp,
34    Label,
35    Lda,
36    Sta,
37    VReg,
38    IRNode
39} from "../../src/irnodes";
40import { checkInstructions, compileMainSnippet } from "../utils/base";
41import { creatAstFromSnippet } from "../utils/asthelper"
42import { PandaGen } from '../../src/pandagen';
43
44describe("ForOfLoopTest", function () {
45    it("forOfLoopWithEmptyArray", function () {
46        let insns = compileMainSnippet("for (let a of []) {}");
47        IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined);
48        let a = new VReg();
49        let arrInstance = new VReg();
50        let iterReg = new VReg();
51        let nextMethodReg = new VReg();
52        let resultObj = new VReg();
53        let exceptionVreg = new VReg();
54        let trueReg = new VReg();
55        let done = new VReg();
56        let value = new VReg();
57
58        let loopStartLabel = new Label();
59        let loopEndLabel = new Label();
60        let tryBeginLabel = new Label();
61        let tryEndLabel = new Label();
62        let catchBeginLabel = new Label();
63        let isDone = new Label();
64
65        let expected = [
66            new Createemptyarray(new Imm(0)),
67            new Sta(arrInstance),
68            new Getiterator(new Imm(1)),
69            new Sta(iterReg),
70            new Lda(iterReg),
71            new Ldobjbyname(new Imm(2), "next"),
72            new Sta(nextMethodReg),
73
74            new Lda(new VReg()),
75            new Sta(done),
76
77            tryBeginLabel,
78            new Lda(trueReg),
79            new Sta(done),
80            loopStartLabel,
81            new Lda(nextMethodReg),
82            new Callthis0(new Imm(4), iterReg),
83            new Sta(resultObj),
84            new ThrowIfnotobject(resultObj),
85            new Lda(resultObj),
86            new Ldobjbyname(new Imm(5), "done"),
87            new Isfalse(),
88            new Jeqz(loopEndLabel),
89            new Lda(resultObj),
90            new Ldobjbyname(new Imm(7), "value"),
91            new Sta(value),
92
93            new Lda(new VReg()),
94            new Sta(done),
95
96            new Lda(value),
97            new Sta(a),
98            tryEndLabel,
99
100            new Jmp(loopStartLabel),
101
102            catchBeginLabel,
103            new Sta(exceptionVreg),
104            new Lda(done),
105            new Strictnoteq(new Imm(9), trueReg),
106            new Jeqz(isDone),
107            new Lda(iterReg),
108            new Ldobjbyname(new Imm(10), "return"),
109            new Sta(nextMethodReg),
110            new Strictnoteq(new Imm(12), new VReg()),
111            new Jeqz(isDone),
112            new Lda(nextMethodReg),
113            new Callthis0(new Imm(13), iterReg),
114            isDone,
115            new Lda(exceptionVreg),
116            new Throw(),
117
118            loopEndLabel,
119            new Returnundefined()
120        ];
121        expect(checkInstructions(insns, expected)).to.be.true;
122
123        let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz));
124
125        expect(jumps.length).to.equal(4);
126    });
127
128    it("forOfLoopWithContinue", function () {
129        let insns = compileMainSnippet("for (let a of []) {continue;}");
130        IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined);
131        let a = new VReg();
132        let arrInstance = new VReg();
133        let resultObj = new VReg();
134        let trueReg = new VReg();
135        let iterReg = new VReg();
136        let exceptionVreg = new VReg();
137        let nextMethodReg = new VReg();
138        let done = new VReg();
139        let value = new VReg();
140
141        let loopStartLabel = new Label();
142        let loopEndLabel = new Label();
143        let tryBeginLabel = new Label();
144        let tryEndLabel = new Label();
145        let catchBeginLabel = new Label();
146        let isDone = new Label();
147        let insertedtryBeginLabel = new Label();
148        let insertedtryEndLabel = new Label();
149
150        let expected = [
151            new Createemptyarray(new Imm(0)),
152            new Sta(arrInstance),
153            new Getiterator(new Imm(1)),
154            new Sta(iterReg),
155            new Lda(iterReg),
156            new Ldobjbyname(new Imm(2), "next"),
157            new Sta(nextMethodReg),
158
159            new Lda(new VReg()),
160            new Sta(done),
161
162            tryBeginLabel,
163            new Lda(trueReg),
164            new Sta(done),
165            loopStartLabel,
166            new Lda(nextMethodReg),
167            new Callthis0(new Imm(4), iterReg),
168            new Sta(resultObj),
169            new ThrowIfnotobject(resultObj),
170            new Lda(resultObj),
171            new Ldobjbyname(new Imm(5), "done"),
172            new Isfalse(),
173            new Jeqz(loopEndLabel),
174            new Lda(resultObj),
175            new Ldobjbyname(new Imm(7), "value"),
176            new Sta(value),
177
178            new Lda(new VReg()),
179            new Sta(done),
180
181            new Lda(value),
182            new Sta(a),
183
184            insertedtryBeginLabel,
185            insertedtryEndLabel,
186            new Jmp(loopStartLabel),
187
188            tryEndLabel,
189
190            new Jmp(loopStartLabel),
191
192            catchBeginLabel,
193            new Sta(exceptionVreg),
194            new Lda(done),
195            new Strictnoteq(new Imm(9), trueReg),
196            new Jeqz(isDone),
197            new Lda(iterReg),
198            new Ldobjbyname(new Imm(10), "return"),
199            new Sta(nextMethodReg),
200            new Strictnoteq(new Imm(12), new VReg()),
201            new Jeqz(isDone),
202            new Lda(nextMethodReg),
203            new Callthis0(new Imm(13), iterReg),
204            isDone,
205            new Lda(exceptionVreg),
206            new Throw(),
207
208            loopEndLabel,
209            new Returnundefined()
210        ];
211        expect(checkInstructions(insns, expected)).to.be.true;
212
213        let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz));
214
215        expect(jumps.length).to.equal(5);
216    });
217
218    it("forOfLoopWithBreak", function () {
219        let insns = compileMainSnippet("for (let a of []) {break;}");
220        IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined);
221        let a = new VReg();
222        let arrInstance = new VReg();
223        let resultObj = new VReg();
224        let exceptionVreg = new VReg();
225        let iterReg = new VReg();
226        let trueReg = new VReg();
227        let nextMethodReg = new VReg();
228        let done = new VReg();
229        let value = new VReg();
230        let loopStartLabel = new Label();
231        let loopEndLabel = new Label();
232        let tryBeginLabel = new Label();
233        let tryEndLabel = new Label();
234        let catchBeginLabel = new Label();
235        let isDone = new Label();
236        let noReturn = new Label();
237        let insertedtryBeginLabel = new Label();
238        let insertedtryEndLabel = new Label();
239
240        let expected = [
241            new Createemptyarray(new Imm(0)),
242            new Sta(arrInstance),
243            new Getiterator(new Imm(1)),
244            new Sta(iterReg),
245            new Lda(iterReg),
246            new Ldobjbyname(new Imm(2), "next"),
247            new Sta(nextMethodReg),
248
249            new Lda(new VReg()),
250            new Sta(done),
251
252            tryBeginLabel,
253            new Lda(trueReg),
254            new Sta(done),
255            loopStartLabel,
256            new Lda(nextMethodReg),
257            new Callthis0(new Imm(4), iterReg),
258            new Sta(resultObj),
259            new ThrowIfnotobject(resultObj),
260            new Lda(resultObj),
261            new Ldobjbyname(new Imm(5), "done"),
262            new Isfalse(),
263            new Jeqz(loopEndLabel),
264            new Lda(resultObj),
265            new Ldobjbyname(new Imm(7), "value"),
266            new Sta(value),
267
268            new Lda(new VReg()),
269            new Sta(done),
270
271            new Lda(value),
272            new Sta(a),
273
274            insertedtryBeginLabel,
275            new Lda(iterReg),
276            new Ldobjbyname(new Imm(9), "return"),
277            new Sta(nextMethodReg),
278            new Strictnoteq(new Imm(11), new VReg()), // undefined
279            new Jeqz(noReturn),
280            new Lda(nextMethodReg),
281            new Callthis0(new Imm(12), iterReg),
282            new Sta(new VReg()),
283            new ThrowIfnotobject(new VReg()),
284            noReturn,
285            insertedtryEndLabel,
286            new Jmp(loopEndLabel),
287
288            tryEndLabel,
289
290            new Jmp(loopStartLabel),
291
292            catchBeginLabel,
293            new Sta(exceptionVreg),
294            new Lda(done),
295            new Strictnoteq(new Imm(13), trueReg),
296            new Jeqz(isDone),
297            new Lda(iterReg),
298            new Ldobjbyname(new Imm(14), "return"),
299            new Sta(nextMethodReg),
300            new Strictnoteq(new Imm(16), new VReg()),
301            new Jeqz(isDone),
302            new Lda(nextMethodReg),
303            new Callthis0(new Imm(17), iterReg),
304            isDone,
305            new Lda(exceptionVreg),
306            new Throw(),
307
308            loopEndLabel,
309            new Returnundefined()
310        ];
311
312        expect(checkInstructions(insns, expected)).to.be.true;
313
314        let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz));
315
316        expect(jumps.length).to.equal(6);
317    });
318
319    it("ForOf SyntaxError", function () {
320        let source: string = `for ([(x, y)] of []) {}`;
321        let errorThrown = false;
322        try {
323            compileMainSnippet(source);
324        } catch (err) {
325            expect(err instanceof DiagnosticError).to.be.true;
326            expect((<DiagnosticError>err).code).to.equal(DiagnosticCode.Property_destructuring_pattern_expected);
327            errorThrown = true;
328        }
329        expect(errorThrown).to.be.true;
330    });
331});
332