diff --git a/index.html b/index.html index ff59372d05..88ea6a3263 100644 --- a/index.html +++ b/index.html @@ -849,8 +849,10 @@ to.
{}. if '=>' follows '(...)', convert contents to arguments
if (metParenL === oldParenL && eat(_arrow)) {
val = parseArrowExpression(node, !val ? [] : val.type === "SequenceExpression" ? val.expressions : [val]);
- } else {disallow '()' before everything but error
if (!val) unexpected(lastStart);
+ } else {forbid '()' before everything but '=>'
if (!val) unexpected(lastStart);
}
val.start = tokStart1;
val.end = lastEnd;
@@ -1337,7 +1338,25 @@ 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);
+ expect(_of);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");
+ }
node.elements = parseExprList(_bracketR, true, true);
return finishNode(node, "ArrayExpression");
@@ -1361,7 +1380,7 @@ or {}. New's precedence is slightly tricky. It must allow its argument + }
New's precedence is slightly tricky. It must allow its argument
to be a [] or dot subscript expression, but not a call — at
least, not without wrapping it in parentheses. Thus, it uses the
function parseNew() {
var node = startNode();
@@ -1370,12 +1389,12 @@ least, not without wrapping it in parentheses. Thus, it uses the
if (eat(_parenL)) node.arguments = parseExprList(_parenR, false);
else node.arguments = empty;
return finishNode(node, "NewExpression");
- }Parse spread element '...expr'
function parseSpread() {
+ }Parse spread element '...expr'
function parseSpread() {
var node = startNode();
next();
node.argument = parseExpression(true);
return finishNode(node, "SpreadElement");
- }Parse an object literal.
function parseObj() {
+ }Parse an object literal.
function parseObj() {
var node = startNode(), first = true, sawGetSet = false;
node.properties = [];
next();
@@ -1416,7 +1435,7 @@ least, not without wrapping it in parentheses. Thus, it uses the
addProperty(node.properties, finishNode(prop, "Property"), sawGetSet, "init");
}
return finishNode(node, "ObjectExpression");
- }Add property to list with keeping in mind and checking that + }
Add property to list with keeping in mind and checking that 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 addProperty(props, current, sawGetSet, defaultKind) {
@@ -1447,7 +1466,7 @@ strict mode, init properties are also not allowed to be repeated.
}
}
prop.key = (tokType === _num || tokType === _string) ? parseExprAtom() : parseIdent(true);
- }Initialize empty function node.
function initFunction(node) {
+ }Initialize empty function node.
function initFunction(node) {
node.id = null;
node.params = [];
if (options.ecmaVersion >= 6) {
@@ -1455,7 +1474,7 @@ strict mode, init properties are also not allowed to be repeated.
node.rest = null;
node.generator = false;
}
- }Parse a function declaration or literal (depending on the + }
Parse a function declaration or literal (depending on the
isStatement parameter).
function parseFunction(node, isStatement, allowExpressionBody) {
initFunction(node);
if (isStatement || tokType === _name) {
@@ -1464,7 +1483,7 @@ strict mode, init properties are also not allowed to be repeated.
parseFunctionParams(node);
parseFunctionBody(node, allowExpressionBody);
return finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression");
- }Parse arrow function expression with given parameters.
function parseArrowExpression(node, params) {
+ }Parse arrow function expression with given parameters.
function parseArrowExpression(node, params) {
initFunction(node);
var defaults = node.defaults, hasDefaults = false;
@@ -1492,7 +1511,7 @@ strict mode, init properties are also not allowed to be repeated.
parseFunctionBody(node, true);
return finishNode(node, "ArrowFunctionExpression");
- }Parse function parameters.
function parseFunctionParams(node) {
+ }Parse function parameters.
function parseFunctionParams(node) {
var defaults = [], hasDefaults = false;
expect(_parenL);
@@ -1519,19 +1538,19 @@ strict mode, init properties are also not allowed to be repeated.
}
if (hasDefaults) node.defaults = defaults;
- }Parse function body and check parameters.
function parseFunctionBody(node, allowExpression) {
+ }Parse function body and check parameters.
function parseFunctionBody(node, allowExpression) {
var isExpression = allowExpression && tokType !== _braceL;
if (isExpression) {
node.body = parseExpression(true);
node.expression = true;
- } else {Start a new scope with regard to labels and the inFunction
+ } else {
Start a new scope with regard to labels and the inFunction
flag (restore them to their old value afterwards).
var oldInFunc = inFunction, oldLabels = labels;
inFunction = true; labels = [];
node.body = parseBlock(true);
node.expression = false;
inFunction = oldInFunc; labels = oldLabels;
- }If this is a strict mode function, verify that argument names + }
If this is a strict mode function, verify that argument names
are not repeated, and it does not try to bind the words eval
or arguments.
if (strict || !isExpression && node.body.body.length && isUseStrict(node.body.body[0])) {
var nameHash = {};
@@ -1542,7 +1561,7 @@ or arguments. Verify that argument names are not repeated, and it does not + }
Verify that argument names are not repeated, and it does not
try to bind the words eval or arguments.
function checkFunctionParam(param, nameHash) {
switch (param.type) {
case "Identifier":
@@ -1563,7 +1582,7 @@ try to bind the words eval or arguments.
checkFunctionParam(param.elements[i], nameHash);
break;
}
- }Parse a class declaration or literal (depending on the + }
Parse a class declaration or literal (depending on the
isStatement parameter).
function parseClass(node, isStatement) {
next();
@@ -1589,7 +1608,7 @@ try to bind the words eval or arguments.
}
node.body = finishNode(classBody, "ClassBody");
return finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression");
- }Parses a comma-separated list of expressions, and returns them as + }
Parses a comma-separated list of expressions, and returns them as
an array. close is the token type that ends the list, and
allowEmpty can be turned on to allow subsequent commas with
nothing in between them to be parsed as null (which is needed
@@ -1605,7 +1624,7 @@ for array literals).
Parse the next token as an identifier. If liberal is true (used
+ }
Parse the next token as an identifier. If liberal is true (used
when parsing properties), it will also convert keywords into
identifiers.
function parseIdent(liberal) {
var node = startNode();
@@ -1626,7 +1645,7 @@ identifiers. Convert existing expression atom to assignable pattern + }
Convert existing expression atom to assignable pattern if possible.
function toAssignable(node, allowSpread) {
if (options.ecmaVersion >= 6 && node) {
switch (node.type) {
@@ -1662,7 +1681,7 @@ if possible. Checks if node can be assignable spread argument.
function checkSpreadAssign(node) {
+ }Checks if node can be assignable spread argument.
function checkSpreadAssign(node) {
if (node.type !== "Identifier" && node.type !== "ArrayPattern")
unexpected(node.start);
}
diff --git a/test/tests-harmony.js b/test/tests-harmony.js
index a0833d10ba..f69ae66f52 100644
--- a/test/tests-harmony.js
+++ b/test/tests-harmony.js
@@ -3700,6 +3700,209 @@ test("[for (x of array) for (y of array2) if (x === test) x]", {
locations: true
});
+test("[for ([,x] of array) for ({[start.x]: x, [start.y]: y} of array2) x]", {
+ type: "Program",
+ body: [{
+ type: "ExpressionStatement",
+ expression: {
+ type: "ComprehensionExpression",
+ filter: null,
+ blocks: [
+ {
+ type: "ComprehensionBlock",
+ left: {
+ type: "ArrayPattern",
+ elements: [
+ null,
+ {
+ type: "Identifier",
+ name: "x",
+ range: [8, 9],
+ loc: {
+ start: {line: 1, column: 8},
+ end: {line: 1, column: 9}
+ }
+ }
+ ],
+ range: [6, 10],
+ loc: {
+ start: {line: 1, column: 6},
+ end: {line: 1, column: 10}
+ }
+ },
+ right: {
+ type: "Identifier",
+ name: "array",
+ range: [14, 19],
+ loc: {
+ start: {line: 1, column: 14},
+ end: {line: 1, column: 19}
+ }
+ },
+ range: [1, 20],
+ loc: {
+ start: {line: 1, column: 1},
+ end: {line: 1, column: 20}
+ },
+ of: true
+ },
+ {
+ type: "ComprehensionBlock",
+ left: {
+ type: "ObjectPattern",
+ properties: [
+ {
+ type: "Property",
+ key: {
+ type: "MemberExpression",
+ computed: false,
+ object: {
+ type: "Identifier",
+ name: "start",
+ range: [28, 33],
+ loc: {
+ start: {line: 1, column: 28},
+ end: {line: 1, column: 33}
+ }
+ },
+ property: {
+ type: "Identifier",
+ name: "x",
+ range: [34, 35],
+ loc: {
+ start: {line: 1, column: 34},
+ end: {line: 1, column: 35}
+ }
+ },
+ range: [28, 35],
+ loc: {
+ start: {line: 1, column: 28},
+ end: {line: 1, column: 35}
+ }
+ },
+ value: {
+ type: "Identifier",
+ name: "x",
+ range: [38, 39],
+ loc: {
+ start: {line: 1, column: 38},
+ end: {line: 1, column: 39}
+ }
+ },
+ kind: "init",
+ method: false,
+ shorthand: false,
+ computed: true,
+ range: [27, 39],
+ loc: {
+ start: {line: 1, column: 27},
+ end: {line: 1, column: 39}
+ }
+ },
+ {
+ type: "Property",
+ key: {
+ type: "MemberExpression",
+ computed: false,
+ object: {
+ type: "Identifier",
+ name: "start",
+ range: [42, 47],
+ loc: {
+ start: {line: 1, column: 42},
+ end: {line: 1, column: 47}
+ }
+ },
+ property: {
+ type: "Identifier",
+ name: "y",
+ range: [48, 49],
+ loc: {
+ start: {line: 1, column: 48},
+ end: {line: 1, column: 49}
+ }
+ },
+ range: [42, 49],
+ loc: {
+ start: {line: 1, column: 42},
+ end: {line: 1, column: 49}
+ }
+ },
+ value: {
+ type: "Identifier",
+ name: "y",
+ range: [52, 53],
+ loc: {
+ start: {line: 1, column: 52},
+ end: {line: 1, column: 53}
+ }
+ },
+ kind: "init",
+ method: false,
+ shorthand: false,
+ computed: true,
+ range: [41, 53],
+ loc: {
+ start: {line: 1, column: 41},
+ end: {line: 1, column: 53}
+ }
+ }
+ ],
+ range: [26, 54],
+ loc: {
+ start: {line: 1, column: 26},
+ end: {line: 1, column: 54}
+ }
+ },
+ right: {
+ type: "Identifier",
+ name: "array2",
+ range: [58, 64],
+ loc: {
+ start: {line: 1, column: 58},
+ end: {line: 1, column: 64}
+ }
+ },
+ range: [21, 65],
+ loc: {
+ start: {line: 1, column: 21},
+ end: {line: 1, column: 65}
+ },
+ of: true
+ }
+ ],
+ body: {
+ type: "Identifier",
+ name: "x",
+ range: [66, 67],
+ loc: {
+ start: {line: 1, column: 66},
+ end: {line: 1, column: 67}
+ }
+ },
+ range: [0, 68],
+ loc: {
+ start: {line: 1, column: 0},
+ end: {line: 1, column: 68}
+ }
+ },
+ range: [0, 68],
+ loc: {
+ start: {line: 1, column: 0},
+ end: {line: 1, column: 68}
+ }
+ }],
+ range: [0, 68],
+ loc: {
+ start: {line: 1, column: 0},
+ end: {line: 1, column: 68}
+ }
+}, {
+ ecmaVersion: 6,
+ ranges: true,
+ locations: true
+});
+
// Harmony: Object Literal Property Value Shorthand
test("x = { y, z }", {