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 = { ...@@ -168,6 +168,7 @@ var kMessages = {
strong_ellision: ["In strong mode, arrays with holes are deprecated, use maps instead"], 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_arguments: ["In strong mode, 'arguments' is deprecated, use '...args' instead"],
strong_undefined: ["In strong mode, binding or assigning to 'undefined' is deprecated"], 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_equal: ["In strong mode, '==' and '!=' are deprecated, use '===' and '!==' instead"],
strong_delete: ["In strong mode, 'delete' is deprecated, use maps or sets 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"], strong_var: ["In strong mode, 'var' is deprecated, use 'let' or 'const' instead"],
......
...@@ -2804,6 +2804,12 @@ ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) { ...@@ -2804,6 +2804,12 @@ ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
} }
case Token::LPAREN: { 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; int pos;
if (scanner()->current_token() == Token::IDENTIFIER) { if (scanner()->current_token() == Token::IDENTIFIER) {
// For call of an identifier we want to report position of // For call of an identifier we want to report position of
......
...@@ -5911,6 +5911,36 @@ TEST(StrongUndefinedArrow) { ...@@ -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) { TEST(ArrowFunctionASIErrors) {
const char* context_data[][2] = {{"'use strict';", ""}, {"", ""}, const char* context_data[][2] = {{"'use strict';", ""}, {"", ""},
{NULL, NULL}}; {NULL, NULL}};
......
...@@ -9,16 +9,18 @@ ...@@ -9,16 +9,18 @@
class C {} class C {}
let indirect_eval = eval;
function assertTypeError(script) { assertThrows(script, TypeError) } function assertTypeError(script) { assertThrows(script, TypeError) }
function assertSyntaxError(script) { assertThrows(script, SyntaxError) } function assertSyntaxError(script) { assertThrows(script, SyntaxError) }
function assertReferenceError(script) { assertThrows(script, ReferenceError) } function assertReferenceError(script) { assertThrows(script, ReferenceError) }
(function ImmutableClassBindings() { (function ImmutableClassBindings() {
class D {} class D {}
assertTypeError(function(){ eval("C = 0") }); assertTypeError(function(){ indirect_eval("C = 0") });
assertTypeError(function(){ eval("D = 0") });
assertEquals('function', typeof C); assertEquals('function', typeof C);
assertEquals('function', typeof D); assertEquals('function', typeof D);
assertTypeError("'use strong'; (function f() {class E {}; E = 0})()");
})(); })();
function constructor(body) { function constructor(body) {
......
...@@ -55,12 +55,6 @@ function assertThrowsHelper(code) { ...@@ -55,12 +55,6 @@ function assertThrowsHelper(code) {
" function f() { if (false) { x; } } var x; f(); \n" + " 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: // Use occurring in the initializer of the declaration:
assertThrowsHelper("let x = x + 1;"); assertThrowsHelper("let x = x + 1;");
assertThrowsHelper("let x = x;"); assertThrowsHelper("let x = x;");
...@@ -215,14 +209,6 @@ function assertThrowsHelper(code) { ...@@ -215,14 +209,6 @@ function assertThrowsHelper(code) {
var1, var2a, var2b, var2c; 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(); class C1 { constructor() { C1; } }; new C1();
let C2 = class C3 { constructor() { C3; } }; new C2(); 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 @@ ...@@ -10,7 +10,6 @@
assertThrows("function f() { 'use strong'; 0 == 0 }", SyntaxError); assertThrows("function f() { 'use strong'; 0 == 0 }", SyntaxError);
assertThrows("'use strong'; function f() { 0 == 0 }", SyntaxError); assertThrows("'use strong'; function f() { 0 == 0 }", SyntaxError);
assertThrows("'use strong'; function f() { function g() { 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("function f() { 'use strong' } 0 == 0"));
assertTrue(eval("eval('\\\'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