[parser] Fix parsing "new super.x"

It's not "(new super).x" but "new (super.x)".

Bug: v8:11261
Change-Id: Ifc9cae038c1dc8fcdb096e213b4ac79ea20e9238
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2593248
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Auto-Submit: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71763}
This commit is contained in:
Marja Hölttä 2020-12-15 12:51:07 +01:00 committed by Commit Bot
parent c2e9357c36
commit 6f290ef767
2 changed files with 26 additions and 12 deletions

View File

@ -1207,7 +1207,7 @@ class ParserBase {
bool name_is_strict_reserved,
int class_token_pos);
ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool tagged);
ExpressionT ParseSuperExpression(bool is_new);
ExpressionT ParseSuperExpression();
ExpressionT ParseImportExpressions();
ExpressionT ParseNewTargetExpression();
@ -1849,8 +1849,7 @@ ParserBase<Impl>::ParsePrimaryExpression() {
return ParseFunctionExpression();
case Token::SUPER: {
const bool is_new = false;
return ParseSuperExpression(is_new);
return ParseSuperExpression();
}
case Token::IMPORT:
return ParseImportExpressions();
@ -3431,16 +3430,14 @@ ParserBase<Impl>::ParseMemberWithPresentNewPrefixesExpression() {
// new new foo means new (new foo)
// new new foo() means new (new foo())
// new new foo().bar().baz means (new (new foo()).bar()).baz
// new super.x means new (super.x)
Consume(Token::NEW);
int new_pos = position();
ExpressionT result;
CheckStackOverflow();
if (peek() == Token::SUPER) {
const bool is_new = true;
result = ParseSuperExpression(is_new);
} else if (peek() == Token::IMPORT && PeekAhead() == Token::LPAREN) {
if (peek() == Token::IMPORT && PeekAhead() == Token::LPAREN) {
impl()->ReportMessageAt(scanner()->peek_location(),
MessageTemplate::kImportCallNotNewExpression);
return impl()->FailureExpression();
@ -3449,6 +3446,12 @@ ParserBase<Impl>::ParseMemberWithPresentNewPrefixesExpression() {
return ParseMemberExpressionContinuation(result);
} else {
result = ParseMemberExpression();
if (result->IsSuperCallReference()) {
// new super() is never allowed
impl()->ReportMessageAt(scanner()->location(),
MessageTemplate::kUnexpectedSuper);
return impl()->FailureExpression();
}
}
if (peek() == Token::LPAREN) {
// NewExpression with arguments.
@ -3576,8 +3579,8 @@ ParserBase<Impl>::ParseImportExpressions() {
}
template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseSuperExpression(
bool is_new) {
typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseSuperExpression() {
Consume(Token::SUPER);
int pos = position();
@ -3602,9 +3605,10 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseSuperExpression(
UseThis();
return impl()->NewSuperPropertyReference(pos);
}
// new super() is never allowed.
// super() is only allowed in derived constructor
if (!is_new && peek() == Token::LPAREN && IsDerivedConstructor(kind)) {
// super() is only allowed in derived constructor. new super() is never
// allowed; it's reported as an error by
// ParseMemberWithPresentNewPrefixesExpression.
if (peek() == Token::LPAREN && IsDerivedConstructor(kind)) {
// TODO(rossberg): This might not be the correct FunctionState for the
// method here.
expression_scope()->RecordThisUse();

View File

@ -0,0 +1,10 @@
// Copyright 2020 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.
let obj = ({ __proto__: { x: class {} }, y() { return new super.x; } });
obj.y();
class A { static a = class {} }
class B extends A { static b() { return new super.a(); } }
B.b();