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

Unified Diff: src/parsing/parser.cc

Issue 2380663002: Revert of [parser] Refactor of ParseClass* and ParseNativeDeclaration (Closed)
Patch Set: 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.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parsing/parser.cc
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
index 2e2ac1c7ad3c19ed95e4440416a5bede71658fe4..cd87da8d14bfb46babba23408e08a987b795a9ca 100644
--- a/src/parsing/parser.cc
+++ b/src/parsing/parser.cc
@@ -1532,6 +1532,94 @@
return variable;
}
+// 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.
+Statement* Parser::ParseNativeDeclaration(bool* ok) {
+ int pos = peek_position();
+ Expect(Token::FUNCTION, CHECK_OK);
+ // Allow "eval" or "arguments" for backward compatibility.
+ const AstRawString* name =
+ ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
+ Expect(Token::LPAREN, CHECK_OK);
+ bool done = (peek() == Token::RPAREN);
+ while (!done) {
+ ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
+ done = (peek() == Token::RPAREN);
+ if (!done) {
+ Expect(Token::COMMA, CHECK_OK);
+ }
+ }
+ Expect(Token::RPAREN, CHECK_OK);
+ Expect(Token::SEMICOLON, CHECK_OK);
+
+ // Make sure that the function containing the native declaration
+ // isn't lazily compiled. The extension structures are only
+ // accessible while parsing the first time not when reparsing
+ // because of lazy compilation.
+ GetClosureScope()->ForceEagerCompilation();
+
+ // TODO(1240846): It's weird that native function declarations are
+ // introduced dynamically when we meet their declarations, whereas
+ // other functions are set up when entering the surrounding scope.
+ Declaration* decl = DeclareVariable(name, VAR, pos, CHECK_OK);
+ NativeFunctionLiteral* lit =
+ factory()->NewNativeFunctionLiteral(name, extension_, kNoSourcePosition);
+ return factory()->NewExpressionStatement(
+ factory()->NewAssignment(Token::INIT, decl->proxy(), lit,
+ kNoSourcePosition),
+ pos);
+}
+
+Statement* Parser::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 pos = position();
+
+ const AstRawString* name;
+ bool is_strict_reserved;
+ const AstRawString* variable_name;
+ if (default_export && (peek() == Token::EXTENDS || peek() == Token::LBRACE)) {
+ name = ast_value_factory()->default_string();
+ is_strict_reserved = false;
+ variable_name = ast_value_factory()->star_default_star_string();
+ } else {
+ name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
+ variable_name = name;
+ }
+
+ ExpressionClassifier no_classifier(this);
+ Expression* value = ParseClassLiteral(name, scanner()->location(),
+ is_strict_reserved, pos, CHECK_OK);
+
+ Declaration* decl = DeclareVariable(variable_name, LET, pos, CHECK_OK);
+ decl->proxy()->var()->set_initializer_position(position());
+ Assignment* assignment =
+ factory()->NewAssignment(Token::INIT, decl->proxy(), value, pos);
+ Statement* assignment_statement =
+ factory()->NewExpressionStatement(assignment, kNoSourcePosition);
+ if (names) names->Add(variable_name, zone());
+ return assignment_statement;
+}
+
Block* Parser::BuildInitializationBlock(
DeclarationParsingResult* parsing_result,
ZoneList<const AstRawString*>* names, bool* ok) {
@@ -1585,40 +1673,6 @@
return delegate;
}
return factory()->NewEmptyStatement(kNoSourcePosition);
-}
-
-Statement* Parser::DeclareClass(const AstRawString* variable_name,
- Expression* value,
- ZoneList<const AstRawString*>* names,
- int class_token_pos, int end_pos, bool* ok) {
- Declaration* decl =
- DeclareVariable(variable_name, LET, class_token_pos, CHECK_OK);
- decl->proxy()->var()->set_initializer_position(end_pos);
- Assignment* assignment = factory()->NewAssignment(Token::INIT, decl->proxy(),
- value, class_token_pos);
- Statement* assignment_statement =
- factory()->NewExpressionStatement(assignment, kNoSourcePosition);
- if (names) names->Add(variable_name, zone());
- return assignment_statement;
-}
-
-Statement* Parser::DeclareNative(const AstRawString* name, int pos, bool* ok) {
- // Make sure that the function containing the native declaration
- // isn't lazily compiled. The extension structures are only
- // accessible while parsing the first time not when reparsing
- // because of lazy compilation.
- GetClosureScope()->ForceEagerCompilation();
-
- // TODO(1240846): It's weird that native function declarations are
- // introduced dynamically when we meet their declarations, whereas
- // other functions are set up when entering the surrounding scope.
- Declaration* decl = DeclareVariable(name, VAR, pos, CHECK_OK);
- NativeFunctionLiteral* lit =
- factory()->NewNativeFunctionLiteral(name, extension_, kNoSourcePosition);
- return factory()->NewExpressionStatement(
- factory()->NewAssignment(Token::INIT, decl->proxy(), lit,
- kNoSourcePosition),
- pos);
}
ZoneList<const AstRawString*>* Parser::DeclareLabel(
@@ -3458,136 +3512,163 @@
return constructor;
}
-// If a class name is specified, this method declares the class variable
-// and sets class_info->proxy to point to that name.
-void Parser::DeclareClassVariable(const AstRawString* name, Scope* block_scope,
- ClassInfo* class_info, int class_token_pos,
- bool* ok) {
+Expression* Parser::ParseClassLiteral(const AstRawString* name,
+ Scanner::Location class_name_location,
+ bool name_is_strict_reserved, int pos,
+ bool* ok) {
+ // All parts of a ClassDeclaration and ClassExpression are strict code.
+ if (name_is_strict_reserved) {
+ ReportMessageAt(class_name_location,
+ MessageTemplate::kUnexpectedStrictReserved);
+ *ok = false;
+ return nullptr;
+ }
+ if (IsEvalOrArguments(name)) {
+ ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments);
+ *ok = false;
+ return nullptr;
+ }
+
+ BlockState block_state(zone(), &scope_state_);
+ RaiseLanguageMode(STRICT);
#ifdef DEBUG
scope()->SetScopeName(name);
#endif
+ VariableProxy* proxy = nullptr;
if (name != nullptr) {
- class_info->proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE);
- Declaration* declaration = factory()->NewVariableDeclaration(
- class_info->proxy, block_scope, class_token_pos);
+ proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE);
+ // TODO(verwaest): declare via block_state.
+ Declaration* declaration =
+ factory()->NewVariableDeclaration(proxy, block_state.scope(), pos);
Declare(declaration, DeclarationDescriptor::NORMAL, CONST,
- Variable::DefaultInitializationFlag(CONST), ok);
- }
-}
-
-// This method declares a property of the given class. It updates the
-// following fields of class_info, as appropriate:
-// - constructor
-// - static_initializer_var
-// - instance_field_initializers
-// - properties
-void Parser::DeclareClassProperty(const AstRawString* class_name,
- ClassLiteralProperty* property,
- ClassInfo* class_info, bool* ok) {
- if (class_info->has_seen_constructor && class_info->constructor == nullptr) {
- class_info->constructor = GetPropertyValue(property)->AsFunctionLiteral();
- DCHECK_NOT_NULL(class_info->constructor);
- class_info->constructor->set_raw_name(
- class_name != nullptr ? class_name
- : ast_value_factory()->empty_string());
- return;
- }
-
- if (property->kind() == ClassLiteralProperty::FIELD) {
- DCHECK(allow_harmony_class_fields());
- if (property->is_static()) {
- if (class_info->static_initializer_var == nullptr) {
- class_info->static_initializer_var =
- NewTemporary(ast_value_factory()->empty_string());
- }
- // TODO(bakkot) only do this conditionally
- Expression* function = InstallHomeObject(
- property->value(),
- factory()->NewVariableProxy(class_info->static_initializer_var));
- ZoneList<Expression*>* args =
- new (zone()) ZoneList<Expression*>(2, zone());
- args->Add(function, zone());
- args->Add(factory()->NewVariableProxy(class_info->static_initializer_var),
- zone());
- Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, args,
- kNoSourcePosition);
- property->set_value(call);
- } else {
- // if (is_computed_name) { // TODO(bakkot) figure out why this is
- // necessary for non-computed names in full-codegen
- ZoneList<Expression*>* to_name_args =
- new (zone()) ZoneList<Expression*>(1, zone());
- to_name_args->Add(property->key(), zone());
- property->set_key(factory()->NewCallRuntime(
- Runtime::kToName, to_name_args, kNoSourcePosition));
- //}
- const AstRawString* name = ClassFieldVariableName(
- true, ast_value_factory(),
- class_info->instance_field_initializers->length());
- VariableProxy* name_proxy =
- factory()->NewVariableProxy(name, NORMAL_VARIABLE);
- Declaration* name_declaration = factory()->NewVariableDeclaration(
- name_proxy, scope(), kNoSourcePosition);
- Variable* name_var =
- Declare(name_declaration, DeclarationDescriptor::NORMAL, CONST,
- kNeedsInitialization, ok, scope());
- DCHECK(*ok);
- if (!*ok) return;
- class_info->instance_field_initializers->Add(property->value(), zone());
- property->set_value(factory()->NewVariableProxy(name_var));
- }
- }
- class_info->properties->Add(property, zone());
-}
-
-// This method rewrites a class literal into a do-expression.
-// It uses the following fields of class_info:
-// - constructor (if missing, it updates it with a default constructor)
-// - proxy
-// - extends
-// - static_initializer_var
-// - instance_field_initializers
-// - properties
-Expression* Parser::RewriteClassLiteral(const AstRawString* name,
- ClassInfo* class_info, int pos,
- bool* ok) {
- int end_pos = scanner()->location().end_pos;
+ Variable::DefaultInitializationFlag(CONST), CHECK_OK);
+ }
+
+ Expression* extends = nullptr;
+ if (Check(Token::EXTENDS)) {
+ block_state.set_start_position(scanner()->location().end_pos);
+ ExpressionClassifier extends_classifier(this);
+ extends = ParseLeftHandSideExpression(CHECK_OK);
+ RewriteNonPattern(CHECK_OK);
+ impl()->AccumulateFormalParameterContainmentErrors();
+ } else {
+ block_state.set_start_position(scanner()->location().end_pos);
+ }
+
+
+ ClassLiteralChecker checker(this);
+ ZoneList<ClassLiteral::Property*>* properties = NewClassPropertyList(4);
+ ZoneList<Expression*>* instance_field_initializers =
+ new (zone()) ZoneList<Expression*>(0, zone());
+ FunctionLiteral* constructor = nullptr;
+ bool has_seen_constructor = false;
+ Variable* static_initializer_var = nullptr;
+
Block* do_block = factory()->NewBlock(nullptr, 1, false, pos);
Variable* result_var = NewTemporary(ast_value_factory()->empty_string());
DoExpression* do_expr = factory()->NewDoExpression(do_block, result_var, pos);
- bool has_extends = class_info->extends != nullptr;
- bool has_instance_fields =
- class_info->instance_field_initializers->length() > 0;
+ Expect(Token::LBRACE, CHECK_OK);
+
+ const bool has_extends = extends != nullptr;
+ 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);
+ ClassLiteral::Property* property =
+ ParseClassPropertyDefinition(&checker, has_extends, &is_computed_name,
+ &has_seen_constructor, CHECK_OK);
+ RewriteNonPattern(CHECK_OK);
+ impl()->AccumulateFormalParameterContainmentErrors();
+
+ if (has_seen_constructor && constructor == nullptr) {
+ constructor = GetPropertyValue(property)->AsFunctionLiteral();
+ DCHECK_NOT_NULL(constructor);
+ constructor->set_raw_name(
+ name != nullptr ? name : ast_value_factory()->empty_string());
+ } else {
+ if (property->kind() == ClassLiteralProperty::FIELD) {
+ DCHECK(allow_harmony_class_fields());
+ if (property->is_static()) {
+ if (static_initializer_var == nullptr) {
+ static_initializer_var =
+ NewTemporary(ast_value_factory()->empty_string());
+ }
+ // TODO(bakkot) only do this conditionally
+ Expression* function = InstallHomeObject(
+ property->value(),
+ factory()->NewVariableProxy(static_initializer_var));
+ ZoneList<Expression*>* args =
+ new (zone()) ZoneList<Expression*>(2, zone());
+ args->Add(function, zone());
+ args->Add(factory()->NewVariableProxy(static_initializer_var),
+ zone());
+ Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall,
+ args, kNoSourcePosition);
+ property->set_value(call);
+ } else {
+ // if (is_computed_name) { // TODO(bakkot) figure out why this is
+ // necessary for non-computed names in full-codegen
+ ZoneList<Expression*>* to_name_args =
+ new (zone()) ZoneList<Expression*>(1, zone());
+ to_name_args->Add(property->key(), zone());
+ property->set_key(factory()->NewCallRuntime(
+ Runtime::kToName, to_name_args, kNoSourcePosition));
+ //}
+ const AstRawString* name = ClassFieldVariableName(
+ true, ast_value_factory(), instance_field_initializers->length());
+ VariableProxy* name_proxy =
+ factory()->NewVariableProxy(name, NORMAL_VARIABLE);
+ Declaration* name_declaration = factory()->NewVariableDeclaration(
+ name_proxy, scope(), kNoSourcePosition);
+ Variable* name_var =
+ Declare(name_declaration, DeclarationDescriptor::NORMAL, CONST,
+ kNeedsInitialization, ok, scope());
+ DCHECK(ok);
+ if (!ok) return nullptr;
+ instance_field_initializers->Add(property->value(), zone());
+ property->set_value(factory()->NewVariableProxy(name_var));
+ }
+ }
+ properties->Add(property, zone());
+ }
+
+ DCHECK_NOT_NULL(fni_);
+ fni_->Infer();
+ }
+
+ Expect(Token::RBRACE, CHECK_OK);
+ int end_pos = scanner()->location().end_pos;
+
+ bool has_instance_fields = instance_field_initializers->length() > 0;
DCHECK(!has_instance_fields || allow_harmony_class_fields());
- bool has_default_constructor = class_info->constructor == nullptr;
+ bool has_default_constructor = constructor == nullptr;
if (has_default_constructor) {
- class_info->constructor =
- DefaultConstructor(name, has_extends, has_instance_fields, pos, end_pos,
- scope()->language_mode());
- }
-
- if (has_instance_fields && !has_extends) {
- class_info->constructor =
- InsertClassFieldInitializer(class_info->constructor);
- class_info->constructor->set_requires_class_field_init(true);
+ constructor = DefaultConstructor(name, has_extends, has_instance_fields,
+ pos, end_pos, block_state.language_mode());
+ }
+
+ if (has_instance_fields && extends == nullptr) {
+ constructor = InsertClassFieldInitializer(constructor);
+ constructor->set_requires_class_field_init(true);
} // The derived case is handled by rewriting super calls.
- scope()->set_end_position(end_pos);
+ block_state.set_end_position(end_pos);
if (name != nullptr) {
- DCHECK_NOT_NULL(class_info->proxy);
- class_info->proxy->var()->set_initializer_position(end_pos);
+ DCHECK_NOT_NULL(proxy);
+ proxy->var()->set_initializer_position(end_pos);
}
ClassLiteral* class_literal = factory()->NewClassLiteral(
- class_info->proxy, class_info->extends, class_info->constructor,
- class_info->properties, pos, end_pos);
-
- if (class_info->static_initializer_var != nullptr) {
+ proxy, extends, constructor, properties, pos, end_pos);
+
+ if (static_initializer_var != nullptr) {
class_literal->set_static_initializer_proxy(
- factory()->NewVariableProxy(class_info->static_initializer_var));
+ factory()->NewVariableProxy(static_initializer_var));
}
do_block->statements()->Add(
@@ -3598,7 +3679,8 @@
pos),
zone());
if (allow_harmony_class_fields() &&
- (has_instance_fields || (has_extends && !has_default_constructor))) {
+ (has_instance_fields ||
+ (extends != nullptr && !has_default_constructor))) {
// Default constructors for derived classes without fields will not try to
// read this variable, so there's no need to create it.
const AstRawString* init_fn_name =
@@ -3608,7 +3690,7 @@
Expression* initializer =
has_instance_fields
? static_cast<Expression*>(SynthesizeClassFieldInitializer(
- class_info->instance_field_initializers->length()))
+ instance_field_initializers->length()))
: factory()->NewBooleanLiteral(false, kNoSourcePosition);
Assignment* assignment = factory()->NewAssignment(
Token::INIT, factory()->NewVariableProxy(init_fn_var), initializer,
@@ -3617,7 +3699,7 @@
factory()->NewExpressionStatement(assignment, kNoSourcePosition),
zone());
}
- for (int i = 0; i < class_info->instance_field_initializers->length(); ++i) {
+ for (int i = 0; i < instance_field_initializers->length(); ++i) {
const AstRawString* function_name =
ClassFieldVariableName(false, ast_value_factory(), i);
VariableProxy* function_proxy =
@@ -3627,14 +3709,15 @@
Variable* function_var =
Declare(function_declaration, DeclarationDescriptor::NORMAL, CONST,
kNeedsInitialization, ok, scope());
- if (!*ok) return nullptr;
+ DCHECK(ok);
+ if (!ok) return nullptr;
Property* prototype_property = factory()->NewProperty(
factory()->NewVariableProxy(result_var),
factory()->NewStringLiteral(ast_value_factory()->prototype_string(),
kNoSourcePosition),
kNoSourcePosition);
Expression* function_value = InstallHomeObject(
- class_info->instance_field_initializers->at(i),
+ instance_field_initializers->at(i),
prototype_property); // TODO(bakkot) ideally this would be conditional,
// especially in trivial cases
Assignment* function_assignment = factory()->NewAssignment(
@@ -3644,11 +3727,12 @@
function_assignment, kNoSourcePosition),
zone());
}
- do_block->set_scope(scope()->FinalizeBlockScope());
- do_expr->set_represented_function(class_info->constructor);
+ do_block->set_scope(block_state.FinalizedBlockScope());
+ do_expr->set_represented_function(constructor);
return do_expr;
}
+
Literal* Parser::GetLiteralUndefined(int position) {
return factory()->NewUndefinedLiteral(position);
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698