Commit bcb1b873 authored by ishell's avatar ishell Committed by Commit bot

[es8] Throw SyntaxError when tail call expressions occur in non-strict mode.

BUG=v8:4915
LOG=N

Review-Url: https://codereview.chromium.org/1955393002
Cr-Commit-Position: refs/heads/master@{#36105}
parent 4cad4c05
......@@ -446,6 +446,8 @@ class CallSite {
T(UnexpectedReserved, "Unexpected reserved word") \
T(UnexpectedStrictReserved, "Unexpected strict mode reserved word") \
T(UnexpectedSuper, "'super' keyword unexpected here") \
T(UnexpectedSloppyTailCall, \
"Tail call expressions are not allowed in non-strict mode") \
T(UnexpectedNewTarget, "new.target expression is not allowed here") \
T(UnexpectedTailCall, "Tail call expression is not allowed here") \
T(UnexpectedTailCallInCatchBlock, \
......
......@@ -2228,6 +2228,17 @@ ParserBase<Traits>::ParseTailCallExpression(ExpressionClassifier* classifier,
CheckNoTailCallExpressions(classifier, CHECK_OK);
Scanner::Location loc(pos, scanner()->location().end_pos);
if (!expression->IsCall()) {
Scanner::Location sub_loc(sub_expression_pos, loc.end_pos);
ReportMessageAt(sub_loc, MessageTemplate::kUnexpectedInsideTailCall);
*ok = false;
return Traits::EmptyExpression();
}
if (!is_strict(language_mode())) {
ReportMessageAt(loc, MessageTemplate::kUnexpectedSloppyTailCall);
*ok = false;
return Traits::EmptyExpression();
}
ReturnExprContext return_expr_context =
function_state_->return_expr_context();
if (return_expr_context != ReturnExprContext::kInsideValidReturnStatement) {
......@@ -2250,12 +2261,6 @@ ParserBase<Traits>::ParseTailCallExpression(ExpressionClassifier* classifier,
*ok = false;
return Traits::EmptyExpression();
}
if (!expression->IsCall()) {
Scanner::Location sub_loc(sub_expression_pos, loc.end_pos);
ReportMessageAt(sub_loc, MessageTemplate::kUnexpectedInsideTailCall);
*ok = false;
return Traits::EmptyExpression();
}
classifier->RecordTailCallExpressionError(
loc, MessageTemplate::kUnexpectedTailCall);
function_state_->AddExpressionInTailPosition(expression, loc);
......
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
// Flags: --harmony-explicit-tailcalls
"use strict";
function f() {
return 1;
......
*%(basename)s:12: SyntaxError: Tail call expression is not allowed here
*%(basename)s:13: SyntaxError: Tail call expression is not allowed here
return continue f() - a ;
^^^^^^^^^^^^
SyntaxError: Tail call expression is not allowed here
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
// Flags: --harmony-explicit-tailcalls
"use strict";
function f() {
return 1;
......
*%(basename)s:12: SyntaxError: Tail call expression is not allowed here
*%(basename)s:13: SyntaxError: Tail call expression is not allowed here
return b + continue f() ;
^^^^^^^^^^^^
SyntaxError: Tail call expression is not allowed here
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
// Flags: --harmony-explicit-tailcalls
"use strict";
function f() {
return 1;
......
*%(basename)s:12: SyntaxError: Tail call expression is not allowed here
*%(basename)s:13: SyntaxError: Tail call expression is not allowed here
return 1, 2, 3, continue f() , 4 ;
^^^^^^^^^^^^
SyntaxError: Tail call expression is not allowed here
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
// Flags: --harmony-explicit-tailcalls
"use strict";
function g() {
return class A extends continue f() {};
......
*%(basename)s:8: SyntaxError: Tail call expression is not allowed here
*%(basename)s:9: SyntaxError: Tail call expression is not allowed here
return class A extends continue f() {};
^^^^^^^^^^^^
SyntaxError: Tail call expression is not allowed here
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
// Flags: --harmony-explicit-tailcalls
"use strict";
function f() {
return 1;
......
*%(basename)s:13: SyntaxError: Tail call expression in for-in/of body
*%(basename)s:14: SyntaxError: Tail call expression in for-in/of body
return continue f() ;
^^^^^^^^^^^^
SyntaxError: Tail call expression in for-in/of body
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
// Flags: --harmony-explicit-tailcalls
"use strict";
function f() {
return 1;
......
*%(basename)s:13: SyntaxError: Tail call expression in for-in/of body
*%(basename)s:14: SyntaxError: Tail call expression in for-in/of body
return continue f() ;
^^^^^^^^^^^^
SyntaxError: Tail call expression in for-in/of body
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
// Flags: --harmony-explicit-tailcalls
"use strict";
function f() {
return 1;
......
*%(basename)s:12: SyntaxError: Tail call expression is not allowed here
*%(basename)s:13: SyntaxError: Tail call expression is not allowed here
return continue f() && a ;
^^^^^^^^^^^^
SyntaxError: Tail call expression is not allowed here
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
// Flags: --harmony-explicit-tailcalls
"use strict";
function f() {
return 1;
......
*%(basename)s:12: SyntaxError: Tail call expression is not allowed here
*%(basename)s:13: SyntaxError: Tail call expression is not allowed here
return continue f() || a ;
^^^^^^^^^^^^
SyntaxError: Tail call expression is not allowed here
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
// Flags: --harmony-explicit-tailcalls
"use strict";
function g() {
class A {};
......
*%(basename)s:11: SyntaxError: Tail call expression is not allowed here
*%(basename)s:12: SyntaxError: Tail call expression is not allowed here
return continue f() ;
^^^^^^^^^^^^
SyntaxError: Tail call expression is not allowed here
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
// Flags: --harmony-explicit-tailcalls
"use strict";
function f() {
return 1;
......
*%(basename)s:15: SyntaxError: Tail call expression in catch block when finally block is also present
*%(basename)s:16: SyntaxError: Tail call expression in catch block when finally block is also present
return continue f() ;
^^^^^^^^^^^^
SyntaxError: Tail call expression in catch block when finally block is also present
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
// Flags: --harmony-explicit-tailcalls
"use strict";
function f() {
return 1;
......
*%(basename)s:16: SyntaxError: Tail call expression in try block
*%(basename)s:17: SyntaxError: Tail call expression in try block
return continue f() ;
^^^^^^^^^^^^
SyntaxError: Tail call expression in try block
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
// Flags: --harmony-explicit-tailcalls
"use strict";
function f() {
return 1;
......
*%(basename)s:13: SyntaxError: Tail call expression in try block
*%(basename)s:14: SyntaxError: Tail call expression in try block
return continue f() ;
^^^^^^^^^^^^
SyntaxError: Tail call expression in try block
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
// Flags: --harmony-explicit-tailcalls
"use strict";
function f() {
return 1;
......
*%(basename)s:12: SyntaxError: Tail call expression is not allowed here
*%(basename)s:13: SyntaxError: Tail call expression is not allowed here
return (continue f(1)) (2) ;
^^^^^^^^^^^^^^
SyntaxError: Tail call expression is not allowed here
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
// Flags: --harmony-explicit-tailcalls
"use strict";
function g(x) {
return continue x ;
......
*%(basename)s:8: SyntaxError: Unexpected expression inside tail call
*%(basename)s:9: SyntaxError: Unexpected expression inside tail call
return continue x ;
^
SyntaxError: Unexpected expression inside tail call
// 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 f() ;
}
*%(basename)s:8: SyntaxError: Tail call expressions are not allowed in non-strict mode
return continue f() ;
^^^^^^^^^^^^^
SyntaxError: Tail call expressions are not allowed in non-strict mode
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
// Flags: --harmony-explicit-tailcalls
"use strict";
function f() {
return 1;
......
*%(basename)s:12: SyntaxError: Tail call expression is not allowed here
*%(basename)s:13: SyntaxError: Tail call expression is not allowed here
var x = continue f() ;
^^^^^^^^^^^^^
SyntaxError: Tail call expression is not allowed here
......@@ -261,9 +261,8 @@ function f_153(expected_call_stack, a) {
}
%NeverOptimizeFunction(g);
var context = 10;
function f(v) {
return g(context);
return g();
}
%SetForceInlineFlag(f);
......
This diff is collapsed.
......@@ -4,6 +4,7 @@
// Flags: --allow-natives-syntax --harmony-explicit-tailcalls
// Flags: --harmony-do-expressions
"use strict";
var SyntaxErrorTests = [
{ msg: "Unexpected expression inside tail call",
......@@ -222,17 +223,14 @@ var SyntaxErrorTests = [
{ src: `()=>{ switch (continue foo()) { case 1: break; } ; }`,
err: ` ^^^^^^^^^^^^^^`,
},
{ src: `()=>{ with (continue foo()) { smth; } }`,
err: ` ^^^^^^^^^^^^^^`,
},
{ src: `()=>{ let x = continue foo() }`,
err: ` ^^^^^^^^^^^^^^`,
},
{ src: `()=>{ const c = continue foo() }`,
err: ` ^^^^^^^^^^^^^^^`,
},
{ src: `class A {}; class B extends A { constructor() { return continue super () ; } }`,
err: ` ^^^^^^^^^^^^^^^^^`,
{ src: `class A {}; class B extends A { constructor() { return continue foo () ; } }`,
err: ` ^^^^^^^^^^^^^^^`,
},
{ src: `class A extends continue f () {}; }`,
err: ` ^^^^^^^^^^^^^`,
......@@ -312,13 +310,13 @@ var NoErrorTests = [
(function() {
for (test_set of SyntaxErrorTests) {
for (var test_set of SyntaxErrorTests) {
var expected_message = "SyntaxError: " + test_set.msg;
for (test of test_set.tests) {
for (var test of test_set.tests) {
var passed = true;
var e = null;
try {
Realm.eval(0, test.src);
eval(test.src);
} catch (ee) {
e = ee;
}
......@@ -359,9 +357,10 @@ var NoErrorTests = [
(function() {
for (src of NoErrorTests) {
for (var src of NoErrorTests) {
print("=======================================");
print("Source | " + src);
src = `"use strict"; ` + src;
Realm.eval(0, src);
print("PASSED");
print();
......
......@@ -4,10 +4,27 @@
// Flags: --allow-natives-syntax --harmony-explicit-tailcalls --stack-size=100
//
// Tail calls work only in strict mode.
//
(function() {
function f(n) {
if (n <= 0) {
return "foo";
}
return f(n - 1);
}
assertThrows(()=>{ f(1e5) });
%OptimizeFunctionOnNextCall(f);
assertThrows(()=>{ f(1e5) });
})();
//
// Tail call normal functions.
//
(function() {
"use strict";
function f(n) {
if (n <= 0) {
return "foo";
......@@ -21,6 +38,7 @@
(function() {
"use strict";
function f(n) {
if (n <= 0) {
return "foo";
......@@ -34,6 +52,7 @@
(function() {
"use strict";
function f(n){
if (n <= 0) {
return "foo";
......@@ -55,6 +74,7 @@
(function() {
"use strict";
function f(n){
if (n <= 0) {
return "foo";
......@@ -79,6 +99,7 @@
// Tail call bound functions.
//
(function() {
"use strict";
function f0(n) {
if (n <= 0) {
return "foo";
......@@ -96,6 +117,7 @@
(function() {
"use strict";
function f0(n){
if (n <= 0) {
return "foo";
......
......@@ -5,6 +5,8 @@
// Flags: --allow-natives-syntax --harmony-explicit-tailcalls
// Flags: --harmony-do-expressions
"use strict";
Error.prepareStackTrace = (error,stack) => {
error.strace = stack;
return error.message + "\n at " + stack.join("\n at ");
......@@ -20,6 +22,8 @@ function CheckStackTrace(expected) {
assertEquals(expected[i].name, stack[i + 1].getFunctionName());
}
}
%NeverOptimizeFunction(CheckStackTrace);
function f(expected_call_stack, a, b) {
CheckStackTrace(expected_call_stack);
......@@ -221,6 +225,87 @@ function f_153(expected_call_stack, a) {
})();
// Tail calling from getter.
(function() {
function g(v) {
CheckStackTrace([g, test]);
%DeoptimizeFunction(test);
return 153;
}
%NeverOptimizeFunction(g);
function f(v) {
return continue g();
}
%SetForceInlineFlag(f);
function test() {
var o = {};
o.__defineGetter__('p', f);
assertEquals(153, o.p);
}
test();
test();
%OptimizeFunctionOnNextCall(test);
test();
})();
// Tail calling from setter.
(function() {
function g() {
CheckStackTrace([g, test]);
%DeoptimizeFunction(test);
return 153;
}
%NeverOptimizeFunction(g);
function f(v) {
return continue g();
}
%SetForceInlineFlag(f);
function test() {
var o = {};
o.__defineSetter__('q', f);
assertEquals(1, o.q = 1);
}
test();
test();
%OptimizeFunctionOnNextCall(test);
test();
})();
// Tail calling from constructor.
(function() {
function g(context) {
CheckStackTrace([g, test]);
%DeoptimizeFunction(test);
return {x: 153};
}
%NeverOptimizeFunction(g);
function A() {
this.x = 42;
return continue g();
}
function test() {
var o = new A();
%DebugPrint(o);
assertEquals(153, o.x);
}
test();
test();
%OptimizeFunctionOnNextCall(test);
test();
})();
// Tail calling via various expressions.
(function() {
function g1(a) {
......@@ -294,6 +379,38 @@ function f_153(expected_call_stack, a) {
})();
// Tail calling from various statements.
(function() {
function g3() {
for (var i = 0; i < 10; i++) {
return continue f_153([f_153, test]);
}
}
function g4() {
while (true) {
return continue f_153([f_153, test]);
}
}
function g5() {
do {
return continue f_153([f_153, test]);
} while (true);
}
function test() {
assertEquals(153, g3());
assertEquals(153, g4());
assertEquals(153, g5());
}
test();
test();
%OptimizeFunctionOnNextCall(test);
test();
})();
// Test tail calls from try-catch constructs.
(function() {
function tc1(a) {
......
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