()
| 2198 | // https://tc39.github.io/ecma262/#sec-for-in-and-for-of-statements |
| 2199 | |
| 2200 | parseForStatement(): Node.ForStatement | Node.ForInStatement | Node.ForOfStatement { |
| 2201 | let init: any = null; |
| 2202 | let test: Node.Expression | null = null; |
| 2203 | let update: Node.Expression | null = null; |
| 2204 | let forIn = true; |
| 2205 | let left, right; |
| 2206 | |
| 2207 | const node = this.createNode(); |
| 2208 | this.expectKeyword('for'); |
| 2209 | this.expect('('); |
| 2210 | |
| 2211 | if (this.match(';')) { |
| 2212 | this.nextToken(); |
| 2213 | } else { |
| 2214 | if (this.matchKeyword('var')) { |
| 2215 | init = this.createNode(); |
| 2216 | this.nextToken(); |
| 2217 | |
| 2218 | const previousAllowIn = this.context.allowIn; |
| 2219 | this.context.allowIn = false; |
| 2220 | const declarations = this.parseVariableDeclarationList({ inFor: true }); |
| 2221 | this.context.allowIn = previousAllowIn; |
| 2222 | |
| 2223 | if (declarations.length === 1 && this.matchKeyword('in')) { |
| 2224 | const decl = declarations[0]; |
| 2225 | if (decl.init && (decl.id.type === Syntax.ArrayPattern || decl.id.type === Syntax.ObjectPattern || this.context.strict)) { |
| 2226 | this.tolerateError(Messages.ForInOfLoopInitializer, 'for-in'); |
| 2227 | } |
| 2228 | init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var')); |
| 2229 | this.nextToken(); |
| 2230 | left = init; |
| 2231 | right = this.parseExpression(); |
| 2232 | init = null; |
| 2233 | } else if (declarations.length === 1 && declarations[0].init === null && this.matchContextualKeyword('of')) { |
| 2234 | init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var')); |
| 2235 | this.nextToken(); |
| 2236 | left = init; |
| 2237 | right = this.parseAssignmentExpression(); |
| 2238 | init = null; |
| 2239 | forIn = false; |
| 2240 | } else { |
| 2241 | init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var')); |
| 2242 | this.expect(';'); |
| 2243 | } |
| 2244 | } else if (this.matchKeyword('const') || this.matchKeyword('let')) { |
| 2245 | init = this.createNode(); |
| 2246 | const kind = this.nextToken().value as string; |
| 2247 | |
| 2248 | if (!this.context.strict && this.lookahead.value === 'in') { |
| 2249 | init = this.finalize(init, new Node.Identifier(kind)); |
| 2250 | this.nextToken(); |
| 2251 | left = init; |
| 2252 | right = this.parseExpression(); |
| 2253 | init = null; |
| 2254 | } else { |
| 2255 | const previousAllowIn = this.context.allowIn; |
| 2256 | this.context.allowIn = false; |
| 2257 | const declarations = this.parseBindingList(kind, { inFor: true }); |
no test coverage detected