Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(611)

Unified Diff: src/parsing/parser-base.h

Issue 2368083002: [parser] Refactor of ParseClass* and ParseNativeDeclaration (Closed)
Patch Set: Rebase again Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parsing/parser.cc ('k') | src/parsing/preparser.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parsing/parser-base.h
diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h
index 0781f0ec9c98b0345fadfeb617c005d43110e2a1..fac3ec694afaa90ad2dc3c213572b8f60d6baede 100644
--- a/src/parsing/parser-base.h
+++ b/src/parsing/parser-base.h
@@ -133,7 +133,8 @@ struct FormalParametersBase {
// typedef ObjectLiteralProperty;
// typedef ClassLiteralProperty;
// typedef ExpressionList;
-// typedef PropertyList;
+// typedef ObjectPropertyList;
+// typedef ClassPropertyList;
// typedef FormalParameters;
// typedef Statement;
// typedef StatementList;
@@ -161,7 +162,6 @@ class ParserBase {
typedef typename Types::ObjectLiteralProperty ObjectLiteralPropertyT;
typedef typename Types::ClassLiteralProperty ClassLiteralPropertyT;
typedef typename Types::ExpressionList ExpressionListT;
- typedef typename Types::PropertyList PropertyListT;
typedef typename Types::FormalParameters FormalParametersT;
typedef typename Types::Statement StatementT;
typedef typename Types::StatementList StatementListT;
@@ -671,6 +671,25 @@ class ParserBase {
DeclarationParsingResult parsing_result;
};
+ struct ClassInfo {
+ public:
+ explicit ClassInfo(ParserBase* parser)
+ : proxy(nullptr),
+ extends(parser->impl()->EmptyExpression()),
+ properties(parser->impl()->NewClassPropertyList(4)),
+ instance_field_initializers(parser->impl()->NewExpressionList(0)),
+ constructor(parser->impl()->EmptyFunctionLiteral()),
+ has_seen_constructor(false),
+ static_initializer_var(nullptr) {}
+ VariableProxy* proxy;
+ ExpressionT extends;
+ typename Types::ClassPropertyList properties;
+ ExpressionListT instance_field_initializers;
+ FunctionLiteralT constructor;
+ bool has_seen_constructor;
+ Variable* static_initializer_var;
+ };
+
DeclarationScope* NewScriptScope() const {
return new (zone()) DeclarationScope(zone(), ast_value_factory());
}
@@ -1174,6 +1193,10 @@ class ParserBase {
FunctionKind kind, FunctionBodyType type,
bool accept_IN, int pos, bool* ok);
ExpressionT ParseAsyncFunctionLiteral(bool* ok);
+ ExpressionT ParseClassLiteral(IdentifierT name,
+ Scanner::Location class_name_location,
+ bool name_is_strict_reserved,
+ int class_token_pos, bool* ok);
ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool* ok);
ExpressionT ParseSuperExpression(bool is_new, bool* ok);
ExpressionT ParseNewTargetExpression(bool* ok);
@@ -1195,6 +1218,9 @@ class ParserBase {
StatementT ParseHoistableDeclaration(int pos, ParseFunctionFlags flags,
ZoneList<const AstRawString*>* names,
bool default_export, bool* ok);
+ StatementT ParseClassDeclaration(ZoneList<const AstRawString*>* names,
+ bool default_export, bool* ok);
+ StatementT ParseNativeDeclaration(bool* ok);
// Under some circumstances, we allow preparsing to abort if the preparsed
// function is "long and trivial", and fully parse instead. Our current
@@ -1783,7 +1809,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
case Token::CLASS: {
BindingPatternUnexpectedToken();
Consume(Token::CLASS);
- int class_token_position = position();
+ int class_token_pos = position();
IdentifierT name = impl()->EmptyIdentifier();
bool is_strict_reserved_name = false;
Scanner::Location class_name_location = Scanner::Location::invalid();
@@ -1792,9 +1818,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
CHECK_OK);
class_name_location = scanner()->location();
}
- return impl()->ParseClassLiteral(name, class_name_location,
- is_strict_reserved_name,
- class_token_position, ok);
+ return ParseClassLiteral(name, class_name_location,
+ is_strict_reserved_name, class_token_pos, ok);
}
case Token::TEMPLATE_SPAN:
@@ -2456,7 +2481,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral(
// '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}'
int pos = peek_position();
- PropertyListT properties = impl()->NewPropertyList(4);
+ typename Types::ObjectPropertyList properties =
+ impl()->NewObjectPropertyList(4);
int number_of_boilerplate_properties = 0;
bool has_computed_names = false;
ObjectLiteralChecker checker(this);
@@ -3701,6 +3727,72 @@ ParserBase<Impl>::ParseHoistableDeclaration(
}
template <typename Impl>
+typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseClassDeclaration(
+ ZoneList<const AstRawString*>* names, bool default_export, bool* ok) {
+ // ClassDeclaration ::
+ // 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}'
+ // 'class' ('extends' LeftHandExpression)? '{' ClassBody '}'
+ //
+ // The anonymous form is allowed iff [default_export] is true.
+ //
+ // 'class' is expected to be consumed by the caller.
+ //
+ // A ClassDeclaration
+ //
+ // class C { ... }
+ //
+ // has the same semantics as:
+ //
+ // let C = class C { ... };
+ //
+ // so rewrite it as such.
+
+ int class_token_pos = position();
+ IdentifierT name = impl()->EmptyIdentifier();
+ bool is_strict_reserved = false;
+ IdentifierT variable_name = impl()->EmptyIdentifier();
+ if (default_export && (peek() == Token::EXTENDS || peek() == Token::LBRACE)) {
+ impl()->GetDefaultStrings(&name, &variable_name);
+ } else {
+ name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved,
+ CHECK_OK_CUSTOM(NullStatement));
+ variable_name = name;
+ }
+
+ ExpressionClassifier no_classifier(this);
+ ExpressionT value =
+ ParseClassLiteral(name, scanner()->location(), is_strict_reserved,
+ class_token_pos, CHECK_OK_CUSTOM(NullStatement));
+ int end_pos = position();
+ return impl()->DeclareClass(variable_name, value, names, class_token_pos,
+ end_pos, ok);
+}
+
+// Language extension which is only enabled for source files loaded
+// through the API's extension mechanism. A native function
+// declaration is resolved by looking up the function through a
+// callback provided by the extension.
+template <typename Impl>
+typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseNativeDeclaration(
+ bool* ok) {
+ int pos = peek_position();
+ Expect(Token::FUNCTION, CHECK_OK_CUSTOM(NullStatement));
+ // Allow "eval" or "arguments" for backward compatibility.
+ IdentifierT name = ParseIdentifier(kAllowRestrictedIdentifiers,
+ CHECK_OK_CUSTOM(NullStatement));
+ Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullStatement));
+ if (peek() != Token::RPAREN) {
+ do {
+ ParseIdentifier(kAllowRestrictedIdentifiers,
+ CHECK_OK_CUSTOM(NullStatement));
+ } while (Check(Token::COMMA));
+ }
+ Expect(Token::RPAREN, CHECK_OK_CUSTOM(NullStatement));
+ Expect(Token::SEMICOLON, CHECK_OK_CUSTOM(NullStatement));
+ return impl()->DeclareNative(name, pos, ok);
+}
+
+template <typename Impl>
typename ParserBase<Impl>::StatementT
ParserBase<Impl>::ParseAsyncFunctionDeclaration(
ZoneList<const AstRawString*>* names, bool default_export, bool* ok) {
@@ -3931,12 +4023,72 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
function_literal->set_should_be_used_once_hint();
}
- impl()->InferFunctionName(function_literal);
+ impl()->AddFunctionForNameInference(function_literal);
return function_literal;
}
template <typename Impl>
+typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
+ IdentifierT name, Scanner::Location class_name_location,
+ bool name_is_strict_reserved, int class_token_pos, bool* ok) {
+ // All parts of a ClassDeclaration and ClassExpression are strict code.
+ if (name_is_strict_reserved) {
+ impl()->ReportMessageAt(class_name_location,
+ MessageTemplate::kUnexpectedStrictReserved);
+ *ok = false;
+ return impl()->EmptyExpression();
+ }
+ if (impl()->IsEvalOrArguments(name)) {
+ impl()->ReportMessageAt(class_name_location,
+ MessageTemplate::kStrictEvalArguments);
+ *ok = false;
+ return impl()->EmptyExpression();
+ }
+
+ BlockState block_state(zone(), &scope_state_);
+ RaiseLanguageMode(STRICT);
+
+ ClassInfo class_info(this);
+ impl()->DeclareClassVariable(name, block_state.scope(), &class_info,
+ class_token_pos, CHECK_OK);
+
+ if (Check(Token::EXTENDS)) {
+ block_state.set_start_position(scanner()->location().end_pos);
+ ExpressionClassifier extends_classifier(this);
+ class_info.extends = ParseLeftHandSideExpression(CHECK_OK);
+ impl()->RewriteNonPattern(CHECK_OK);
+ impl()->AccumulateFormalParameterContainmentErrors();
+ } else {
+ block_state.set_start_position(scanner()->location().end_pos);
+ }
+
+ ClassLiteralChecker checker(this);
+
+ Expect(Token::LBRACE, CHECK_OK);
+
+ const bool has_extends = !impl()->IsEmptyExpression(class_info.extends);
+ while (peek() != Token::RBRACE) {
+ if (Check(Token::SEMICOLON)) continue;
+ FuncNameInferrer::State fni_state(fni_);
+ bool is_computed_name = false; // Classes do not care about computed
+ // property names here.
+ ExpressionClassifier property_classifier(this);
+ ClassLiteralPropertyT property = ParseClassPropertyDefinition(
+ &checker, has_extends, &is_computed_name,
+ &class_info.has_seen_constructor, CHECK_OK);
+ impl()->RewriteNonPattern(CHECK_OK);
+ impl()->AccumulateFormalParameterContainmentErrors();
+
+ impl()->DeclareClassProperty(name, property, &class_info, CHECK_OK);
+ impl()->InferFunctionName();
+ }
+
+ Expect(Token::RBRACE, CHECK_OK);
+ return impl()->RewriteClassLiteral(name, &class_info, class_token_pos, ok);
+}
+
+template <typename Impl>
void ParserBase<Impl>::ParseAsyncFunctionBody(Scope* scope, StatementListT body,
FunctionKind kind,
FunctionBodyType body_type,
@@ -4287,7 +4439,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatementListItem(
return ParseHoistableDeclaration(nullptr, false, ok);
case Token::CLASS:
Consume(Token::CLASS);
- return impl()->ParseClassDeclaration(nullptr, false, ok);
+ return ParseClassDeclaration(nullptr, false, ok);
case Token::VAR:
case Token::CONST:
return ParseVariableStatement(kStatementListItem, nullptr, ok);
@@ -4565,7 +4717,7 @@ ParserBase<Impl>::ParseExpressionOrLabelledStatement(
if (extension_ != nullptr && peek() == Token::FUNCTION &&
!scanner()->HasAnyLineTerminatorBeforeNext() && impl()->IsNative(expr) &&
!scanner()->literal_contains_escapes()) {
- return impl()->ParseNativeDeclaration(ok);
+ return ParseNativeDeclaration(ok);
}
// Parsed expression statement, followed by semicolon.
« no previous file with comments | « src/parsing/parser.cc ('k') | src/parsing/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698