Support for for (const ...).

Fixes #213.

Also changes API to pass token type to `parseVar` to reduce string comparison ops.
This commit is contained in:
Ingvar Stepanyan 2015-03-10 11:36:15 +02:00
parent ff60ee4fdb
commit 34050d3917
4 changed files with 95 additions and 8 deletions

View File

@ -1773,7 +1773,7 @@
case tt._throw: return this.parseThrowStatement(node);
case tt._try: return this.parseTryStatement(node);
case tt._let: case tt._const: if (!declaration) this.unexpected(); // NOTE: falls through to _var
case tt._var: return this.parseVarStatement(node, starttype.keyword);
case tt._var: return this.parseVarStatement(node, starttype);
case tt._while: return this.parseWhileStatement(node);
case tt._with: return this.parseWithStatement(node);
case tt.braceL: return this.parseBlock(); // no point creating a function for this
@ -1853,13 +1853,13 @@
this.labels.push(loopLabel);
this.expect(tt.parenL);
if (this.type === tt.semi) return this.parseFor(node, null);
if (this.type === tt._var || this.type === tt._let) {
var init = this.startNode(), varKind = this.type.keyword, isLet = this.type === tt._let;
if (this.type === tt._var || this.type === tt._let || this.type === tt._const) {
var init = this.startNode(), varKind = this.type;
this.next();
this.parseVar(init, true, varKind);
this.finishNode(init, "VariableDeclaration");
if ((this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init.declarations.length === 1 &&
!(isLet && init.declarations[0].init))
!(varKind !== tt._var && init.declarations[0].init))
return this.parseForIn(node, init);
return this.parseFor(node, init);
}
@ -2079,12 +2079,18 @@
pp.parseVar = function(node, noIn, kind) {
node.declarations = [];
node.kind = kind;
node.kind = kind.keyword;
for (;;) {
var decl = this.startNode();
decl.id = this.parseBindingAtom();
this.checkLVal(decl.id, true);
decl.init = this.eat(tt.eq) ? this.parseMaybeAssign(noIn) : (kind === tt._const.keyword ? this.unexpected() : null);
if (this.eat(tt.eq)) {
decl.init = this.parseMaybeAssign(noIn);
} else if (kind === tt._const && !(this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) {
this.unexpected();
} else {
decl.init = null;
}
node.declarations.push(this.finishNode(decl, "VariableDeclarator"));
if (!this.eat(tt.comma)) break;
}

View File

@ -346,7 +346,7 @@
this.pushCx();
this.expect(tt.parenL);
if (this.tok.type === tt.semi) return this.parseFor(node, null);
if (this.tok.type === tt._var || this.tok.type === tt._let) {
if (this.tok.type === tt._var || this.tok.type === tt._let || this.tok.type === tt._const) {
var init = this.parseVar(true);
if (init.declarations.length === 1 && (this.tok.type === tt._in || this.isContextual("of"))) {
return this.parseForIn(node, init);

View File

@ -14970,6 +14970,55 @@ test("class A { static() {} }", {
locations: true
});
// https://github.com/marijnh/acorn/issues/213
test("for (const x of list) process(x);", {
type: "Program",
body: [{
type: "ForOfStatement",
left: {
type: "VariableDeclaration",
declarations: [{
type: "VariableDeclarator",
id: {
type: "Identifier",
name: "x",
range: [11, 12]
},
init: null,
range: [11, 12]
}],
kind: "const",
range: [5, 12]
},
right: {
type: "Identifier",
name: "list",
range: [16, 20]
},
body: {
type: "ExpressionStatement",
expression: {
type: "CallExpression",
callee: {
type: "Identifier",
name: "process",
range: [22, 29]
},
arguments: [{
type: "Identifier",
name: "x",
range: [30, 31]
}],
range: [22, 32]
},
range: [22, 33]
},
range: [0, 33]
}],
range: [0, 33]
}, {ecmaVersion: 6, ranges: true});
test("class A { *static() {} }", {
type: "Program",
range: [0, 24],

View File

@ -28682,7 +28682,39 @@ test("const x = 14, y = 3, z = 1977", {
testFail("const a;", "Unexpected token (1:7)", {ecmaVersion: 6});
testFail("for(const x = 0;;);", "Unexpected token (1:4)", {ecmaVersion: 6});
test("for(const x = 0;;);", {
type: "Program",
body: [{
type: "ForStatement",
init: {
type: "VariableDeclaration",
declarations: [{
type: "VariableDeclarator",
id: {
type: "Identifier",
name: "x",
range: [10, 11]
},
init: {
type: "Literal",
value: 0,
range: [14, 15]
},
range: [10, 15]
}],
kind: "const",
range: [4, 15]
},
test: null,
update: null,
body: {
type: "EmptyStatement",
range: [18, 19]
},
range: [0, 19]
}],
range: [0, 19]
}, {ecmaVersion: 6, ranges: true});
testFail("for(x of a);", "Unexpected token (1:6)");