Commit c983689d authored by conradw's avatar conradw Committed by Commit bot

[strong] Implement static restrictions on direct eval

Does not entirely disallow the use of 'eval' as an identifier in strong mode,
as originally proposed.

BUG=v8:3956
LOG=N

Review URL: https://codereview.chromium.org/1059273004

Cr-Commit-Position: refs/heads/master@{#27796}
parent 434b456b
......@@ -168,6 +168,7 @@ var kMessages = {
strong_ellision: ["In strong mode, arrays with holes are deprecated, use maps instead"],
strong_arguments: ["In strong mode, 'arguments' is deprecated, use '...args' instead"],
strong_undefined: ["In strong mode, binding or assigning to 'undefined' is deprecated"],
strong_direct_eval: ["In strong mode, direct calls to eval are deprecated"],
strong_equal: ["In strong mode, '==' and '!=' are deprecated, use '===' and '!==' instead"],
strong_delete: ["In strong mode, 'delete' is deprecated, use maps or sets instead"],
strong_var: ["In strong mode, 'var' is deprecated, use 'let' or 'const' instead"],
......
......@@ -2804,6 +2804,12 @@ ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
}
case Token::LPAREN: {
if (is_strong(language_mode()) && this->IsIdentifier(result) &&
this->IsEval(this->AsIdentifier(result))) {
ReportMessage("strong_direct_eval");
*ok = false;
return this->EmptyExpression();
}
int pos;
if (scanner()->current_token() == Token::IDENTIFIER) {
// For call of an identifier we want to report position of
......
......@@ -5911,6 +5911,36 @@ TEST(StrongUndefinedArrow) {
}
TEST(StrongDirectEval) {
const char* context_data[][2] = {{"", ""}, {NULL}};
const char* error_data[] = {
"'use strong'; eval();",
"'use strong'; eval([]);",
"'use strong'; (eval)();",
"'use strong'; (((eval)))();",
"'use strong'; eval('function f() {}');",
"'use strong'; function f() {eval()}",
NULL};
const char* success_data[] = {
"'use strong'; eval;",
"'use strong'; eval`foo`;",
"'use strong'; let foo = eval; foo();",
"'use strong'; (1, eval)();",
NULL};
static const ParserFlag always_flags[] = {
kAllowStrongMode
};
RunParserSyncTest(context_data, error_data, kError, NULL, 0,
always_flags, arraysize(always_flags));
RunParserSyncTest(context_data, success_data, kSuccess, NULL, 0,
always_flags, arraysize(always_flags));
}
TEST(ArrowFunctionASIErrors) {
const char* context_data[][2] = {{"'use strict';", ""}, {"", ""},
{NULL, NULL}};
......
......@@ -9,16 +9,18 @@
class C {}
let indirect_eval = eval;
function assertTypeError(script) { assertThrows(script, TypeError) }
function assertSyntaxError(script) { assertThrows(script, SyntaxError) }
function assertReferenceError(script) { assertThrows(script, ReferenceError) }
(function ImmutableClassBindings() {
class D {}
assertTypeError(function(){ eval("C = 0") });
assertTypeError(function(){ eval("D = 0") });
assertTypeError(function(){ indirect_eval("C = 0") });
assertEquals('function', typeof C);
assertEquals('function', typeof D);
assertTypeError("'use strong'; (function f() {class E {}; E = 0})()");
})();
function constructor(body) {
......
......@@ -55,12 +55,6 @@ function assertThrowsHelper(code) {
" function f() { if (false) { x; } } var x; f(); \n" +
"})()");
// Errors are also detected when the declaration and the use are in the same
// eval scope.
assertThrows("'use strong'; eval('if (false) { x; let x = 0;}')",
ReferenceError);
assertDoesNotThrow("'use strict'; eval('if (false) { x; let x = 0; }')");
// Use occurring in the initializer of the declaration:
assertThrowsHelper("let x = x + 1;");
assertThrowsHelper("let x = x;");
......@@ -215,14 +209,6 @@ function assertThrowsHelper(code) {
var1, var2a, var2b, var2c;
}
(function eval1() {
let var7 = 0; // Declaration position will be something large.
// But use position will be something small, however, this is not an error,
// since the use is inside an eval scope.
eval("var7;");
})();
class C1 { constructor() { C1; } }; new C1();
let C2 = class C3 { constructor() { C3; } }; new C2();
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --strong-mode
// In strong mode, direct calls to eval are forbidden
assertThrows("'use strong'; eval();", SyntaxError);
assertThrows("'use strong'; (eval)();", SyntaxError);
assertThrows("'use strong'; (((eval)))();", SyntaxError);
assertThrows("'use strong'; eval([]);", SyntaxError);
assertThrows("'use strong'; eval('function f() {}');", SyntaxError);
assertThrows("'use strong'; function f() {eval()}", SyntaxError);
assertDoesNotThrow("'use strong'; eval;");
assertDoesNotThrow("'use strong'; eval`foo`;");
assertDoesNotThrow("'use strong'; let foo = eval; foo();");
assertDoesNotThrow("'use strong'; (1, eval)();");
......@@ -10,7 +10,6 @@
assertThrows("function f() { 'use strong'; 0 == 0 }", SyntaxError);
assertThrows("'use strong'; function f() { 0 == 0 }", SyntaxError);
assertThrows("'use strong'; function f() { function g() { 0 == 0 } }", SyntaxError);
assertThrows("'use strong'; eval('function f() { 0 == 0 }')", SyntaxError);
assertTrue(eval("function f() { 'use strong' } 0 == 0"));
assertTrue(eval("eval('\\\'use strong\\\''); 0 == 0"));
})();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment