Revert of Parse arrow functions at proper precedence level (patchset #2 id:60001 of https://codereview.chromium.org/1286383005/ )
Reason for revert: Breaks layout test. Please change test expectation on blink first. --- /mnt/data/b/build/slave/V8-Blink_Linux_64/build/layout-test-results/inspector/sources/debugger-pause/debugger-pause-in-internal-expected.txt +++ /mnt/data/b/build/slave/V8-Blink_Linux_64/build/layout-test-results/inspector/sources/debugger-pause/debugger-pause-in-internal-actual.txt @@ -1,4 +1,4 @@ -CONSOLE ERROR: line 9: Uncaught SyntaxError: Expected () to start arrow function, but got '}' instead of '=>' +CONSOLE ERROR: line 9: Uncaught SyntaxError: Unexpected token ) Tests that pause on exception in internal script does not crash. Script source was shown. Original issue's description: > Parse arrow functions at proper precedence level > > BUG=v8:4211 > LOG=Y > R=rossberg@chromium.org > > Committed: https://crrev.com/9271b0ccf9ddb217deb1f0b9ef9b59b64dc40214 > Cr-Commit-Position: refs/heads/master@{#30298} TBR=rossberg@chromium.org,mstarzinger@chromium.org,fennyfanny655@gmail.com,machenbach@chromium.org,wingo@igalia.com NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:4211 Review URL: https://codereview.chromium.org/1315503002 Cr-Commit-Position: refs/heads/master@{#30318}
This commit is contained in:
parent
2911007240
commit
cc97e524a1
@ -174,9 +174,6 @@ void AstLiteralReindexer::VisitSpread(Spread* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AstLiteralReindexer::VisitEmptyParentheses(EmptyParentheses* node) {}
|
|
||||||
|
|
||||||
|
|
||||||
void AstLiteralReindexer::VisitForInStatement(ForInStatement* node) {
|
void AstLiteralReindexer::VisitForInStatement(ForInStatement* node) {
|
||||||
Visit(node->each());
|
Visit(node->each());
|
||||||
Visit(node->enumerable());
|
Visit(node->enumerable());
|
||||||
|
@ -371,11 +371,6 @@ void AstNumberingVisitor::VisitSpread(Spread* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AstNumberingVisitor::VisitEmptyParentheses(EmptyParentheses* node) {
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) {
|
void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) {
|
||||||
IncrementNodeCount();
|
IncrementNodeCount();
|
||||||
DisableSelfOptimization();
|
DisableSelfOptimization();
|
||||||
|
18
src/ast.h
18
src/ast.h
@ -88,8 +88,7 @@ namespace internal {
|
|||||||
V(ThisFunction) \
|
V(ThisFunction) \
|
||||||
V(SuperPropertyReference) \
|
V(SuperPropertyReference) \
|
||||||
V(SuperCallReference) \
|
V(SuperCallReference) \
|
||||||
V(CaseClause) \
|
V(CaseClause)
|
||||||
V(EmptyParentheses)
|
|
||||||
|
|
||||||
#define AST_NODE_LIST(V) \
|
#define AST_NODE_LIST(V) \
|
||||||
DECLARATION_NODE_LIST(V) \
|
DECLARATION_NODE_LIST(V) \
|
||||||
@ -2849,17 +2848,6 @@ class SuperCallReference final : public Expression {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// This class is produced when parsing the () in arrow functions without any
|
|
||||||
// arguments and is not actually a valid expression.
|
|
||||||
class EmptyParentheses final : public Expression {
|
|
||||||
public:
|
|
||||||
DECLARE_NODE_TYPE(EmptyParentheses)
|
|
||||||
|
|
||||||
private:
|
|
||||||
EmptyParentheses(Zone* zone, int pos) : Expression(zone, pos) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#undef DECLARE_NODE_TYPE
|
#undef DECLARE_NODE_TYPE
|
||||||
|
|
||||||
|
|
||||||
@ -3645,10 +3633,6 @@ class AstNodeFactory final BASE_EMBEDDED {
|
|||||||
this_function_var, pos);
|
this_function_var, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
EmptyParentheses* NewEmptyParentheses(int pos) {
|
|
||||||
return new (zone_) EmptyParentheses(zone_, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Zone* zone_;
|
Zone* zone_;
|
||||||
AstValueFactory* ast_value_factory_;
|
AstValueFactory* ast_value_factory_;
|
||||||
|
@ -2867,12 +2867,6 @@ void AstGraphBuilder::VisitSpread(Spread* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AstGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
|
|
||||||
// Handled entirely by the parser itself.
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
|
void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
|
||||||
Node* value = GetFunctionClosure();
|
Node* value = GetFunctionClosure();
|
||||||
ast_context()->ProduceValue(value);
|
ast_context()->ProduceValue(value);
|
||||||
|
@ -193,9 +193,6 @@ void ALAA::VisitCompareOperation(CompareOperation* e) {
|
|||||||
void ALAA::VisitSpread(Spread* e) { Visit(e->expression()); }
|
void ALAA::VisitSpread(Spread* e) { Visit(e->expression()); }
|
||||||
|
|
||||||
|
|
||||||
void ALAA::VisitEmptyParentheses(EmptyParentheses* e) { UNREACHABLE(); }
|
|
||||||
|
|
||||||
|
|
||||||
void ALAA::VisitCaseClause(CaseClause* cc) {
|
void ALAA::VisitCaseClause(CaseClause* cc) {
|
||||||
if (!cc->is_default()) Visit(cc->label());
|
if (!cc->is_default()) Visit(cc->label());
|
||||||
VisitStatements(cc->statements());
|
VisitStatements(cc->statements());
|
||||||
|
@ -1399,11 +1399,6 @@ void FullCodeGenerator::ExitTryBlock(int handler_index) {
|
|||||||
void FullCodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
|
void FullCodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
|
FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
|
||||||
int* stack_depth, int* context_length) {
|
int* stack_depth, int* context_length) {
|
||||||
// The macros used here must preserve the result register.
|
// The macros used here must preserve the result register.
|
||||||
|
@ -11525,11 +11525,6 @@ void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
|
|||||||
void HOptimizedGraphBuilder::VisitSpread(Spread* expr) { UNREACHABLE(); }
|
void HOptimizedGraphBuilder::VisitSpread(Spread* expr) { UNREACHABLE(); }
|
||||||
|
|
||||||
|
|
||||||
void HOptimizedGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
|
HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
|
||||||
// If we share optimized code between different closures, the
|
// If we share optimized code between different closures, the
|
||||||
// this-function is not a constant, except inside an inlined body.
|
// this-function is not a constant, except inside an inlined body.
|
||||||
|
@ -335,11 +335,6 @@ void BytecodeGenerator::VisitCompareOperation(CompareOperation* node) {
|
|||||||
void BytecodeGenerator::VisitSpread(Spread* node) { UNIMPLEMENTED(); }
|
void BytecodeGenerator::VisitSpread(Spread* node) { UNIMPLEMENTED(); }
|
||||||
|
|
||||||
|
|
||||||
void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* node) {
|
|
||||||
UNIMPLEMENTED();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void BytecodeGenerator::VisitThisFunction(ThisFunction* node) {
|
void BytecodeGenerator::VisitThisFunction(ThisFunction* node) {
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
@ -308,6 +308,8 @@ class CallSite {
|
|||||||
T(MalformedArrowFunParamList, "Malformed arrow function parameter list") \
|
T(MalformedArrowFunParamList, "Malformed arrow function parameter list") \
|
||||||
T(MalformedRegExp, "Invalid regular expression: /%/: %") \
|
T(MalformedRegExp, "Invalid regular expression: /%/: %") \
|
||||||
T(MalformedRegExpFlags, "Invalid regular expression flags") \
|
T(MalformedRegExpFlags, "Invalid regular expression flags") \
|
||||||
|
T(MissingArrow, \
|
||||||
|
"Expected () to start arrow function, but got '%' instead of '=>'") \
|
||||||
T(ModuleExportUndefined, "Export '%' is not defined in module") \
|
T(ModuleExportUndefined, "Export '%' is not defined in module") \
|
||||||
T(MultipleDefaultsInSwitch, \
|
T(MultipleDefaultsInSwitch, \
|
||||||
"More than one default clause in switch statement") \
|
"More than one default clause in switch statement") \
|
||||||
|
@ -3934,8 +3934,6 @@ void ParserTraits::ParseArrowFunctionFormalParameterList(
|
|||||||
ParserFormalParameters* parameters, Expression* expr,
|
ParserFormalParameters* parameters, Expression* expr,
|
||||||
const Scanner::Location& params_loc,
|
const Scanner::Location& params_loc,
|
||||||
Scanner::Location* duplicate_loc, bool* ok) {
|
Scanner::Location* duplicate_loc, bool* ok) {
|
||||||
if (expr->IsEmptyParentheses()) return;
|
|
||||||
|
|
||||||
ParseArrowFunctionFormalParameters(parameters, expr, params_loc,
|
ParseArrowFunctionFormalParameters(parameters, expr, params_loc,
|
||||||
duplicate_loc, ok);
|
duplicate_loc, ok);
|
||||||
if (!*ok) return;
|
if (!*ok) return;
|
||||||
|
@ -368,11 +368,6 @@ void Parser::PatternRewriter::VisitSpread(Spread* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Parser::PatternRewriter::VisitEmptyParentheses(EmptyParentheses* node) {
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// =============== UNREACHABLE =============================
|
// =============== UNREACHABLE =============================
|
||||||
|
|
||||||
void Parser::PatternRewriter::Visit(AstNode* node) { UNREACHABLE(); }
|
void Parser::PatternRewriter::Visit(AstNode* node) { UNREACHABLE(); }
|
||||||
|
@ -1308,10 +1308,6 @@ class PreParserFactory {
|
|||||||
return PreParserExpression::Spread(expression);
|
return PreParserExpression::Spread(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
PreParserExpression NewEmptyParentheses(int pos) {
|
|
||||||
return PreParserExpression::Default();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the object itself as AstVisitor and implement the needed
|
// Return the object itself as AstVisitor and implement the needed
|
||||||
// dummy method right in this class.
|
// dummy method right in this class.
|
||||||
PreParserFactory* visitor() { return this; }
|
PreParserFactory* visitor() { return this; }
|
||||||
@ -2266,35 +2262,38 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
|
|||||||
}
|
}
|
||||||
BindingPatternUnexpectedToken(classifier);
|
BindingPatternUnexpectedToken(classifier);
|
||||||
Consume(Token::LPAREN);
|
Consume(Token::LPAREN);
|
||||||
if (Check(Token::RPAREN)) {
|
if (allow_harmony_arrow_functions() && Check(Token::RPAREN)) {
|
||||||
// ()=>x. The continuation that looks for the => is in
|
// As a primary expression, the only thing that can follow "()" is "=>".
|
||||||
// ParseAssignmentExpression.
|
|
||||||
classifier->RecordExpressionError(scanner()->location(),
|
|
||||||
MessageTemplate::kUnexpectedToken,
|
|
||||||
Token::String(Token::RPAREN));
|
|
||||||
classifier->RecordBindingPatternError(scanner()->location(),
|
classifier->RecordBindingPatternError(scanner()->location(),
|
||||||
MessageTemplate::kUnexpectedToken,
|
MessageTemplate::kUnexpectedToken,
|
||||||
Token::String(Token::RPAREN));
|
Token::String(Token::RPAREN));
|
||||||
result = factory()->NewEmptyParentheses(beg_pos);
|
// Give a good error to the user who might have typed e.g. "return();".
|
||||||
} else if (allow_harmony_rest_parameters() && Check(Token::ELLIPSIS)) {
|
if (peek() != Token::ARROW) {
|
||||||
// (...x)=>x. The continuation that looks for the => is in
|
ReportUnexpectedTokenAt(scanner_->peek_location(), peek(),
|
||||||
// ParseAssignmentExpression.
|
MessageTemplate::kMissingArrow);
|
||||||
int ellipsis_pos = scanner()->location().beg_pos;
|
|
||||||
classifier->RecordExpressionError(scanner()->location(),
|
|
||||||
MessageTemplate::kUnexpectedToken,
|
|
||||||
Token::String(Token::ELLIPSIS));
|
|
||||||
Scanner::Location expr_loc = scanner()->peek_location();
|
|
||||||
Token::Value tok = peek();
|
|
||||||
result = this->ParseAssignmentExpression(true, classifier, CHECK_OK);
|
|
||||||
// Patterns are not allowed as rest parameters. There is no way we can
|
|
||||||
// succeed so go ahead and use the convenient ReportUnexpectedToken
|
|
||||||
// interface.
|
|
||||||
if (!Traits::IsIdentifier(result)) {
|
|
||||||
ReportUnexpectedTokenAt(expr_loc, tok);
|
|
||||||
*ok = false;
|
*ok = false;
|
||||||
return this->EmptyExpression();
|
return this->EmptyExpression();
|
||||||
}
|
}
|
||||||
result = factory()->NewSpread(result, ellipsis_pos);
|
Scope* scope =
|
||||||
|
this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction);
|
||||||
|
FormalParametersT parameters(scope);
|
||||||
|
scope->set_start_position(beg_pos);
|
||||||
|
ExpressionClassifier args_classifier;
|
||||||
|
result = this->ParseArrowFunctionLiteral(parameters, args_classifier,
|
||||||
|
CHECK_OK);
|
||||||
|
} else if (allow_harmony_arrow_functions() &&
|
||||||
|
allow_harmony_rest_parameters() && Check(Token::ELLIPSIS)) {
|
||||||
|
// (...x) => y
|
||||||
|
Scope* scope =
|
||||||
|
this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction);
|
||||||
|
FormalParametersT formals(scope);
|
||||||
|
scope->set_start_position(beg_pos);
|
||||||
|
ExpressionClassifier formals_classifier;
|
||||||
|
formals.has_rest = true;
|
||||||
|
this->ParseFormalParameter(&formals, &formals_classifier, CHECK_OK);
|
||||||
|
Traits::DeclareFormalParameter(
|
||||||
|
formals.scope, formals.at(0), formals.is_simple,
|
||||||
|
&formals_classifier);
|
||||||
if (peek() == Token::COMMA) {
|
if (peek() == Token::COMMA) {
|
||||||
ReportMessageAt(scanner()->peek_location(),
|
ReportMessageAt(scanner()->peek_location(),
|
||||||
MessageTemplate::kParamAfterRest);
|
MessageTemplate::kParamAfterRest);
|
||||||
@ -2302,6 +2301,8 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
|
|||||||
return this->EmptyExpression();
|
return this->EmptyExpression();
|
||||||
}
|
}
|
||||||
Expect(Token::RPAREN, CHECK_OK);
|
Expect(Token::RPAREN, CHECK_OK);
|
||||||
|
result = this->ParseArrowFunctionLiteral(formals, formals_classifier,
|
||||||
|
CHECK_OK);
|
||||||
} else {
|
} else {
|
||||||
// Heuristically try to detect immediately called functions before
|
// Heuristically try to detect immediately called functions before
|
||||||
// seeing the call parentheses.
|
// seeing the call parentheses.
|
||||||
|
@ -360,11 +360,6 @@ void CallPrinter::VisitSpread(Spread* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CallPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CallPrinter::VisitThisFunction(ThisFunction* node) {}
|
void CallPrinter::VisitThisFunction(ThisFunction* node) {}
|
||||||
|
|
||||||
|
|
||||||
@ -850,11 +845,6 @@ void PrettyPrinter::VisitSpread(Spread* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PrettyPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
|
|
||||||
Print("<empty-parentheses>");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
|
void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
|
||||||
Print("<this-function>");
|
Print("<this-function>");
|
||||||
}
|
}
|
||||||
@ -1575,11 +1565,6 @@ void AstPrinter::VisitSpread(Spread* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AstPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
|
|
||||||
IndentedScope indent(this, "()");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void AstPrinter::VisitThisFunction(ThisFunction* node) {
|
void AstPrinter::VisitThisFunction(ThisFunction* node) {
|
||||||
IndentedScope indent(this, "THIS-FUNCTION");
|
IndentedScope indent(this, "THIS-FUNCTION");
|
||||||
}
|
}
|
||||||
|
@ -742,11 +742,6 @@ void AstTyper::VisitCompareOperation(CompareOperation* expr) {
|
|||||||
void AstTyper::VisitSpread(Spread* expr) { RECURSE(Visit(expr->expression())); }
|
void AstTyper::VisitSpread(Spread* expr) { RECURSE(Visit(expr->expression())); }
|
||||||
|
|
||||||
|
|
||||||
void AstTyper::VisitEmptyParentheses(EmptyParentheses* expr) {
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void AstTyper::VisitThisFunction(ThisFunction* expr) {
|
void AstTyper::VisitThisFunction(ThisFunction* expr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
*%(basename)s:7: SyntaxError: Unexpected token )
|
*%(basename)s:7: SyntaxError: Expected () to start arrow function, but got ';' instead of '=>'
|
||||||
function foo() { return(); }
|
function foo() { return(); }
|
||||||
^
|
^
|
||||||
SyntaxError: Unexpected token )
|
SyntaxError: Expected () to start arrow function, but got ';' instead of '=>'
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
// 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: --harmony-arrow-functions --harmony-rest-parameters
|
|
||||||
|
|
||||||
assertThrows("()=>{}()", SyntaxError);
|
|
||||||
assertThrows("x=>{}()", SyntaxError);
|
|
||||||
assertThrows("(...x)=>{}()", SyntaxError);
|
|
||||||
assertThrows("(x)=>{}()", SyntaxError);
|
|
||||||
assertThrows("(x,y)=>{}()", SyntaxError);
|
|
||||||
assertThrows("(x,y,...z)=>{}()", SyntaxError);
|
|
Loading…
Reference in New Issue
Block a user