From acbef8557f2093e9149fbfbf1559b9f8bee56614 Mon Sep 17 00:00:00 2001
From: Ingvar Stepanyan eval or arguments.
Check if property name clashes with already added. Object/class getters and setters are not allowed to clash — either with each other or with an init property — and in -strict mode, init properties are also not allowed to be repeated.
function checkPropClash(prop, defaultKind, propHash) {
+strict mode, init properties are also not allowed to be repeated. function checkPropClash(prop, propHash) {
var key = prop.key, name;
switch (key.type) {
case "Identifier": name = key.name; break;
case "Literal": name = String(key.value); break;
default: return;
}
- var kind = prop.kind, other = propHash[name];
+ var kind = prop.kind || "init", other = propHash[name];
if (other) {
- var isGetSet = kind !== defaultKind;
- if ((strict || isGetSet) && other[kind] || !(isGetSet ^ other[defaultKind]))
+ var isGetSet = kind !== "init";
+ if ((strict || isGetSet) && other[kind] || !(isGetSet ^ other.init))
raise(key.start, "Redefinition of property");
} else {
other = propHash[name] = hash();
+ other.init = other.get = other.set = false;
}
other[kind] = true;
}Verify that a node is an lval — something that can be assigned
@@ -1448,20 +1449,23 @@ or {}.
check whether this is generator comprehension or regular expression
if (options.ecmaVersion >= 6 && tokType === _for) {
+ val = parseComprehension(startNode(), true);
} else {
- exprList = [];
- }
- expect(_parenR);if '=>' follows '(...)', convert contents to arguments
if (metParenL === oldParenL && eat(_arrow)) {
- val = parseArrowExpression(node, exprList);
- } else {forbid '()' before everything but '=>'
if (!val) unexpected(lastStart);forbid '...' in sequence expressions
if (options.ecmaVersion >= 6) {
- for (var i = 0; i < exprList.length; i++) {
- if (exprList[i].type === "SpreadElement") unexpected();
+ var oldParenL = ++metParenL;
+ if (tokType !== _parenR) {
+ val = parseExpression();
+ exprList = val.type === "SequenceExpression" ? val.expressions : [val];
+ } else {
+ exprList = [];
+ }
+ expect(_parenR);if '=>' follows '(...)', convert contents to arguments
if (metParenL === oldParenL && eat(_arrow)) {
+ val = parseArrowExpression(startNode(), exprList);
+ } else {forbid '()' before everything but '=>'
if (!val) unexpected(lastStart);forbid '...' in sequence expressions
if (options.ecmaVersion >= 6) {
+ for (var i = 0; i < exprList.length; i++) {
+ if (exprList[i].type === "SpreadElement") unexpected();
+ }
}
}
}
@@ -1478,25 +1482,8 @@ or {}. check whether this is array comprehension or regular array
if (options.ecmaVersion >= 6 && tokType === _for) {
- node.blocks = [];
- while (tokType === _for) {
- var block = startNode();
- next();
- expect(_parenL);
- block.left = toAssignable(parseExprAtom());
- checkLVal(block.left, true);
- if (tokType !== _name || tokVal !== "of") unexpected();
- next();of property is here for compatibility with Esprima's AST
-which also supports deprecated [for (... in ...) expr]
block.of = true;
- block.right = parseExpression();
- expect(_parenR);
- node.blocks.push(finishNode(block, "ComprehensionBlock"));
- }
- node.filter = eat(_if) ? parseParenExpression() : null;
- node.body = parseExpression();
- expect(_bracketR);
- return finishNode(node, "ComprehensionExpression");
+ next();check whether this is array comprehension or regular array
if (options.ecmaVersion >= 6 && tokType === _for) {
+ return parseComprehension(node, false);
}
node.elements = parseExprList(_bracketR, true, true);
return finishNode(node, "ArrayExpression");
@@ -1598,7 +1585,7 @@ least, not without wrapping it in parentheses. Thus, it uses the
prop.shorthand = true;
} else unexpected();
- checkPropClash(prop, "init", propHash);
+ checkPropClash(prop, propHash);
node.properties.push(finishNode(prop, "Property"));
}
return finishNode(node, "ObjectExpression");
@@ -1754,7 +1741,7 @@ or arguments. Parses yield expression inside generator.
function parseYield() {
var node = startNode();
next();
- node.delegate = eat(_star);
- node.argument = parseExpression(true);
+ if (eat(_semi) || canInsertSemicolon()) {
+ node.delegate = false;
+ node.argument = null;
+ } else {
+ node.delegate = eat(_star);
+ node.argument = parseExpression(true);
+ }
return finishNode(node, "YieldExpression");
+ }Parses array and generator comprehensions.
function parseComprehension(node, isGenerator) {
+ node.blocks = [];
+ while (tokType === _for) {
+ var block = startNode();
+ next();
+ expect(_parenL);
+ block.left = toAssignable(parseExprAtom());
+ checkLVal(block.left, true);
+ if (tokType !== _name || tokVal !== "of") unexpected();
+ next();of property is here for compatibility with Esprima's AST
+which also supports deprecated [for (... in ...) expr]
block.of = true;
+ block.right = parseExpression();
+ expect(_parenR);
+ node.blocks.push(finishNode(block, "ComprehensionBlock"));
+ }
+ node.filter = eat(_if) ? parseParenExpression() : null;
+ node.body = parseExpression();
+ expect(isGenerator ? _parenR : _bracketR);
+ node.generator = isGenerator;
+ return finishNode(node, "ComprehensionExpression");
}
});
diff --git a/test/tests-harmony.js b/test/tests-harmony.js
index 98ec29f1a3..a6ec0f2c65 100644
--- a/test/tests-harmony.js
+++ b/test/tests-harmony.js
@@ -6138,6 +6138,86 @@ test("(function* () { yield v })", {
locations: true
});
+test("(function* () { yield\nv })", {
+ type: "Program",
+ body: [{
+ type: "ExpressionStatement",
+ expression: {
+ type: "FunctionExpression",
+ id: null,
+ params: [],
+ defaults: [],
+ body: {
+ type: "BlockStatement",
+ body: [
+ {
+ type: "ExpressionStatement",
+ expression: {
+ type: "YieldExpression",
+ argument: null,
+ delegate: false,
+ range: [16, 21],
+ loc: {
+ start: {line: 1, column: 16},
+ end: {line: 1, column: 21}
+ }
+ },
+ range: [16, 21],
+ loc: {
+ start: {line: 1, column: 16},
+ end: {line: 1, column: 21}
+ }
+ },
+ {
+ type: "ExpressionStatement",
+ expression: {
+ type: "Identifier",
+ name: "v",
+ range: [22, 23],
+ loc: {
+ start: {line: 2, column: 0},
+ end: {line: 2, column: 1}
+ }
+ },
+ range: [22, 23],
+ loc: {
+ start: {line: 2, column: 0},
+ end: {line: 2, column: 1}
+ }
+ }
+ ],
+ range: [14, 25],
+ loc: {
+ start: {line: 1, column: 14},
+ end: {line: 2, column: 3}
+ }
+ },
+ rest: null,
+ generator: true,
+ expression: false,
+ range: [0, 26],
+ loc: {
+ start: {line: 1, column: 0},
+ end: {line: 2, column: 4}
+ }
+ },
+ range: [0, 26],
+ loc: {
+ start: {line: 1, column: 0},
+ end: {line: 2, column: 4}
+ }
+ }],
+ range: [0, 26],
+ loc: {
+ start: {line: 1, column: 0},
+ end: {line: 2, column: 4}
+ }
+}, {
+ ecmaVersion: 6,
+ ranges: true,
+ locations: true
+});
+
test("(function* () { yield *v })", {
type: "Program",
body: [{