summaryrefslogtreecommitdiff
path: root/chromium/v8/src/parsing/parser-base.h
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/v8/src/parsing/parser-base.h')
-rw-r--r--chromium/v8/src/parsing/parser-base.h135
1 files changed, 100 insertions, 35 deletions
diff --git a/chromium/v8/src/parsing/parser-base.h b/chromium/v8/src/parsing/parser-base.h
index 108b11edc83..8093472eebe 100644
--- a/chromium/v8/src/parsing/parser-base.h
+++ b/chromium/v8/src/parsing/parser-base.h
@@ -27,12 +27,15 @@
#include "src/parsing/parse-info.h"
#include "src/parsing/scanner.h"
#include "src/parsing/token.h"
+#include "src/regexp/regexp.h"
#include "src/utils/pointer-with-payload.h"
#include "src/zone/zone-chunk-list.h"
namespace v8 {
namespace internal {
+class PreParserIdentifier;
+
enum FunctionNameValidity {
kFunctionNameIsStrictReserved,
kSkipFunctionNameCheck,
@@ -1074,22 +1077,24 @@ class ParserBase {
}
// Report syntax errors.
- V8_NOINLINE void ReportMessage(MessageTemplate message) {
- Scanner::Location source_location = scanner()->location();
- impl()->ReportMessageAt(source_location, message,
- static_cast<const char*>(nullptr));
+ template <typename... Ts>
+ V8_NOINLINE void ReportMessage(MessageTemplate message, const Ts&... args) {
+ ReportMessageAt(scanner()->location(), message, args...);
}
- template <typename T>
- V8_NOINLINE void ReportMessage(MessageTemplate message, T arg) {
- Scanner::Location source_location = scanner()->location();
- impl()->ReportMessageAt(source_location, message, arg);
+ template <typename... Ts>
+ V8_NOINLINE void ReportMessageAt(Scanner::Location source_location,
+ MessageTemplate message, const Ts&... args) {
+ impl()->pending_error_handler()->ReportMessageAt(
+ source_location.beg_pos, source_location.end_pos, message, args...);
+ scanner()->set_parser_error();
}
- V8_NOINLINE void ReportMessageAt(Scanner::Location location,
- MessageTemplate message) {
- impl()->ReportMessageAt(location, message,
- static_cast<const char*>(nullptr));
+ V8_NOINLINE void ReportMessageAt(Scanner::Location source_location,
+ MessageTemplate message,
+ const PreParserIdentifier& arg0) {
+ ReportMessageAt(source_location, message,
+ impl()->PreParserIdentifierToAstRawString(arg0));
}
V8_NOINLINE void ReportUnexpectedToken(Token::Value token);
@@ -1122,6 +1127,12 @@ class ParserBase {
}
V8_INLINE IdentifierT ParseAndClassifyIdentifier(Token::Value token);
+
+ // Similar logic to ParseAndClassifyIdentifier but the identifier is
+ // already parsed in prop_info. Returns false if this is an invalid
+ // identifier or an invalid use of the "arguments" keyword.
+ V8_INLINE bool ClassifyPropertyIdentifier(Token::Value token,
+ ParsePropertyInfo* prop_info);
// 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
// expression, where the relevant "function_kind" bit is of the function being
@@ -1140,6 +1151,11 @@ class ParserBase {
ExpressionT ParsePropertyOrPrivatePropertyName();
+ const AstRawString* GetNextSymbolForRegExpLiteral() const {
+ return scanner()->NextSymbol(ast_value_factory());
+ }
+ bool ValidateRegExpLiteral(const AstRawString* pattern, RegExpFlags flags,
+ RegExpError* regexp_error);
ExpressionT ParseRegExpLiteral();
ExpressionT ParseBindingPattern();
@@ -1634,8 +1650,39 @@ void ParserBase<Impl>::ReportUnexpectedToken(Token::Value token) {
}
template <typename Impl>
+bool ParserBase<Impl>::ClassifyPropertyIdentifier(
+ Token::Value next, ParsePropertyInfo* prop_info) {
+ // Updates made here must be reflected on ParseAndClassifyIdentifier.
+ if (V8_LIKELY(base::IsInRange(next, Token::IDENTIFIER, Token::ASYNC))) {
+ if (V8_UNLIKELY(impl()->IsArguments(prop_info->name) &&
+ scope()->ShouldBanArguments())) {
+ ReportMessage(
+ MessageTemplate::kArgumentsDisallowedInInitializerAndStaticBlock);
+ return false;
+ }
+ return true;
+ }
+
+ if (!Token::IsValidIdentifier(next, language_mode(), is_generator(),
+ is_await_as_identifier_disallowed())) {
+ ReportUnexpectedToken(next);
+ return false;
+ }
+
+ DCHECK(!prop_info->is_computed_name);
+
+ if (next == Token::AWAIT) {
+ DCHECK(!is_async_function());
+ expression_scope()->RecordAsyncArrowParametersError(
+ scanner()->peek_location(), MessageTemplate::kAwaitBindingIdentifier);
+ }
+ return true;
+}
+
+template <typename Impl>
typename ParserBase<Impl>::IdentifierT
ParserBase<Impl>::ParseAndClassifyIdentifier(Token::Value next) {
+ // Updates made here must be reflected on ClassifyPropertyIdentifier.
DCHECK_EQ(scanner()->current_token(), next);
if (V8_LIKELY(base::IsInRange(next, Token::IDENTIFIER, Token::ASYNC))) {
IdentifierT name = impl()->GetIdentifier();
@@ -1746,6 +1793,26 @@ ParserBase<Impl>::ParsePropertyOrPrivatePropertyName() {
}
template <typename Impl>
+bool ParserBase<Impl>::ValidateRegExpLiteral(const AstRawString* pattern,
+ RegExpFlags flags,
+ RegExpError* regexp_error) {
+ // TODO(jgruber): If already validated in the preparser, skip validation in
+ // the parser.
+ DisallowGarbageCollection no_gc;
+ ZoneScope zone_scope(zone()); // Free regexp parser memory after use.
+ const unsigned char* d = pattern->raw_data();
+ if (pattern->is_one_byte()) {
+ return RegExp::VerifySyntax(zone(), stack_limit(),
+ static_cast<const uint8_t*>(d),
+ pattern->length(), flags, regexp_error, no_gc);
+ } else {
+ return RegExp::VerifySyntax(zone(), stack_limit(),
+ reinterpret_cast<const uint16_t*>(d),
+ pattern->length(), flags, regexp_error, no_gc);
+ }
+}
+
+template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseRegExpLiteral() {
int pos = peek_position();
if (!scanner()->ScanRegExpPattern()) {
@@ -1754,15 +1821,22 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseRegExpLiteral() {
return impl()->FailureExpression();
}
- IdentifierT js_pattern = impl()->GetNextSymbol();
- Maybe<int> flags = scanner()->ScanRegExpFlags();
- if (flags.IsNothing()) {
+ const AstRawString* js_pattern = GetNextSymbolForRegExpLiteral();
+ base::Optional<RegExpFlags> flags = scanner()->ScanRegExpFlags();
+ if (!flags.has_value()) {
Next();
ReportMessage(MessageTemplate::kMalformedRegExpFlags);
return impl()->FailureExpression();
}
Next();
- return factory()->NewRegExpLiteral(js_pattern, flags.FromJust(), pos);
+ RegExpError regexp_error;
+ if (!ValidateRegExpLiteral(js_pattern, flags.value(), &regexp_error)) {
+ if (RegExpErrorIsStackOverflow(regexp_error)) set_stack_overflow();
+ ReportMessage(MessageTemplate::kMalformedRegExp, js_pattern,
+ RegExpErrorString(regexp_error));
+ return impl()->FailureExpression();
+ }
+ return factory()->NewRegExpLiteral(js_pattern, flags.value(), pos);
}
template <typename Impl>
@@ -2514,7 +2588,6 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ParsePropertyInfo* prop_info,
IdentifierT name = prop_info->name;
ParseFunctionFlags function_flags = prop_info->function_flags;
- ParsePropertyKind kind = prop_info->kind;
switch (prop_info->kind) {
case ParsePropertyKind::kSpread:
@@ -2562,19 +2635,10 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ParsePropertyInfo* prop_info,
// IdentifierReference Initializer?
DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
- if (!Token::IsValidIdentifier(name_token, language_mode(), is_generator(),
- is_await_as_identifier_disallowed())) {
- ReportUnexpectedToken(Next());
+ if (!ClassifyPropertyIdentifier(name_token, prop_info)) {
return impl()->NullLiteralProperty();
}
- DCHECK(!prop_info->is_computed_name);
-
- if (name_token == Token::AWAIT) {
- DCHECK(!is_async_function());
- expression_scope()->RecordAsyncArrowParametersError(
- next_loc, MessageTemplate::kAwaitBindingIdentifier);
- }
ExpressionT lhs =
impl()->ExpressionFromIdentifier(name, next_loc.beg_pos);
if (!IsAssignableIdentifier(lhs)) {
@@ -2637,7 +2701,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ParsePropertyInfo* prop_info,
case ParsePropertyKind::kAccessorGetter:
case ParsePropertyKind::kAccessorSetter: {
DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
- bool is_get = kind == ParsePropertyKind::kAccessorGetter;
+ bool is_get = prop_info->kind == ParsePropertyKind::kAccessorGetter;
expression_scope()->RecordPatternError(
Scanner::Location(next_loc.beg_pos, end_position()),
@@ -3170,20 +3234,21 @@ template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
int prec) {
DCHECK_GE(prec, 4);
- ExpressionT x;
+
// "#foo in ShiftExpression" needs to be parsed separately, since private
// identifiers are not valid PrimaryExpressions.
if (V8_UNLIKELY(FLAG_harmony_private_brand_checks &&
peek() == Token::PRIVATE_NAME)) {
- x = ParsePropertyOrPrivatePropertyName();
- if (peek() != Token::IN) {
- ReportUnexpectedToken(peek());
+ ExpressionT x = ParsePropertyOrPrivatePropertyName();
+ int prec1 = Token::Precedence(peek(), accept_IN_);
+ if (peek() != Token::IN || prec1 < prec) {
+ ReportUnexpectedToken(Token::PRIVATE_NAME);
return impl()->FailureExpression();
}
- } else {
- x = ParseUnaryExpression();
+ return ParseBinaryContinuation(x, prec, prec1);
}
+ ExpressionT x = ParseUnaryExpression();
int prec1 = Token::Precedence(peek(), accept_IN_);
if (prec1 >= prec) {
return ParseBinaryContinuation(x, prec, prec1);
@@ -5258,7 +5323,7 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseBlock(
body->set_scope(scope()->FinalizeBlockScope());
}
- body->InitializeStatements(statements, zone_);
+ body->InitializeStatements(statements, zone());
return body;
}