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