Chromium Code Reviews| Index: src/parsing/parser.cc |
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc |
| index 44d1a8145880902ce0e8e176b8a887b47c3de532..a3dd5912522acc0015e0e4b8c88e50558f314903 100644 |
| --- a/src/parsing/parser.cc |
| +++ b/src/parsing/parser.cc |
| @@ -769,7 +769,7 @@ FunctionLiteral* ParserTraits::ParseFunctionLiteral( |
| function_token_position, type, language_mode, ok); |
| } |
| -ClassLiteral* ParserTraits::ParseClassLiteral( |
| +Expression* ParserTraits::ParseClassLiteral( |
| Type::ExpressionClassifier* classifier, const AstRawString* name, |
| Scanner::Location class_name_location, bool name_is_strict_reserved, |
| int pos, bool* ok) { |
| @@ -2236,8 +2236,8 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, |
| variable_name = name; |
| } |
| - ClassLiteral* value = ParseClassLiteral(nullptr, name, scanner()->location(), |
| - is_strict_reserved, pos, CHECK_OK); |
| + Expression* value = ParseClassLiteral(nullptr, name, scanner()->location(), |
| + is_strict_reserved, pos, CHECK_OK); |
| VariableProxy* proxy = NewUnresolved(variable_name, LET); |
| Declaration* declaration = |
| @@ -4974,11 +4974,11 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( |
| return result; |
| } |
| -ClassLiteral* Parser::ParseClassLiteral(ExpressionClassifier* classifier, |
| - const AstRawString* name, |
| - Scanner::Location class_name_location, |
| - bool name_is_strict_reserved, int pos, |
| - bool* ok) { |
| +Expression* Parser::ParseClassLiteral(ExpressionClassifier* classifier, |
| + 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, |
| @@ -5022,8 +5022,15 @@ ClassLiteral* Parser::ParseClassLiteral(ExpressionClassifier* classifier, |
| ClassLiteralChecker checker(this); |
| - ZoneList<ObjectLiteral::Property*>* properties = NewPropertyList(4, zone()); |
| FunctionLiteral* constructor = NULL; |
| + |
| + ZoneList<Expression*>* property_names = |
| + new (zone()) ZoneList<Expression*>(4, zone()); |
| + ZoneList<Expression*>* property_funcs = |
| + new (zone()) ZoneList<Expression*>(4, zone()); |
| + ZoneList<Expression*>* property_infos = |
| + new (zone()) ZoneList<Expression*>(4, zone()); |
| + |
| bool has_seen_constructor = false; |
| Expect(Token::LBRACE, CHECK_OK); |
| @@ -5052,7 +5059,50 @@ ClassLiteral* Parser::ParseClassLiteral(ExpressionClassifier* classifier, |
| constructor->set_raw_name( |
| name != nullptr ? name : ast_value_factory()->empty_string()); |
| } else { |
| - properties->Add(property, zone()); |
| + Expression* value = property->value(); |
| + int property_position = value->position(); |
| + |
| + Expression* property_key; |
| + |
| + if (property_name != nullptr) { |
| + // For static keys, no ToName call is necessary. |
| + if (property->key()->IsPropertyName()) { |
| + property_key = property->key(); |
| + } else { |
| + property_key = |
| + factory()->NewStringLiteral(property_name, property_position); |
| + } |
| + } else { |
| + ZoneList<Expression*>* to_name_args = |
| + new (zone()) ZoneList<Expression*>(1, zone()); |
| + to_name_args->Add(property->key(), zone()); |
| + |
| + property_key = factory()->NewCallRuntime(Runtime::kToName, to_name_args, |
|
Benedikt Meurer
2016/07/19 04:04:27
Nit: Please add a TODO here, that we look into thi
|
| + property_position); |
| + } |
| + |
| + int info = property->is_static() ? kIsStaticMask : 0; |
| + switch (property->kind()) { |
| + case ObjectLiteral::Property::CONSTANT: |
| + case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| + case ObjectLiteral::Property::PROTOTYPE: |
| + UNREACHABLE(); |
| + case ObjectLiteral::Property::COMPUTED: |
| + break; |
| + |
| + case ObjectLiteral::Property::GETTER: |
| + info |= kIsAccessorMask; |
| + break; |
| + |
| + case ObjectLiteral::Property::SETTER: |
| + info |= kIsAccessorMask | kIsSetterMask; |
| + break; |
| + } |
| + |
| + property_names->Add(property_key, zone()); |
| + property_funcs->Add(value, zone()); |
| + property_infos->Add(factory()->NewNumberLiteral(info, kNoSourcePosition), |
| + zone()); |
| } |
| if (fni_ != NULL) fni_->Infer(); |
| @@ -5079,8 +5129,86 @@ ClassLiteral* Parser::ParseClassLiteral(ExpressionClassifier* classifier, |
| proxy->var()->set_initializer_position(end_pos); |
| } |
| - return factory()->NewClassLiteral(block_scope, proxy, extends, constructor, |
| - properties, pos, end_pos); |
| + // Construct a DoExpression representing the class literal. |
| + Block* do_block = factory()->NewBlock(nullptr, 1, false, pos); |
| + do_block->set_scope(scope_); |
| + |
| + // Call DefineClass. It takes seven arguments: |
|
Benedikt Meurer
2016/07/19 04:04:27
I remember when we discussed this, we wanted to ac
Dan Ehrenberg
2016/07/19 04:52:33
The issue here is that the properties that are cre
|
| + // 1. The superclass constructor, or the Hole if not present. |
| + // 2. The constructor function. |
| + // 3. An array of method names. |
| + // 4. An array of said method's corresponding functions. |
| + // 5. An array of flags signalling if they are accessors and/or static. |
| + // 6. The location where the class's source starts. |
| + // 7. The location where the class's source ends. |
| + ZoneList<Expression*>* define_class_args = |
| + new (zone()) ZoneList<Expression*>(7, zone()); |
| + define_class_args->Add(extends != nullptr |
| + ? extends |
| + : factory()->NewTheHoleLiteral(kNoSourcePosition), |
| + zone()); |
| + define_class_args->Add(constructor, zone()); |
| + |
| + int names_idx = function_state_->NextMaterializedLiteralIndex(); |
| + int funcs_idx = function_state_->NextMaterializedLiteralIndex(); |
| + int infos_idx = function_state_->NextMaterializedLiteralIndex(); |
| + |
| + define_class_args->Add( |
|
Benedikt Meurer
2016/07/19 04:04:27
Why do we wrap these into JSArrays? That seems rat
Dan Ehrenberg
2016/07/19 04:52:33
Is there a way to create FixedArrays from the pars
marja
2016/07/19 09:54:34
FixedArray is a heap object, so no. This will be c
|
| + factory()->NewArrayLiteral(property_names, names_idx, kNoSourcePosition), |
| + zone()); |
| + define_class_args->Add( |
| + factory()->NewArrayLiteral(property_funcs, funcs_idx, kNoSourcePosition), |
| + zone()); |
| + define_class_args->Add( |
| + factory()->NewArrayLiteral(property_infos, infos_idx, kNoSourcePosition), |
| + zone()); |
| + |
| + define_class_args->Add(factory()->NewNumberLiteral(pos, kNoSourcePosition), |
| + zone()); |
| + define_class_args->Add( |
| + factory()->NewNumberLiteral(end_pos, kNoSourcePosition), zone()); |
| + |
| + Expression* define_class_call = factory()->NewCallRuntime( |
| + Runtime::kDefineClass, define_class_args, kNoSourcePosition); |
| + |
| + // Set the constructor to have fast properties. |
| + ZoneList<Expression*>* fast_properties_args = |
| + new (zone()) ZoneList<Expression*>(1, zone()); |
| + fast_properties_args->Add(define_class_call, zone()); |
| + |
| + // This call returns its argument, so we can chain it. |
| + Expression* fast_properties_call = factory()->NewCallRuntime( |
| + Runtime::kToFastProperties, fast_properties_args, kNoSourcePosition); |
| + |
| + if (name != nullptr) { |
| + DCHECK_NOT_NULL(proxy); |
| + // Init the variable representing the class name only after evaluating all |
| + // property names. |
| + Expression* name_assignment = factory()->NewAssignment( |
| + Token::INIT, proxy, fast_properties_call, end_pos); |
| + |
| + do_block->statements()->Add( |
| + factory()->NewExpressionStatement(name_assignment, end_pos), zone()); |
| + } else { |
| + do_block->statements()->Add(factory()->NewExpressionStatement( |
| + fast_properties_call, kNoSourcePosition), |
| + zone()); |
| + } |
| + |
| + Variable* result = scope_->NewTemporary(ast_value_factory()->empty_string()); |
| + DoExpression* expr = factory()->NewDoExpression(do_block, result, pos); |
| + |
| + Rewriter::Rewrite(this, expr, |
| + ast_value_factory()); // TODO(bakkot) This is just going to |
| + // turn the final ExpressionStatement |
| + // into an assignment to result; we |
| + // could do that ourselves slightly |
| + // cheaper. |
| + |
| + // This enables function name inference. |
| + expr->set_represented_function(constructor); |
| + |
| + return expr; |
| } |
| @@ -6056,9 +6184,10 @@ void ParserTraits::SetFunctionNameFromPropertyName( |
| function->set_raw_name(name); |
| DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind()); |
| } else { |
| - DCHECK(value->IsClassLiteral()); |
| + DCHECK(value->IsDoExpression()); |
| DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind()); |
| - value->AsClassLiteral()->constructor()->set_raw_name(name); |
| + DCHECK_NOT_NULL(value->AsDoExpression()->represented_function()); |
| + value->AsDoExpression()->represented_function()->set_raw_name(name); |
| } |
| } |
| @@ -6075,8 +6204,9 @@ void ParserTraits::SetFunctionNameFromIdentifierRef(Expression* value, |
| if (function != nullptr) { |
| function->set_raw_name(name); |
| } else { |
| - DCHECK(value->IsClassLiteral()); |
| - value->AsClassLiteral()->constructor()->set_raw_name(name); |
| + DCHECK(value->IsDoExpression()); |
| + DCHECK_NOT_NULL(value->AsDoExpression()->represented_function()); |
| + value->AsDoExpression()->represented_function()->set_raw_name(name); |
| } |
| } |