Skip to content

Commit

Permalink
Checking argument names clash in strict mode for arrow functions.
Browse files Browse the repository at this point in the history
Some more testFail message fixes.
  • Loading branch information
RReverser authored and marijnh committed Jul 29, 2014
1 parent 47c4196 commit 2db14fb
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 50 deletions.
79 changes: 43 additions & 36 deletions acorn.js
Original file line number Diff line number Diff line change
Expand Up @@ -1810,7 +1810,6 @@
node.defaults = [];
node.rest = null;
node.generator = false;
node.expression = false;
}
expect(_parenL);
for (;;) {
Expand All @@ -1828,36 +1827,7 @@
}
}
}

// 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);
inFunction = oldInFunc; labels = oldLabels;

// 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 || node.body.body.length && isUseStrict(node.body.body[0])) {
// Negative indices are used to reuse loop body for node.rest and node.id
for (var i = -2, id; i < node.params.length; ++i) {
if (i >= 0) {
id = node.params[i];
} else if (i == -2) {
if (node.rest) id = node.rest;
else continue;
} else {
if (node.id) id = node.id;
else continue;
}
if (isStrictReservedWord(id.name) || isStrictBadIdWord(id.name))
raise(id.start, "Defining '" + id.name + "' in strict mode");
if (i >= 0) for (var j = 0; j < i; ++j) if (id.name === node.params[j].name)
raise(id.start, "Argument name clash in strict mode");
}
}

parseFunctionBody(node);
return finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression");
}

Expand Down Expand Up @@ -1885,19 +1855,56 @@
}
}

var isExpression = tokType !== _braceL;
var body = isExpression ? parseExpression(true) : parseBlock(true);

node.id = null;
node.params = params;
node.defaults = hasDefaults ? defaults : [];
node.rest = null;
node.body = body;
node.generator = false;
node.expression = isExpression;
parseFunctionBody(node, true);
return finishNode(node, "ArrowFunctionExpression");
}

// 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`
// 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
// 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])) {
// Negative indices are used to reuse loop body for node.rest and node.id
for (var i = -2, id; i < node.params.length; ++i) {
if (i >= 0) {
id = node.params[i];
} else if (i == -2) {
if (node.rest) id = node.rest;
else continue;
} else {
if (node.id) id = node.id;
else continue;
}
if (isStrictReservedWord(id.name) || isStrictBadIdWord(id.name))
raise(id.start, "Defining '" + id.name + "' in strict mode");
if (i >= 0) for (var j = 0; j < i; ++j) if (id.name === node.params[j].name)
raise(id.start, "Argument name clash in strict mode");
}
}
}

// 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
Expand Down
28 changes: 14 additions & 14 deletions test/tests-harmony.js
Original file line number Diff line number Diff line change
Expand Up @@ -15817,33 +15817,33 @@ testFail("((a)) => 42", "Unexpected token (1:7)", {ecmaVersion: 6});

testFail("(a, (b)) => 42", "Unexpected token (1:10)", {ecmaVersion: 6});

testFail("\"use strict\"; (eval = 10) => 42", "Unexpected token (1:16)", {ecmaVersion: 6});
testFail("\"use strict\"; (eval = 10) => 42", "Assigning to eval in strict mode (1:15)", {ecmaVersion: 6});

testFail("\"use strict\"; eval => 42", "Unexpected token (1:25)", {ecmaVersion: 6});
testFail("\"use strict\"; eval => 42", "Defining 'eval' in strict mode (1:14)", {ecmaVersion: 6});

testFail("\"use strict\"; arguments => 42", "Unexpected token (1:30)", {ecmaVersion: 6});
testFail("\"use strict\"; arguments => 42", "Defining 'arguments' in strict mode (1:14)", {ecmaVersion: 6});

testFail("\"use strict\"; (eval, a) => 42", "Unexpected token (1:30)", {ecmaVersion: 6});
testFail("\"use strict\"; (eval, a) => 42", "Defining 'eval' in strict mode (1:15)", {ecmaVersion: 6});

testFail("\"use strict\"; (arguments, a) => 42", "Unexpected token (1:35)", {ecmaVersion: 6});
testFail("\"use strict\"; (arguments, a) => 42", "Defining 'arguments' in strict mode (1:15)", {ecmaVersion: 6});

testFail("\"use strict\"; (eval, a = 10) => 42", "Unexpected token (1:35)", {ecmaVersion: 6});
testFail("\"use strict\"; (eval, a = 10) => 42", "Defining 'eval' in strict mode (1:15)", {ecmaVersion: 6});

testFail("(a, a) => 42", "Unexpected token (1:7)", {ecmaVersion: 6});

testFail("\"use strict\"; (a, a) => 42", "Unexpected token (1:21)", {ecmaVersion: 6});
testFail("\"use strict\"; (a, a) => 42", "Argument name clash in strict mode (1:18)", {ecmaVersion: 6});

testFail("\"use strict\"; (a) => 00", "Unexpected token (1:22)", {ecmaVersion: 6});
testFail("\"use strict\"; (a) => 00", "Invalid number (1:21)", {ecmaVersion: 6});

testFail("() <= 42", "Unexpected token (1:4)", {ecmaVersion: 6});

testFail("(10) => 00", "Unexpected token (1:6)", {ecmaVersion: 6});
testFail("(10) => 00", "Unexpected token (1:1)", {ecmaVersion: 6});

testFail("(10, 20) => 00", "Unexpected token (1:10)", {ecmaVersion: 6});
testFail("(10, 20) => 00", "Unexpected token (1:1)", {ecmaVersion: 6});

testFail("yield v", "Unexpected token (1:7)", {ecmaVersion: 6});
testFail("yield v", "Unexpected token (1:6)", {ecmaVersion: 6});

testFail("yield 10", "Unexpected token (1:7)", {ecmaVersion: 6});
testFail("yield 10", "Unexpected token (1:6)", {ecmaVersion: 6});

test("yield* 10", {
type: "Program",
Expand Down Expand Up @@ -16126,8 +16126,8 @@ testFail("module \"Universe\" { ; ; ", "Unexpected token (1:27)", {ecmaVersion

testFail("switch (cond) { case 10: let a = 20; ", "Unexpected token (1:37)", {ecmaVersion: 6});

testFail("\"use strict\"; (eval) => 42", "Unexpected token (1:27)", {ecmaVersion: 6});
testFail("\"use strict\"; (eval) => 42", "Defining 'eval' in strict mode (1:15)", {ecmaVersion: 6});

testFail("(eval) => { \"use strict\"; 42 }", "Unexpected token (1:31)", {ecmaVersion: 6});
testFail("(eval) => { \"use strict\"; 42 }", "Defining 'eval' in strict mode (1:1)", {ecmaVersion: 6});

testFail("({ get test() { } }) => 42", "Unexpected token (1:21)", {ecmaVersion: 6});

0 comments on commit 2db14fb

Please sign in to comment.