summaryrefslogtreecommitdiff
path: root/deps/v8/src/parsing/parser-base.h
diff options
context:
space:
mode:
authorUjjwal Sharma <usharma1998@gmail.com>2019-03-15 18:35:06 +0530
committerRefael Ackermann <refack@gmail.com>2019-03-28 16:36:18 -0400
commitf579e1194046c50f2e6bb54348d48c8e7d1a53cf (patch)
tree9125787c758358365f74f9fd9673c14f57e67870 /deps/v8/src/parsing/parser-base.h
parent2c73868b0471fbd4038f500d076df056cbf697fe (diff)
downloadandroid-node-v8-f579e1194046c50f2e6bb54348d48c8e7d1a53cf.tar.gz
android-node-v8-f579e1194046c50f2e6bb54348d48c8e7d1a53cf.tar.bz2
android-node-v8-f579e1194046c50f2e6bb54348d48c8e7d1a53cf.zip
deps: update V8 to 7.4.288.13
PR-URL: https://github.com/nodejs/node/pull/26685 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Michaƫl Zasso <targos@protonmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com>
Diffstat (limited to 'deps/v8/src/parsing/parser-base.h')
-rw-r--r--deps/v8/src/parsing/parser-base.h545
1 files changed, 351 insertions, 194 deletions
diff --git a/deps/v8/src/parsing/parser-base.h b/deps/v8/src/parsing/parser-base.h
index 33c165cd92..3bcb8bed91 100644
--- a/deps/v8/src/parsing/parser-base.h
+++ b/deps/v8/src/parsing/parser-base.h
@@ -16,6 +16,7 @@
#include "src/base/hashmap.h"
#include "src/base/v8-fallthrough.h"
#include "src/counters.h"
+#include "src/function-kind.h"
#include "src/globals.h"
#include "src/log.h"
#include "src/message-template.h"
@@ -277,13 +278,13 @@ class ParserBase {
bool allow_##name() const { return allow_##name##_; } \
void set_allow_##name(bool allow) { allow_##name##_ = allow; }
- ALLOW_ACCESSORS(natives);
- ALLOW_ACCESSORS(harmony_public_fields);
- ALLOW_ACCESSORS(harmony_static_fields);
- ALLOW_ACCESSORS(harmony_dynamic_import);
- ALLOW_ACCESSORS(harmony_import_meta);
- ALLOW_ACCESSORS(harmony_private_methods);
- ALLOW_ACCESSORS(eval_cache);
+ ALLOW_ACCESSORS(natives)
+ ALLOW_ACCESSORS(harmony_public_fields)
+ ALLOW_ACCESSORS(harmony_static_fields)
+ ALLOW_ACCESSORS(harmony_dynamic_import)
+ ALLOW_ACCESSORS(harmony_import_meta)
+ ALLOW_ACCESSORS(harmony_private_methods)
+ ALLOW_ACCESSORS(eval_cache)
#undef ALLOW_ACCESSORS
@@ -399,7 +400,7 @@ class ParserBase {
}
void set_next_function_is_likely_called() {
- next_function_is_likely_called_ = true;
+ next_function_is_likely_called_ = !FLAG_max_lazy;
}
void RecordFunctionOrEvalCall() { contains_function_or_eval_ = true; }
@@ -480,16 +481,14 @@ class ParserBase {
struct DeclarationParsingResult {
struct Declaration {
- Declaration(ExpressionT pattern, int initializer_position,
- ExpressionT initializer)
- : pattern(pattern),
- initializer_position(initializer_position),
- initializer(initializer) {}
+ Declaration(ExpressionT pattern, ExpressionT initializer)
+ : pattern(pattern), initializer(initializer) {
+ DCHECK_IMPLIES(Impl::IsNull(pattern), Impl::IsNull(initializer));
+ }
ExpressionT pattern;
- int initializer_position;
- int value_beg_position = kNoSourcePosition;
ExpressionT initializer;
+ int value_beg_pos = kNoSourcePosition;
};
DeclarationParsingResult()
@@ -798,6 +797,7 @@ class ParserBase {
bool PeekContextualKeyword(const AstRawString* name) {
return peek() == Token::IDENTIFIER &&
+ !scanner()->next_literal_contains_escapes() &&
scanner()->NextSymbol(ast_value_factory()) == name;
}
@@ -809,14 +809,21 @@ class ParserBase {
return false;
}
- void ExpectMetaProperty(const AstRawString* property_name,
- const char* full_name, int pos);
-
- void ExpectContextualKeyword(const AstRawString* name) {
+ void ExpectContextualKeyword(const AstRawString* name,
+ const char* fullname = nullptr, int pos = -1) {
Expect(Token::IDENTIFIER);
if (V8_UNLIKELY(scanner()->CurrentSymbol(ast_value_factory()) != name)) {
ReportUnexpectedToken(scanner()->current_token());
}
+ if (V8_UNLIKELY(scanner()->literal_contains_escapes())) {
+ const char* full = fullname == nullptr
+ ? reinterpret_cast<const char*>(name->raw_data())
+ : fullname;
+ int start = pos == -1 ? position() : pos;
+ impl()->ReportMessageAt(Scanner::Location(start, end_position()),
+ MessageTemplate::kInvalidEscapedMetaProperty,
+ full);
+ }
}
bool CheckInOrOf(ForEachStatement::VisitMode* visit_mode) {
@@ -955,6 +962,26 @@ class ParserBase {
if (is_strict(language_mode)) parameters.ValidateStrictMode(impl());
}
+ // Needs to be called if the reference needs to be available from the current
+ // point. It causes the receiver to be context allocated if necessary.
+ // Returns the receiver variable that we're referencing.
+ V8_INLINE Variable* UseThis() {
+ DeclarationScope* closure_scope = scope()->GetClosureScope();
+ DeclarationScope* receiver_scope = closure_scope->GetReceiverScope();
+ Variable* var = receiver_scope->receiver();
+ var->set_is_used();
+ if (closure_scope == receiver_scope) {
+ // It's possible that we're parsing the head of an arrow function, in
+ // which case we haven't realized yet that closure_scope !=
+ // receiver_scope. Mark through the ExpressionScope for now.
+ expression_scope()->RecordThisUse();
+ } else {
+ closure_scope->set_has_this_reference();
+ var->ForceContextAllocation();
+ }
+ return var;
+ }
+
V8_INLINE IdentifierT ParseAndClassifyIdentifier(Token::Value token);
// Parses an identifier or a strict mode future reserved word. Allows passing
// in function_kind for the case of parsing the identifier in a function
@@ -968,6 +995,8 @@ class ParserBase {
// mode.
IdentifierT ParseNonRestrictedIdentifier();
+ // This method should be used to ambiguously parse property names that can
+ // become destructuring identifiers.
V8_INLINE IdentifierT ParsePropertyName();
ExpressionT ParsePropertyOrPrivatePropertyName();
@@ -1027,10 +1056,11 @@ class ParserBase {
ExpressionT ParseAwaitExpression();
V8_INLINE ExpressionT ParseUnaryExpression();
V8_INLINE ExpressionT ParsePostfixExpression();
+ V8_NOINLINE ExpressionT ParsePostfixContinuation(ExpressionT expression,
+ int lhs_beg_pos);
V8_INLINE ExpressionT ParseLeftHandSideExpression();
ExpressionT ParseLeftHandSideContinuation(ExpressionT expression);
ExpressionT ParseMemberWithPresentNewPrefixesExpression();
- V8_INLINE ExpressionT ParseMemberWithNewPrefixesExpression();
ExpressionT ParseFunctionExpression();
V8_INLINE ExpressionT ParseMemberExpression();
V8_INLINE ExpressionT
@@ -1082,6 +1112,31 @@ class ParserBase {
FunctionLiteral::FunctionType function_type,
FunctionBodyType body_type);
+ // Check if the scope has conflicting var/let declarations from different
+ // scopes. This covers for example
+ //
+ // function f() { { { var x; } let x; } }
+ // function g() { { var x; let x; } }
+ //
+ // The var declarations are hoisted to the function scope, but originate from
+ // a scope where the name has also been let bound or the var declaration is
+ // hoisted over such a scope.
+ void CheckConflictingVarDeclarations(DeclarationScope* scope) {
+ if (has_error()) return;
+ Declaration* decl = scope->CheckConflictingVarDeclarations();
+ if (decl != nullptr) {
+ // In ES6, conflicting variable bindings are early errors.
+ const AstRawString* name = decl->var()->raw_name();
+ int position = decl->position();
+ Scanner::Location location =
+ position == kNoSourcePosition
+ ? Scanner::Location::invalid()
+ : Scanner::Location(position, position + 1);
+ impl()->ReportMessageAt(location, MessageTemplate::kVarRedeclaration,
+ name);
+ }
+ }
+
// TODO(nikolaos, marja): The first argument should not really be passed
// by value. The method is expected to add the parsed statements to the
// list. This works because in the case of the parser, StatementListT is
@@ -1159,39 +1214,6 @@ class ParserBase {
return identifier == ast_value_factory()->let_string();
}
- void DesugarBindingInForEachStatement(ForInfo* for_info, BlockT* body_block,
- ExpressionT* each_variable) {
- // Annex B.3.5 prohibits the form
- // `try {} catch(e) { for (var e of {}); }`
- // So if we are parsing a statement like `for (var ... of ...)`
- // we need to walk up the scope chain and look for catch scopes
- // which have a simple binding, then compare their binding against
- // all of the names declared in the init of the for-of we're
- // parsing.
- bool is_for_var_of =
- for_info->mode == ForEachStatement::ITERATE &&
- for_info->parsing_result.descriptor.mode == VariableMode::kVar;
-
- if (is_for_var_of) {
- Scope* scope = this->scope();
- while (scope != nullptr && !scope->is_declaration_scope()) {
- if (scope->is_catch_scope()) {
- auto name = scope->catch_variable()->raw_name();
- // If it's a simple binding and the name is declared in the for loop.
- if (name != ast_value_factory()->dot_catch_string() &&
- for_info->bound_names.Contains(name)) {
- impl()->ReportMessageAt(for_info->parsing_result.bindings_loc,
- MessageTemplate::kVarRedeclaration, name);
- }
- }
- scope = scope->outer_scope();
- }
- }
-
- impl()->DesugarBindingInForEachStatement(for_info, body_block,
- each_variable);
- }
-
bool IsNextLetKeyword();
// Checks if the expression is a valid reference expression (e.g., on the
@@ -1461,9 +1483,8 @@ template <typename Impl>
typename ParserBase<Impl>::IdentifierT
ParserBase<Impl>::ParseAndClassifyIdentifier(Token::Value next) {
DCHECK_EQ(scanner()->current_token(), next);
- STATIC_ASSERT(Token::IDENTIFIER + 1 == Token::ASYNC);
if (V8_LIKELY(IsInRange(next, Token::IDENTIFIER, Token::ASYNC))) {
- IdentifierT name = impl()->GetSymbol();
+ IdentifierT name = impl()->GetIdentifier();
if (V8_UNLIKELY(impl()->IsArguments(name) &&
scope()->ShouldBanArguments())) {
ReportMessage(MessageTemplate::kArgumentsDisallowedInInitializer);
@@ -1481,13 +1502,13 @@ ParserBase<Impl>::ParseAndClassifyIdentifier(Token::Value next) {
if (next == Token::AWAIT) {
expression_scope()->RecordAsyncArrowParametersError(
scanner()->location(), MessageTemplate::kAwaitBindingIdentifier);
- return impl()->GetSymbol();
+ return impl()->GetIdentifier();
}
DCHECK(Token::IsStrictReservedWord(next));
expression_scope()->RecordStrictModeParameterError(
scanner()->location(), MessageTemplate::kUnexpectedStrictReserved);
- return impl()->GetSymbol();
+ return impl()->GetIdentifier();
}
template <class Impl>
@@ -1502,7 +1523,7 @@ typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParseIdentifier(
return impl()->EmptyIdentifierString();
}
- return impl()->GetSymbol();
+ return impl()->GetIdentifier();
}
template <typename Impl>
@@ -1522,7 +1543,10 @@ ParserBase<Impl>::ParseNonRestrictedIdentifier() {
template <typename Impl>
typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParsePropertyName() {
Token::Value next = Next();
- if (V8_LIKELY(Token::IsPropertyName(next))) return impl()->GetSymbol();
+ if (V8_LIKELY(Token::IsPropertyName(next))) {
+ if (peek() == Token::COLON) return impl()->GetSymbol();
+ return impl()->GetIdentifier();
+ }
ReportUnexpectedToken(next);
return impl()->EmptyIdentifierString();
@@ -1539,7 +1563,23 @@ ParserBase<Impl>::ParsePropertyOrPrivatePropertyName() {
name = impl()->GetSymbol();
key = factory()->NewStringLiteral(name, pos);
} else if (allow_harmony_private_fields() && next == Token::PRIVATE_NAME) {
- name = impl()->GetSymbol();
+ // In the case of a top level function, we completely skip
+ // analysing it's scope, meaning, we don't have a chance to
+ // resolve private names and find that they are not enclosed in a
+ // class body.
+ //
+ // Here, we check if this is a new private name reference in a top
+ // level function and throw an error if so.
+ //
+ // Bug(v8:7468): This hack will go away once we refactor private
+ // name resolution to happen independently from scope resolution.
+ if (scope()->scope_type() == FUNCTION_SCOPE &&
+ scope()->outer_scope() != nullptr &&
+ scope()->outer_scope()->scope_type() == SCRIPT_SCOPE) {
+ ReportMessage(MessageTemplate::kInvalidPrivateFieldResolution);
+ }
+
+ name = impl()->GetIdentifier();
key = impl()->ExpressionFromIdentifier(name, pos, InferName::kNo);
} else {
ReportUnexpectedToken(next);
@@ -1637,7 +1677,8 @@ ParserBase<Impl>::ParsePrimaryExpression() {
FunctionKind kind = FunctionKind::kArrowFunction;
if (V8_UNLIKELY(token == Token::ASYNC &&
- !scanner()->HasLineTerminatorBeforeNext())) {
+ !scanner()->HasLineTerminatorBeforeNext() &&
+ !scanner()->literal_contains_escapes())) {
// async function ...
if (peek() == Token::FUNCTION) return ParseAsyncFunctionLiteral();
@@ -1668,15 +1709,29 @@ ParserBase<Impl>::ParsePrimaryExpression() {
}
switch (token) {
+ case Token::NEW:
+ return ParseMemberWithPresentNewPrefixesExpression();
+
case Token::THIS: {
Consume(Token::THIS);
- return impl()->ThisExpression(beg_pos);
+ return impl()->ThisExpression();
}
case Token::ASSIGN_DIV:
case Token::DIV:
return ParseRegExpLiteral();
+ case Token::FUNCTION:
+ return ParseFunctionExpression();
+
+ case Token::SUPER: {
+ const bool is_new = false;
+ return ParseSuperExpression(is_new);
+ }
+ case Token::IMPORT:
+ if (!allow_harmony_dynamic_import()) break;
+ return ParseImportExpressions();
+
case Token::LBRACK:
return ParseArrayLiteral();
@@ -1914,10 +1969,13 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseProperty(
Token::Value token = peek();
if ((token != Token::MUL && prop_info->ParsePropertyKindFromToken(token)) ||
scanner()->HasLineTerminatorBeforeNext()) {
- prop_info->name = impl()->GetSymbol();
+ prop_info->name = impl()->GetIdentifier();
impl()->PushLiteralName(prop_info->name);
return factory()->NewStringLiteral(prop_info->name, position());
}
+ if (V8_UNLIKELY(scanner()->literal_contains_escapes())) {
+ impl()->ReportUnexpectedToken(Token::ESCAPED_KEYWORD);
+ }
prop_info->function_flags = ParseFunctionFlag::kIsAsync;
prop_info->kind = ParsePropertyKind::kMethod;
}
@@ -1928,21 +1986,21 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseProperty(
}
if (prop_info->kind == ParsePropertyKind::kNotSet &&
- Check(Token::IDENTIFIER)) {
- IdentifierT symbol = impl()->GetSymbol();
- if (!prop_info->ParsePropertyKindFromToken(peek())) {
- if (impl()->IdentifierEquals(symbol, ast_value_factory()->get_string())) {
- prop_info->kind = ParsePropertyKind::kAccessorGetter;
- } else if (impl()->IdentifierEquals(symbol,
- ast_value_factory()->set_string())) {
- prop_info->kind = ParsePropertyKind::kAccessorSetter;
- }
- }
- if (!IsAccessor(prop_info->kind)) {
- prop_info->name = symbol;
+ IsInRange(peek(), Token::GET, Token::SET)) {
+ Token::Value token = Next();
+ if (prop_info->ParsePropertyKindFromToken(peek())) {
+ prop_info->name = impl()->GetIdentifier();
impl()->PushLiteralName(prop_info->name);
return factory()->NewStringLiteral(prop_info->name, position());
}
+ if (V8_UNLIKELY(scanner()->literal_contains_escapes())) {
+ impl()->ReportUnexpectedToken(Token::ESCAPED_KEYWORD);
+ }
+ if (token == Token::GET) {
+ prop_info->kind = ParsePropertyKind::kAccessorGetter;
+ } else if (token == Token::SET) {
+ prop_info->kind = ParsePropertyKind::kAccessorSetter;
+ }
}
int pos = peek_position();
@@ -1966,19 +2024,26 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseProperty(
if (prop_info->kind == ParsePropertyKind::kNotSet) {
prop_info->ParsePropertyKindFromToken(peek());
}
- prop_info->name = impl()->GetSymbol();
- if (prop_info->position == PropertyPosition::kObjectLiteral ||
- (!allow_harmony_private_methods() &&
- (IsAccessor(prop_info->kind) ||
- prop_info->kind == ParsePropertyKind::kMethod))) {
+ prop_info->name = impl()->GetIdentifier();
+ if (V8_UNLIKELY(prop_info->position ==
+ PropertyPosition::kObjectLiteral)) {
+ ReportUnexpectedToken(Token::PRIVATE_NAME);
+ prop_info->kind = ParsePropertyKind::kNotSet;
+ return impl()->FailureExpression();
+ }
+ if (V8_UNLIKELY(!allow_harmony_private_methods() &&
+ (IsAccessor(prop_info->kind) ||
+ prop_info->kind == ParsePropertyKind::kMethod))) {
ReportUnexpectedToken(Next());
+ prop_info->kind = ParsePropertyKind::kNotSet;
return impl()->FailureExpression();
}
break;
case Token::STRING:
Consume(Token::STRING);
- prop_info->name = impl()->GetSymbol();
+ prop_info->name = peek() == Token::COLON ? impl()->GetSymbol()
+ : impl()->GetIdentifier();
is_array_index = impl()->IsArrayIndex(prop_info->name, &index);
break;
@@ -2071,13 +2136,13 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassInfo* class_info,
if (peek() == Token::LPAREN) {
prop_info->kind = ParsePropertyKind::kMethod;
// TODO(bakkot) specialize on 'static'
- prop_info->name = impl()->GetSymbol();
+ prop_info->name = impl()->GetIdentifier();
name_expression =
factory()->NewStringLiteral(prop_info->name, position());
} else if (peek() == Token::ASSIGN || peek() == Token::SEMICOLON ||
peek() == Token::RBRACE) {
// TODO(bakkot) specialize on 'static'
- prop_info->name = impl()->GetSymbol();
+ prop_info->name = impl()->GetIdentifier();
name_expression =
factory()->NewStringLiteral(prop_info->name, position());
} else {
@@ -2264,6 +2329,9 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ParsePropertyInfo* prop_info,
Scanner::Location next_loc = scanner()->peek_location();
ExpressionT name_expression = ParseProperty(prop_info);
+
+ DCHECK_IMPLIES(name_token == Token::PRIVATE_NAME, has_error());
+
IdentifierT name = prop_info->name;
ParseFunctionFlags function_flags = prop_info->function_flags;
ParsePropertyKind kind = prop_info->kind;
@@ -2285,7 +2353,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ParsePropertyInfo* prop_info,
DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
if (!prop_info->is_computed_name &&
- impl()->IdentifierEquals(name, ast_value_factory()->proto_string())) {
+ scanner()->CurrentLiteralEquals("__proto__")) {
if (*has_seen_proto) {
expression_scope()->RecordExpressionError(
scanner()->location(), MessageTemplate::kDuplicateProto);
@@ -2322,10 +2390,6 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ParsePropertyInfo* prop_info,
DCHECK(!prop_info->is_computed_name);
- if (name_token == Token::LET) {
- expression_scope()->RecordLexicalDeclarationError(
- scanner()->location(), MessageTemplate::kLetInLexicalBinding);
- }
if (name_token == Token::AWAIT) {
DCHECK(!is_async_function());
expression_scope()->RecordAsyncArrowParametersError(
@@ -2666,6 +2730,9 @@ ParserBase<Impl>::ParseYieldExpression() {
expression_scope()->RecordParameterInitializerError(
scanner()->peek_location(), MessageTemplate::kYieldInParameter);
Consume(Token::YIELD);
+ if (V8_UNLIKELY(scanner()->literal_contains_escapes())) {
+ impl()->ReportUnexpectedToken(Token::ESCAPED_KEYWORD);
+ }
CheckStackOverflow();
@@ -2890,6 +2957,9 @@ ParserBase<Impl>::ParseAwaitExpression() {
MessageTemplate::kAwaitExpressionFormalParameter);
int await_pos = peek_position();
Consume(Token::AWAIT);
+ if (V8_UNLIKELY(scanner()->literal_contains_escapes())) {
+ impl()->ReportUnexpectedToken(Token::ESCAPED_KEYWORD);
+ }
CheckStackOverflow();
@@ -2933,24 +3003,29 @@ ParserBase<Impl>::ParsePostfixExpression() {
int lhs_beg_pos = peek_position();
ExpressionT expression = ParseLeftHandSideExpression();
- if (!scanner()->HasLineTerminatorBeforeNext() && Token::IsCountOp(peek())) {
- if (V8_UNLIKELY(!IsValidReferenceExpression(expression))) {
- expression = RewriteInvalidReferenceExpression(
- expression, lhs_beg_pos, end_position(),
- MessageTemplate::kInvalidLhsInPostfixOp);
- }
- if (impl()->IsIdentifier(expression)) {
- expression_scope()->MarkIdentifierAsAssigned();
- }
+ if (V8_LIKELY(!Token::IsCountOp(peek()) ||
+ scanner()->HasLineTerminatorBeforeNext())) {
+ return expression;
+ }
+ return ParsePostfixContinuation(expression, lhs_beg_pos);
+}
- Token::Value next = Next();
- expression =
- factory()->NewCountOperation(next,
- false /* postfix */,
- expression,
- position());
+template <typename Impl>
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParsePostfixContinuation(ExpressionT expression,
+ int lhs_beg_pos) {
+ if (V8_UNLIKELY(!IsValidReferenceExpression(expression))) {
+ expression = RewriteInvalidReferenceExpression(
+ expression, lhs_beg_pos, end_position(),
+ MessageTemplate::kInvalidLhsInPostfixOp);
}
- return expression;
+ if (impl()->IsIdentifier(expression)) {
+ expression_scope()->MarkIdentifierAsAssigned();
+ }
+
+ Token::Value next = Next();
+ return factory()->NewCountOperation(next, false /* postfix */, expression,
+ position());
}
template <typename Impl>
@@ -2959,7 +3034,7 @@ ParserBase<Impl>::ParseLeftHandSideExpression() {
// LeftHandSideExpression ::
// (NewExpression | MemberExpression) ...
- ExpressionT result = ParseMemberWithNewPrefixesExpression();
+ ExpressionT result = ParseMemberExpression();
if (!Token::IsPropertyOrCall(peek())) return result;
return ParseLeftHandSideContinuation(result);
}
@@ -2971,7 +3046,8 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {
if (V8_UNLIKELY(peek() == Token::LPAREN && impl()->IsIdentifier(result) &&
scanner()->current_token() == Token::ASYNC &&
- !scanner()->HasLineTerminatorBeforeNext())) {
+ !scanner()->HasLineTerminatorBeforeNext() &&
+ !scanner()->literal_contains_escapes())) {
DCHECK(impl()->IsAsync(impl()->AsIdentifier(result)));
int pos = position();
@@ -3128,7 +3204,7 @@ ParserBase<Impl>::ParseMemberWithPresentNewPrefixesExpression() {
result = ParseNewTargetExpression();
return ParseMemberExpressionContinuation(result);
} else {
- result = ParseMemberWithNewPrefixesExpression();
+ result = ParseMemberExpression();
}
if (peek() == Token::LPAREN) {
// NewExpression with arguments.
@@ -3153,13 +3229,6 @@ ParserBase<Impl>::ParseMemberWithPresentNewPrefixesExpression() {
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
-ParserBase<Impl>::ParseMemberWithNewPrefixesExpression() {
- return peek() == Token::NEW ? ParseMemberWithPresentNewPrefixesExpression()
- : ParseMemberExpression();
-}
-
-template <typename Impl>
-typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseFunctionExpression() {
Consume(Token::FUNCTION);
int function_token_position = position();
@@ -3207,22 +3276,11 @@ ParserBase<Impl>::ParseMemberExpression() {
// ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)*
//
// The '[' Expression ']' and '.' Identifier parts are parsed by
- // ParseMemberExpressionContinuation, and the Arguments part is parsed by the
- // caller.
+ // ParseMemberExpressionContinuation, and everything preceeding it is merged
+ // into ParsePrimaryExpression.
// Parse the initial primary or function expression.
- ExpressionT result;
- if (peek() == Token::FUNCTION) {
- result = ParseFunctionExpression();
- } else if (peek() == Token::SUPER) {
- const bool is_new = false;
- result = ParseSuperExpression(is_new);
- } else if (allow_harmony_dynamic_import() && peek() == Token::IMPORT) {
- result = ParseImportExpressions();
- } else {
- result = ParsePrimaryExpression();
- }
-
+ ExpressionT result = ParsePrimaryExpression();
return ParseMemberExpressionContinuation(result);
}
@@ -3233,8 +3291,9 @@ ParserBase<Impl>::ParseImportExpressions() {
Consume(Token::IMPORT);
int pos = position();
- if (allow_harmony_import_meta() && peek() == Token::PERIOD) {
- ExpectMetaProperty(ast_value_factory()->meta_string(), "import.meta", pos);
+ if (allow_harmony_import_meta() && Check(Token::PERIOD)) {
+ ExpectContextualKeyword(ast_value_factory()->meta_string(), "import.meta",
+ pos);
if (!parsing_module_) {
impl()->ReportMessageAt(scanner()->location(),
MessageTemplate::kImportMetaOutsideModule);
@@ -3267,7 +3326,15 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseSuperExpression(
if (IsConciseMethod(kind) || IsAccessorFunction(kind) ||
IsClassConstructor(kind)) {
if (Token::IsProperty(peek())) {
+ if (peek() == Token::PERIOD && PeekAhead() == Token::PRIVATE_NAME) {
+ Consume(Token::PERIOD);
+ Consume(Token::PRIVATE_NAME);
+
+ impl()->ReportMessage(MessageTemplate::kUnexpectedPrivateField);
+ return impl()->FailureExpression();
+ }
scope->RecordSuperPropertyUsage();
+ UseThis();
return impl()->NewSuperPropertyReference(pos);
}
// new super() is never allowed.
@@ -3275,6 +3342,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseSuperExpression(
if (!is_new && peek() == Token::LPAREN && IsDerivedConstructor(kind)) {
// TODO(rossberg): This might not be the correct FunctionState for the
// method here.
+ expression_scope()->RecordThisUse();
+ UseThis()->set_maybe_assigned();
return impl()->NewSuperCallReference(pos);
}
}
@@ -3285,22 +3354,12 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseSuperExpression(
}
template <typename Impl>
-void ParserBase<Impl>::ExpectMetaProperty(const AstRawString* property_name,
- const char* full_name, int pos) {
- Consume(Token::PERIOD);
- ExpectContextualKeyword(property_name);
- if (V8_UNLIKELY(scanner()->literal_contains_escapes())) {
- impl()->ReportMessageAt(Scanner::Location(pos, end_position()),
- MessageTemplate::kInvalidEscapedMetaProperty,
- full_name);
- }
-}
-
-template <typename Impl>
typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseNewTargetExpression() {
int pos = position();
- ExpectMetaProperty(ast_value_factory()->target_string(), "new.target", pos);
+ Consume(Token::PERIOD);
+ ExpectContextualKeyword(ast_value_factory()->target_string(), "new.target",
+ pos);
if (!GetReceiverScope()->is_function_scope()) {
impl()->ReportMessageAt(scanner()->location(),
@@ -3363,6 +3422,7 @@ void ParserBase<Impl>::ParseFormalParameter(FormalParametersT* parameters) {
// BindingElement[?Yield, ?GeneratorParameter]
FuncNameInferrerState fni_state(&fni_);
int pos = peek_position();
+ auto declaration_it = scope()->declarations()->end();
ExpressionT pattern = ParseBindingPattern();
if (impl()->IsIdentifier(pattern)) {
ClassifyParameter(impl()->AsIdentifier(pattern), pos, end_position());
@@ -3379,11 +3439,17 @@ void ParserBase<Impl>::ParseFormalParameter(FormalParametersT* parameters) {
return;
}
- AcceptINScope scope(this, true);
+ AcceptINScope accept_in_scope(this, true);
initializer = ParseAssignmentExpression();
impl()->SetFunctionNameFromIdentifierRef(initializer, pattern);
}
+ auto declaration_end = scope()->declarations()->end();
+ int initializer_end = end_position();
+ for (; declaration_it != declaration_end; ++declaration_it) {
+ declaration_it->var()->set_initializer_position(initializer_end);
+ }
+
impl()->AddFormalParameter(parameters, pattern, initializer, end_position(),
parameters->has_rest);
}
@@ -3473,6 +3539,11 @@ void ParserBase<Impl>::ParseVariableDeclarations(
VariableDeclarationParsingScope declaration(
impl(), parsing_result->descriptor.mode, names);
+ Scope* target_scope = IsLexicalVariableMode(parsing_result->descriptor.mode)
+ ? scope()
+ : scope()->GetDeclarationScope();
+
+ auto declaration_it = target_scope->declarations()->end();
int bindings_start = peek_position();
do {
@@ -3480,17 +3551,44 @@ void ParserBase<Impl>::ParseVariableDeclarations(
FuncNameInferrerState fni_state(&fni_);
int decl_pos = peek_position();
- ExpressionT pattern = ParseBindingPattern();
+
+ IdentifierT name;
+ ExpressionT pattern;
+ // Check for an identifier first, so that we can elide the pattern in cases
+ // where there is no initializer (and so no proxy needs to be created).
+ if (V8_LIKELY(Token::IsAnyIdentifier(peek()))) {
+ name = ParseAndClassifyIdentifier(Next());
+ if (V8_UNLIKELY(is_strict(language_mode()) &&
+ impl()->IsEvalOrArguments(name))) {
+ impl()->ReportMessageAt(scanner()->location(),
+ MessageTemplate::kStrictEvalArguments);
+ return;
+ }
+ if (peek() == Token::ASSIGN ||
+ (var_context == kForStatement && PeekInOrOf()) ||
+ parsing_result->descriptor.mode == VariableMode::kLet) {
+ // Assignments need the variable expression for the assignment LHS, and
+ // for of/in will need it later, so create the expression now.
+ pattern = impl()->ExpressionFromIdentifier(name, decl_pos);
+ } else {
+ // Otherwise, elide the variable expression and just declare it.
+ impl()->DeclareIdentifier(name, decl_pos);
+ pattern = impl()->NullExpression();
+ }
+ } else {
+ name = impl()->NullIdentifier();
+ pattern = ParseBindingPattern();
+ DCHECK(!impl()->IsIdentifier(pattern));
+ }
Scanner::Location variable_loc = scanner()->location();
ExpressionT value = impl()->NullExpression();
- int initializer_position = kNoSourcePosition;
- int value_beg_position = kNoSourcePosition;
+ int value_beg_pos = kNoSourcePosition;
if (Check(Token::ASSIGN)) {
- value_beg_position = peek_position();
-
+ DCHECK(!impl()->IsNull(pattern));
{
+ value_beg_pos = peek_position();
AcceptINScope scope(this, var_context != kForStatement);
value = ParseAssignmentExpression();
}
@@ -3510,18 +3608,36 @@ void ParserBase<Impl>::ParseVariableDeclarations(
}
impl()->SetFunctionNameFromIdentifierRef(value, pattern);
-
- // End position of the initializer is after the assignment expression.
- initializer_position = end_position();
} else {
+#ifdef DEBUG
+ // We can fall through into here on error paths, so don't DCHECK those.
+ if (!has_error()) {
+ // We should never get identifier patterns for the non-initializer path,
+ // as those expressions should be elided.
+ DCHECK_EQ(!impl()->IsNull(name),
+ Token::IsAnyIdentifier(scanner()->current_token()));
+ DCHECK_IMPLIES(impl()->IsNull(pattern), !impl()->IsNull(name));
+ // The only times we have a non-null pattern are:
+ // 1. This is a destructuring declaration (with no initializer, which
+ // is immediately an error),
+ // 2. This is a declaration in a for in/of loop, or
+ // 3. This is a let (which has an implicit undefined initializer)
+ DCHECK_IMPLIES(
+ !impl()->IsNull(pattern),
+ !impl()->IsIdentifier(pattern) ||
+ (var_context == kForStatement && PeekInOrOf()) ||
+ parsing_result->descriptor.mode == VariableMode::kLet);
+ }
+#endif
+
if (var_context != kForStatement || !PeekInOrOf()) {
// ES6 'const' and binding patterns require initializers.
if (parsing_result->descriptor.mode == VariableMode::kConst ||
- !impl()->IsIdentifier(pattern)) {
+ impl()->IsNull(name)) {
impl()->ReportMessageAt(
Scanner::Location(decl_pos, end_position()),
MessageTemplate::kDeclarationMissingInitializer,
- !impl()->IsIdentifier(pattern) ? "destructuring" : "const");
+ impl()->IsNull(name) ? "destructuring" : "const");
return;
}
// 'let x' initializes 'x' to undefined.
@@ -3529,14 +3645,22 @@ void ParserBase<Impl>::ParseVariableDeclarations(
value = factory()->NewUndefinedLiteral(position());
}
}
+ }
- // End position of the initializer is after the variable.
- initializer_position = position();
+ int initializer_position = end_position();
+ auto declaration_end = target_scope->declarations()->end();
+ for (; declaration_it != declaration_end; ++declaration_it) {
+ declaration_it->var()->set_initializer_position(initializer_position);
}
- typename DeclarationParsingResult::Declaration decl(
- pattern, initializer_position, value);
- decl.value_beg_position = value_beg_position;
+ // Patterns should be elided iff. they don't have an initializer.
+ DCHECK_IMPLIES(impl()->IsNull(pattern),
+ impl()->IsNull(value) ||
+ (var_context == kForStatement && PeekInOrOf()));
+
+ typename DeclarationParsingResult::Declaration decl(pattern, value);
+ decl.value_beg_pos = value_beg_pos;
+
parsing_result->declarations.push_back(decl);
} while (Check(Token::COMMA));
@@ -3617,10 +3741,10 @@ ParserBase<Impl>::ParseHoistableDeclaration(
FuncNameInferrerState fni_state(&fni_);
impl()->PushEnclosingName(name);
- FunctionKind kind = FunctionKindFor(flags);
+ FunctionKind function_kind = FunctionKindFor(flags);
FunctionLiteralT function = impl()->ParseFunctionLiteral(
- name, scanner()->location(), name_validity, kind, pos,
+ name, scanner()->location(), name_validity, function_kind, pos,
FunctionLiteral::kDeclaration, language_mode(), nullptr);
// In ES6, a function behaves as a lexical binding, except in
@@ -3631,16 +3755,17 @@ ParserBase<Impl>::ParseHoistableDeclaration(
: VariableMode::kVar;
// Async functions don't undergo sloppy mode block scoped hoisting, and don't
// allow duplicates in a block. Both are represented by the
- // sloppy_block_function_map. Don't add them to the map for async functions.
+ // sloppy_block_functions_. Don't add them to the map for async functions.
// Generators are also supposed to be prohibited; currently doing this behind
// a flag and UseCounting violations to assess web compatibility.
- bool is_sloppy_block_function = is_sloppy(language_mode()) &&
- !scope()->is_declaration_scope() &&
- flags == ParseFunctionFlag::kIsNormal;
-
- return impl()->DeclareFunction(variable_name, function, mode, pos,
- end_position(), is_sloppy_block_function,
- names);
+ VariableKind kind = is_sloppy(language_mode()) &&
+ !scope()->is_declaration_scope() &&
+ flags == ParseFunctionFlag::kIsNormal
+ ? SLOPPY_BLOCK_FUNCTION_VARIABLE
+ : NORMAL_VARIABLE;
+
+ return impl()->DeclareFunction(variable_name, function, mode, kind, pos,
+ end_position(), names);
}
template <typename Impl>
@@ -3716,6 +3841,9 @@ ParserBase<Impl>::ParseAsyncFunctionDeclaration(
// async [no LineTerminator here] function BindingIdentifier[Await]
// ( FormalParameters[Await] ) { AsyncFunctionBody }
DCHECK_EQ(scanner()->current_token(), Token::ASYNC);
+ if (V8_UNLIKELY(scanner()->literal_contains_escapes())) {
+ impl()->ReportUnexpectedToken(Token::ESCAPED_KEYWORD);
+ }
int pos = position();
DCHECK(!scanner()->HasLineTerminatorBeforeNext());
Consume(Token::FUNCTION);
@@ -3786,8 +3914,10 @@ void ParserBase<Impl>::ParseFunctionBody(
}
if (IsDerivedConstructor(kind)) {
+ ExpressionParsingScope expression_scope(impl());
inner_body.Add(factory()->NewReturnStatement(impl()->ThisExpression(),
kNoSourcePosition));
+ expression_scope.ValidateExpression();
}
Expect(closing_token);
}
@@ -3797,6 +3927,8 @@ void ParserBase<Impl>::ParseFunctionBody(
bool allow_duplicate_parameters = false;
+ CheckConflictingVarDeclarations(inner_scope);
+
if (V8_LIKELY(parameters.is_simple)) {
DCHECK_EQ(inner_scope, function_scope);
if (is_sloppy(function_scope->language_mode())) {
@@ -3820,12 +3952,13 @@ void ParserBase<Impl>::ParseFunctionBody(
inner_body.Rewind();
inner_body.Add(inner_block);
inner_block->set_scope(inner_scope);
- const AstRawString* conflict = inner_scope->FindVariableDeclaredIn(
- function_scope, VariableMode::kLastLexicalVariableMode);
- if (conflict != nullptr) {
- impl()->ReportVarRedeclarationIn(conflict, inner_scope);
+ if (!impl()->HasCheckedSyntax()) {
+ const AstRawString* conflict = inner_scope->FindVariableDeclaredIn(
+ function_scope, VariableMode::kLastLexicalVariableMode);
+ if (conflict != nullptr) {
+ impl()->ReportVarRedeclarationIn(conflict, inner_scope);
+ }
}
- impl()->CheckConflictingVarDeclarations(inner_scope);
impl()->InsertShadowingVarBindingInitializers(inner_block);
}
}
@@ -3851,6 +3984,7 @@ void ParserBase<Impl>::CheckArityRestrictions(int param_count,
bool has_rest,
int formals_start_pos,
int formals_end_pos) {
+ if (impl()->HasCheckedSyntax()) return;
if (IsGetterFunction(function_kind)) {
if (param_count != 0) {
impl()->ReportMessageAt(
@@ -3887,6 +4021,8 @@ bool ParserBase<Impl>::IsNextLetKeyword() {
// tokens.
case Token::YIELD:
case Token::AWAIT:
+ case Token::GET:
+ case Token::SET:
case Token::ASYNC:
return true;
case Token::FUTURE_STRICT_RESERVED_WORD:
@@ -3912,7 +4048,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start();
DCHECK_IMPLIES(!has_error(), peek() == Token::ARROW);
- if (scanner_->HasLineTerminatorBeforeNext()) {
+ if (!impl()->HasCheckedSyntax() && scanner_->HasLineTerminatorBeforeNext()) {
// ASI inserts `;` after arrow parameters if a line terminator is found.
// `=> ...` is never a valid expression, so report as syntax error.
// If next token is not `=>`, it's a syntax error anyways.
@@ -4068,7 +4204,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
bool is_anonymous = impl()->IsNull(name);
// All parts of a ClassDeclaration and ClassExpression are strict code.
- if (!is_anonymous) {
+ if (!impl()->HasCheckedSyntax() && !is_anonymous) {
if (name_is_strict_reserved) {
impl()->ReportMessageAt(class_name_location,
MessageTemplate::kUnexpectedStrictReserved);
@@ -4167,6 +4303,9 @@ ParserBase<Impl>::ParseAsyncFunctionLiteral() {
// async [no LineTerminator here] function BindingIdentifier[Await]
// ( FormalParameters[Await] ) { AsyncFunctionBody }
DCHECK_EQ(scanner()->current_token(), Token::ASYNC);
+ if (V8_UNLIKELY(scanner()->literal_contains_escapes())) {
+ impl()->ReportUnexpectedToken(Token::ESCAPED_KEYWORD);
+ }
int pos = position();
Consume(Token::FUNCTION);
IdentifierT name = impl()->NullIdentifier();
@@ -4418,9 +4557,9 @@ void ParserBase<Impl>::ParseStatementList(StatementListT* body,
Scanner::Location token_loc = scanner()->peek_location();
- if (scanner()->NextLiteralEquals("use strict")) {
+ if (scanner()->NextLiteralExactlyEquals("use strict")) {
use_strict = true;
- } else if (scanner()->NextLiteralEquals("use asm")) {
+ } else if (scanner()->NextLiteralExactlyEquals("use asm")) {
use_asm = true;
}
@@ -4604,7 +4743,8 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatement(
case Token::VAR:
return ParseVariableStatement(kStatement, nullptr);
case Token::ASYNC:
- if (!scanner()->HasLineTerminatorAfterNext() &&
+ if (!impl()->HasCheckedSyntax() &&
+ !scanner()->HasLineTerminatorAfterNext() &&
PeekAhead() == Token::FUNCTION) {
impl()->ReportMessageAt(
scanner()->peek_location(),
@@ -4922,7 +5062,9 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseReturnStatement() {
ExpressionT return_value = impl()->NullExpression();
if (scanner()->HasLineTerminatorBeforeNext() || Token::IsAutoSemicolon(tok)) {
if (IsDerivedConstructor(function_state_->kind())) {
- return_value = impl()->ThisExpression(loc.beg_pos);
+ ExpressionParsingScope expression_scope(impl());
+ return_value = impl()->ThisExpression();
+ expression_scope.ValidateExpression();
}
} else {
return_value = ParseExpression();
@@ -5181,9 +5323,20 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseTryStatement() {
} else {
catch_info.variable = catch_info.scope->DeclareCatchVariableName(
ast_value_factory()->dot_catch_string());
+
+ auto declaration_it = scope()->declarations()->end();
+
VariableDeclarationParsingScope destructuring(
impl(), VariableMode::kLet, nullptr);
catch_info.pattern = ParseBindingPattern();
+
+ int initializer_position = end_position();
+ auto declaration_end = scope()->declarations()->end();
+ for (; declaration_it != declaration_end; ++declaration_it) {
+ declaration_it->var()->set_initializer_position(
+ initializer_position);
+ }
+
RETURN_IF_PARSE_ERROR;
catch_statements.Add(impl()->RewriteCatchPattern(&catch_info));
}
@@ -5194,18 +5347,20 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseTryStatement() {
catch_statements.Add(inner_block);
// Check for `catch(e) { let e; }` and similar errors.
- Scope* inner_scope = inner_block->scope();
- if (inner_scope != nullptr) {
- const AstRawString* conflict = nullptr;
- if (impl()->IsNull(catch_info.pattern)) {
- const AstRawString* name = catch_info.variable->raw_name();
- if (inner_scope->LookupLocal(name)) conflict = name;
- } else {
- conflict = inner_scope->FindVariableDeclaredIn(
- scope(), VariableMode::kVar);
- }
- if (conflict != nullptr) {
- impl()->ReportVarRedeclarationIn(conflict, inner_scope);
+ if (!impl()->HasCheckedSyntax()) {
+ Scope* inner_scope = inner_block->scope();
+ if (inner_scope != nullptr) {
+ const AstRawString* conflict = nullptr;
+ if (impl()->IsNull(catch_info.pattern)) {
+ const AstRawString* name = catch_info.variable->raw_name();
+ if (inner_scope->LookupLocal(name)) conflict = name;
+ } else {
+ conflict = inner_scope->FindVariableDeclaredIn(
+ scope(), VariableMode::kVar);
+ }
+ if (conflict != nullptr) {
+ impl()->ReportVarRedeclarationIn(conflict, inner_scope);
+ }
}
}
@@ -5424,7 +5579,8 @@ ParserBase<Impl>::ParseForEachStatementWithDeclarations(
}
impl()->RecordIterationStatementSourceRange(loop, body_range);
- DesugarBindingInForEachStatement(for_info, &body_block, &each_variable);
+ impl()->DesugarBindingInForEachStatement(for_info, &body_block,
+ &each_variable);
body_block->statements()->Add(body, zone());
if (IsLexicalVariableMode(for_info->parsing_result.descriptor.mode)) {
@@ -5680,7 +5836,8 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
if (has_declarations) {
BlockT body_block = impl()->NullBlock();
- DesugarBindingInForEachStatement(&for_info, &body_block, &each_variable);
+ impl()->DesugarBindingInForEachStatement(&for_info, &body_block,
+ &each_variable);
body_block->statements()->Add(body, zone());
body_block->set_scope(scope()->FinalizeBlockScope());
body = body_block;