Commit 11efb976 authored by ishell's avatar ishell Committed by Commit bot

[es8] Throw SyntaxError when trying to tail call a direct eval.

BUG=v8:4999, v8:4915
LOG=N

Review-Url: https://codereview.chromium.org/1964603002
Cr-Commit-Position: refs/heads/master@{#36126}
parent 7b372433
...@@ -454,6 +454,7 @@ class CallSite { ...@@ -454,6 +454,7 @@ class CallSite {
"Tail call expression in catch block when finally block is also present") \ "Tail call expression in catch block when finally block is also present") \
T(UnexpectedTailCallInForInOf, "Tail call expression in for-in/of body") \ T(UnexpectedTailCallInForInOf, "Tail call expression in for-in/of body") \
T(UnexpectedTailCallInTryBlock, "Tail call expression in try block") \ T(UnexpectedTailCallInTryBlock, "Tail call expression in try block") \
T(UnexpectedTailCallOfEval, "Tail call of a direct eval is not allowed") \
T(UnexpectedTemplateString, "Unexpected template string") \ T(UnexpectedTemplateString, "Unexpected template string") \
T(UnexpectedToken, "Unexpected token %") \ T(UnexpectedToken, "Unexpected token %") \
T(UnexpectedTokenIdentifier, "Unexpected identifier") \ T(UnexpectedTokenIdentifier, "Unexpected identifier") \
......
...@@ -2234,6 +2234,12 @@ ParserBase<Traits>::ParseTailCallExpression(ExpressionClassifier* classifier, ...@@ -2234,6 +2234,12 @@ ParserBase<Traits>::ParseTailCallExpression(ExpressionClassifier* classifier,
*ok = false; *ok = false;
return Traits::EmptyExpression(); return Traits::EmptyExpression();
} }
if (Traits::IsDirectEvalCall(expression)) {
Scanner::Location sub_loc(sub_expression_pos, loc.end_pos);
ReportMessageAt(sub_loc, MessageTemplate::kUnexpectedTailCallOfEval);
*ok = false;
return Traits::EmptyExpression();
}
if (!is_strict(language_mode())) { if (!is_strict(language_mode())) {
ReportMessageAt(loc, MessageTemplate::kUnexpectedSloppyTailCall); ReportMessageAt(loc, MessageTemplate::kUnexpectedSloppyTailCall);
*ok = false; *ok = false;
......
...@@ -371,6 +371,12 @@ class ParserTraits { ...@@ -371,6 +371,12 @@ class ParserTraits {
return expression->AsVariableProxy()->raw_name(); return expression->AsVariableProxy()->raw_name();
} }
bool IsDirectEvalCall(Expression* expression) {
if (!expression->IsCall()) return false;
expression = expression->AsCall()->expression();
return IsIdentifier(expression) && IsEval(AsIdentifier(expression));
}
static bool IsBoilerplateProperty(ObjectLiteral::Property* property) { static bool IsBoilerplateProperty(ObjectLiteral::Property* property) {
return ObjectLiteral::IsBoilerplateProperty(property); return ObjectLiteral::IsBoilerplateProperty(property);
} }
......
...@@ -175,6 +175,12 @@ class PreParserExpression { ...@@ -175,6 +175,12 @@ class PreParserExpression {
ExpressionTypeField::encode(kCallExpression)); ExpressionTypeField::encode(kCallExpression));
} }
static PreParserExpression CallEval() {
return PreParserExpression(
TypeField::encode(kExpression) |
ExpressionTypeField::encode(kCallEvalExpression));
}
static PreParserExpression SuperCallReference() { static PreParserExpression SuperCallReference() {
return PreParserExpression( return PreParserExpression(
TypeField::encode(kExpression) | TypeField::encode(kExpression) |
...@@ -236,7 +242,13 @@ class PreParserExpression { ...@@ -236,7 +242,13 @@ class PreParserExpression {
bool IsCall() const { bool IsCall() const {
return TypeField::decode(code_) == kExpression && return TypeField::decode(code_) == kExpression &&
ExpressionTypeField::decode(code_) == kCallExpression; (ExpressionTypeField::decode(code_) == kCallExpression ||
ExpressionTypeField::decode(code_) == kCallEvalExpression);
}
bool IsDirectEvalCall() const {
return TypeField::decode(code_) == kExpression &&
ExpressionTypeField::decode(code_) == kCallEvalExpression;
} }
bool IsSuperCallReference() const { bool IsSuperCallReference() const {
...@@ -294,6 +306,7 @@ class PreParserExpression { ...@@ -294,6 +306,7 @@ class PreParserExpression {
kThisPropertyExpression, kThisPropertyExpression,
kPropertyExpression, kPropertyExpression,
kCallExpression, kCallExpression,
kCallEvalExpression,
kSuperCallReference, kSuperCallReference,
kNoTemplateTagExpression, kNoTemplateTagExpression,
kAssignment kAssignment
...@@ -503,6 +516,9 @@ class PreParserFactory { ...@@ -503,6 +516,9 @@ class PreParserFactory {
PreParserExpression NewCall(PreParserExpression expression, PreParserExpression NewCall(PreParserExpression expression,
PreParserExpressionList arguments, PreParserExpressionList arguments,
int pos) { int pos) {
if (expression.IsIdentifier() && expression.AsIdentifier().IsEval()) {
return PreParserExpression::CallEval();
}
return PreParserExpression::Call(); return PreParserExpression::Call();
} }
PreParserExpression NewCallNew(PreParserExpression expression, PreParserExpression NewCallNew(PreParserExpression expression,
...@@ -635,6 +651,14 @@ class PreParserTraits { ...@@ -635,6 +651,14 @@ class PreParserTraits {
return expression.AsIdentifier(); return expression.AsIdentifier();
} }
static bool IsEvalIdentifier(PreParserExpression expression) {
return IsIdentifier(expression) && IsEval(AsIdentifier(expression));
}
static bool IsDirectEvalCall(PreParserExpression expression) {
return expression.IsDirectEvalCall();
}
static bool IsFutureStrictReserved(PreParserIdentifier identifier) { static bool IsFutureStrictReserved(PreParserIdentifier identifier) {
return identifier.IsFutureStrictReserved(); return identifier.IsFutureStrictReserved();
} }
......
// Copyright 2016 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: --harmony-explicit-tailcalls
function g() {
return continue eval ("f()") ;
}
*%(basename)s:8: SyntaxError: Tail call of a direct eval is not allowed
return continue eval ("f()") ;
^^^^^^^^^^^^^
SyntaxError: Tail call of a direct eval is not allowed
...@@ -270,6 +270,25 @@ var SyntaxErrorTests = [ ...@@ -270,6 +270,25 @@ var SyntaxErrorTests = [
}, },
], ],
}, },
{ msg: "Tail call of a direct eval is not allowed",
tests: [
{ src: `()=>{ return continue eval(" foo () " ) ; }`,
err: ` ^^^^^^^^^^^^^^^^^`,
},
{ src: `()=>{ return a || continue eval("", 1, 2) ; }`,
err: ` ^^^^^^^^^^^^^^`,
},
{ src: `()=>{ return a, continue eval ( ) ; }`,
err: ` ^^^^^^^^^`,
},
{ src: `()=> a, continue eval ( ) ; `,
err: ` ^^^^^^^^^`,
},
{ src: `()=> a || continue eval (' ' ) ; `,
err: ` ^^^^^^^^^^^^`,
},
],
},
{ msg: "Undefined label 'foo'", { msg: "Undefined label 'foo'",
tests: [ tests: [
{ src: `()=>{ continue foo () ; }`, { src: `()=>{ continue foo () ; }`,
...@@ -285,6 +304,7 @@ var NoErrorTests = [ ...@@ -285,6 +304,7 @@ var NoErrorTests = [
`()=>{ return continue a.b.c.foo () ; }`, `()=>{ return continue a.b.c.foo () ; }`,
`()=>{ return continue a().b.c().d.foo () ; }`, `()=>{ return continue a().b.c().d.foo () ; }`,
`()=>{ return continue foo (1)(2)(3, 4) ; }`, `()=>{ return continue foo (1)(2)(3, 4) ; }`,
`()=>{ return continue (0, eval)(); }`,
`()=>{ return ( continue b() ) ; }`, `()=>{ return ( continue b() ) ; }`,
"()=>{ return continue bar`ab cd ef` ; }", "()=>{ return continue bar`ab cd ef` ; }",
"()=>{ return continue bar`ab ${cd} ef` ; }", "()=>{ return continue bar`ab ${cd} ef` ; }",
......
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