Skip to content

Commit 2db14fb

Browse files
RReversermarijnh
authored andcommitted
Checking argument names clash in strict mode for arrow functions.
Some more testFail message fixes.
1 parent 47c4196 commit 2db14fb

File tree

2 files changed

+57
-50
lines changed

2 files changed

+57
-50
lines changed

acorn.js

Lines changed: 43 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1810,7 +1810,6 @@
18101810
node.defaults = [];
18111811
node.rest = null;
18121812
node.generator = false;
1813-
node.expression = false;
18141813
}
18151814
expect(_parenL);
18161815
for (;;) {
@@ -1828,36 +1827,7 @@
18281827
}
18291828
}
18301829
}
1831-
1832-
// Start a new scope with regard to labels and the `inFunction`
1833-
// flag (restore them to their old value afterwards).
1834-
var oldInFunc = inFunction, oldLabels = labels;
1835-
inFunction = true; labels = [];
1836-
node.body = parseBlock(true);
1837-
inFunction = oldInFunc; labels = oldLabels;
1838-
1839-
// If this is a strict mode function, verify that argument names
1840-
// are not repeated, and it does not try to bind the words `eval`
1841-
// or `arguments`.
1842-
if (strict || node.body.body.length && isUseStrict(node.body.body[0])) {
1843-
// Negative indices are used to reuse loop body for node.rest and node.id
1844-
for (var i = -2, id; i < node.params.length; ++i) {
1845-
if (i >= 0) {
1846-
id = node.params[i];
1847-
} else if (i == -2) {
1848-
if (node.rest) id = node.rest;
1849-
else continue;
1850-
} else {
1851-
if (node.id) id = node.id;
1852-
else continue;
1853-
}
1854-
if (isStrictReservedWord(id.name) || isStrictBadIdWord(id.name))
1855-
raise(id.start, "Defining '" + id.name + "' in strict mode");
1856-
if (i >= 0) for (var j = 0; j < i; ++j) if (id.name === node.params[j].name)
1857-
raise(id.start, "Argument name clash in strict mode");
1858-
}
1859-
}
1860-
1830+
parseFunctionBody(node);
18611831
return finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression");
18621832
}
18631833

@@ -1885,19 +1855,56 @@
18851855
}
18861856
}
18871857

1888-
var isExpression = tokType !== _braceL;
1889-
var body = isExpression ? parseExpression(true) : parseBlock(true);
1890-
18911858
node.id = null;
18921859
node.params = params;
18931860
node.defaults = hasDefaults ? defaults : [];
18941861
node.rest = null;
1895-
node.body = body;
18961862
node.generator = false;
1897-
node.expression = isExpression;
1863+
parseFunctionBody(node, true);
18981864
return finishNode(node, "ArrowFunctionExpression");
18991865
}
19001866

1867+
// Parse function body and check parameters.
1868+
1869+
function parseFunctionBody(node, allowExpression) {
1870+
var isExpression = allowExpression && tokType !== _braceL;
1871+
1872+
if (isExpression) {
1873+
node.body = parseExpression(true);
1874+
node.expression = true;
1875+
} else {
1876+
// Start a new scope with regard to labels and the `inFunction`
1877+
// flag (restore them to their old value afterwards).
1878+
var oldInFunc = inFunction, oldLabels = labels;
1879+
inFunction = true; labels = [];
1880+
node.body = parseBlock(true);
1881+
node.expression = false;
1882+
inFunction = oldInFunc; labels = oldLabels;
1883+
}
1884+
1885+
// If this is a strict mode function, verify that argument names
1886+
// are not repeated, and it does not try to bind the words `eval`
1887+
// or `arguments`.
1888+
if (strict || !isExpression && node.body.body.length && isUseStrict(node.body.body[0])) {
1889+
// Negative indices are used to reuse loop body for node.rest and node.id
1890+
for (var i = -2, id; i < node.params.length; ++i) {
1891+
if (i >= 0) {
1892+
id = node.params[i];
1893+
} else if (i == -2) {
1894+
if (node.rest) id = node.rest;
1895+
else continue;
1896+
} else {
1897+
if (node.id) id = node.id;
1898+
else continue;
1899+
}
1900+
if (isStrictReservedWord(id.name) || isStrictBadIdWord(id.name))
1901+
raise(id.start, "Defining '" + id.name + "' in strict mode");
1902+
if (i >= 0) for (var j = 0; j < i; ++j) if (id.name === node.params[j].name)
1903+
raise(id.start, "Argument name clash in strict mode");
1904+
}
1905+
}
1906+
}
1907+
19011908
// Parses a comma-separated list of expressions, and returns them as
19021909
// an array. `close` is the token type that ends the list, and
19031910
// `allowEmpty` can be turned on to allow subsequent commas with

test/tests-harmony.js

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15817,33 +15817,33 @@ testFail("((a)) => 42", "Unexpected token (1:7)", {ecmaVersion: 6});
1581715817

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

0 commit comments

Comments
 (0)