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